werift 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dtls/src/server.js +3 -0
- package/lib/dtls/src/server.js.map +1 -1
- package/lib/dtls/src/socket.d.ts +4 -3
- package/lib/dtls/src/socket.js +9 -0
- package/lib/dtls/src/socket.js.map +1 -1
- package/lib/rtp/src/codec/av1.js +4 -4
- package/lib/rtp/src/codec/av1.js.map +1 -1
- package/lib/rtp/src/codec/h264.js +1 -1
- package/lib/rtp/src/codec/h264.js.map +1 -1
- package/lib/rtp/src/codec/index.d.ts +0 -2
- package/lib/rtp/src/codec/index.js +1 -21
- package/lib/rtp/src/codec/index.js.map +1 -1
- package/lib/rtp/src/codec/vp8.js +1 -1
- package/lib/rtp/src/codec/vp8.js.map +1 -1
- package/lib/rtp/src/codec/vp9.js +1 -1
- package/lib/rtp/src/codec/vp9.js.map +1 -1
- package/lib/rtp/src/processor/depacketizer.d.ts +2 -1
- package/lib/rtp/src/processor/depacketizer.js.map +1 -1
- package/lib/rtp/src/processor/interface.d.ts +3 -0
- package/lib/rtp/src/processor/interface.js +3 -0
- package/lib/rtp/src/processor/interface.js.map +1 -0
- package/lib/rtp/src/processor/jitterBuffer.d.ts +2 -1
- package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
- package/lib/rtp/src/rtcp/rtpfb/nack.js +11 -11
- package/lib/rtp/src/rtcp/rtpfb/nack.js.map +1 -1
- package/lib/rtp/src/rtp/red/packet.js +3 -3
- package/lib/rtp/src/rtp/red/packet.js.map +1 -1
- package/lib/webrtc/src/media/receiver/nack.d.ts +4 -4
- package/lib/webrtc/src/media/receiver/nack.js +21 -20
- package/lib/webrtc/src/media/receiver/nack.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +1 -1
- package/lib/webrtc/src/media/rtpSender.js +7 -1
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +1 -0
- package/lib/webrtc/src/peerConnection.js +74 -23
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sdp.js +21 -0
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +1 -0
- package/lib/webrtc/src/transport/dtls.js +13 -6
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/package.json +1 -1
- package/src/media/receiver/nack.ts +26 -23
- package/src/media/rtpSender.ts +13 -4
- package/src/peerConnection.ts +92 -31
- package/src/sdp.ts +30 -0
- package/src/transport/dtls.ts +15 -6
package/src/peerConnection.ts
CHANGED
|
@@ -87,6 +87,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
87
87
|
signalingState: RTCSignalingState = "stable";
|
|
88
88
|
negotiationneeded = false;
|
|
89
89
|
readonly transceivers: RTCRtpTransceiver[] = [];
|
|
90
|
+
candidatesSent = new Set<string>();
|
|
90
91
|
|
|
91
92
|
readonly iceGatheringStateChange = new Event<[IceGathererState]>();
|
|
92
93
|
readonly iceConnectionStateChange = new Event<[RTCIceConnectionState]>();
|
|
@@ -298,6 +299,10 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
298
299
|
} else {
|
|
299
300
|
const transceiver = this.getTransceiverByMid(mid);
|
|
300
301
|
if (!transceiver) {
|
|
302
|
+
if (m.direction === "inactive") {
|
|
303
|
+
description.media.push(m);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
301
306
|
throw new Error("transceiver not found");
|
|
302
307
|
}
|
|
303
308
|
transceiver.mLineIndex = i;
|
|
@@ -315,17 +320,20 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
315
320
|
this.transceivers
|
|
316
321
|
.filter((t) => !description.media.find((m) => m.rtp.muxId === t.mid))
|
|
317
322
|
.forEach((transceiver) => {
|
|
318
|
-
transceiver.mLineIndex = description.media.length;
|
|
319
323
|
if (transceiver.mid == undefined) {
|
|
320
324
|
transceiver.mid = allocateMid(this.seenMid, "av");
|
|
321
325
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
transceiver.direction
|
|
327
|
-
)
|
|
326
|
+
const mediaDescription = createMediaDescriptionForTransceiver(
|
|
327
|
+
transceiver,
|
|
328
|
+
this.cname,
|
|
329
|
+
transceiver.direction
|
|
328
330
|
);
|
|
331
|
+
if (transceiver.mLineIndex === undefined) {
|
|
332
|
+
transceiver.mLineIndex = description.media.length;
|
|
333
|
+
description.media.push(mediaDescription);
|
|
334
|
+
} else {
|
|
335
|
+
description.media[transceiver.mLineIndex] = mediaDescription;
|
|
336
|
+
}
|
|
329
337
|
});
|
|
330
338
|
|
|
331
339
|
if (
|
|
@@ -341,10 +349,12 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
341
349
|
|
|
342
350
|
if (this.config.bundlePolicy !== "disable") {
|
|
343
351
|
const mids = description.media
|
|
344
|
-
.map((m) => m.rtp.muxId)
|
|
352
|
+
.map((m) => (m.direction !== "inactive" ? m.rtp.muxId : undefined))
|
|
345
353
|
.filter((v) => v) as string[];
|
|
346
|
-
|
|
347
|
-
|
|
354
|
+
if (mids.length) {
|
|
355
|
+
const bundle = new GroupDescription("BUNDLE", mids);
|
|
356
|
+
description.group.push(bundle);
|
|
357
|
+
}
|
|
348
358
|
}
|
|
349
359
|
|
|
350
360
|
return description;
|
|
@@ -408,13 +418,17 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
408
418
|
return;
|
|
409
419
|
}
|
|
410
420
|
|
|
411
|
-
if (transceiver.
|
|
412
|
-
transceiver.direction = "recvonly";
|
|
413
|
-
} else if (
|
|
414
|
-
transceiver.direction === "sendonly" ||
|
|
415
|
-
transceiver.direction === "recvonly"
|
|
416
|
-
) {
|
|
421
|
+
if (transceiver.stopping || transceiver.stopped) {
|
|
417
422
|
transceiver.direction = "inactive";
|
|
423
|
+
} else {
|
|
424
|
+
if (transceiver.direction === "sendrecv") {
|
|
425
|
+
transceiver.direction = "recvonly";
|
|
426
|
+
} else if (
|
|
427
|
+
transceiver.direction === "sendonly" ||
|
|
428
|
+
transceiver.direction === "recvonly"
|
|
429
|
+
) {
|
|
430
|
+
transceiver.direction = "inactive";
|
|
431
|
+
}
|
|
418
432
|
}
|
|
419
433
|
this.needNegotiation();
|
|
420
434
|
}
|
|
@@ -491,6 +505,16 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
491
505
|
|
|
492
506
|
candidate.foundation = "candidate:" + candidate.foundation;
|
|
493
507
|
|
|
508
|
+
// prevent ice candidates that have already been sent from being being resent
|
|
509
|
+
// when the connection is renegotiated during a later setLocalDescription call.
|
|
510
|
+
if (candidate.sdpMid) {
|
|
511
|
+
const candidateKey = `${candidate.foundation}:${candidate.sdpMid}`;
|
|
512
|
+
if (this.candidatesSent.has(candidateKey)) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
this.candidatesSent.add(candidateKey);
|
|
516
|
+
}
|
|
517
|
+
|
|
494
518
|
this.onIceCandidate.execute(candidate.toJSON());
|
|
495
519
|
if (this.onicecandidate) {
|
|
496
520
|
this.onicecandidate({ candidate: candidate.toJSON() });
|
|
@@ -800,14 +824,19 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
800
824
|
|
|
801
825
|
// # apply description
|
|
802
826
|
|
|
803
|
-
const
|
|
827
|
+
const matchTransceiverWithMedia = (
|
|
828
|
+
transceiver: RTCRtpTransceiver,
|
|
829
|
+
media: MediaDescription
|
|
830
|
+
) =>
|
|
831
|
+
transceiver.kind === media.kind &&
|
|
832
|
+
[undefined, media.rtp.muxId].includes(transceiver.mid);
|
|
833
|
+
|
|
834
|
+
let transports = enumerate(remoteSdp.media).map(([i, remoteMedia]) => {
|
|
804
835
|
let dtlsTransport: RTCDtlsTransport | undefined;
|
|
805
836
|
|
|
806
837
|
if (["audio", "video"].includes(remoteMedia.kind)) {
|
|
807
|
-
let transceiver = this.transceivers.find(
|
|
808
|
-
(t)
|
|
809
|
-
t.kind === remoteMedia.kind &&
|
|
810
|
-
[undefined, remoteMedia.rtp.muxId].includes(t.mid)
|
|
838
|
+
let transceiver = this.transceivers.find((t) =>
|
|
839
|
+
matchTransceiverWithMedia(t, remoteMedia)
|
|
811
840
|
);
|
|
812
841
|
if (!transceiver) {
|
|
813
842
|
// create remote transceiver
|
|
@@ -816,6 +845,12 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
816
845
|
});
|
|
817
846
|
transceiver.mid = remoteMedia.rtp.muxId;
|
|
818
847
|
this.onRemoteTransceiverAdded.execute(transceiver);
|
|
848
|
+
} else {
|
|
849
|
+
if (transceiver.direction === "inactive" && transceiver.stopping) {
|
|
850
|
+
transceiver.stopped = true;
|
|
851
|
+
transceiver.currentDirection = "inactive";
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
819
854
|
}
|
|
820
855
|
|
|
821
856
|
if (this.remoteIsBundled) {
|
|
@@ -876,7 +911,25 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
876
911
|
remoteMedia.dtlsParams.role === "client" ? "server" : "client";
|
|
877
912
|
}
|
|
878
913
|
return iceTransport;
|
|
879
|
-
});
|
|
914
|
+
}) as RTCIceTransport[];
|
|
915
|
+
|
|
916
|
+
// filter out inactive transports
|
|
917
|
+
transports = transports.filter((iceTransport) => !!iceTransport);
|
|
918
|
+
|
|
919
|
+
const removedTransceivers = this.transceivers.filter(
|
|
920
|
+
(t) =>
|
|
921
|
+
remoteSdp.media.find((m) => matchTransceiverWithMedia(t, m)) ==
|
|
922
|
+
undefined
|
|
923
|
+
);
|
|
924
|
+
|
|
925
|
+
if (sessionDescription.type === "answer") {
|
|
926
|
+
for (const transceiver of removedTransceivers) {
|
|
927
|
+
// todo: handle answer side transceiver removal work.
|
|
928
|
+
// event should trigger to notify media source to stop.
|
|
929
|
+
transceiver.stop();
|
|
930
|
+
transceiver.stopped = true;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
880
933
|
|
|
881
934
|
if (remoteSdp.type === "offer") {
|
|
882
935
|
this.setSignalingState("have-remote-offer");
|
|
@@ -1107,7 +1160,20 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1107
1160
|
transceiver.options = options;
|
|
1108
1161
|
this.router.registerRtpSender(transceiver.sender);
|
|
1109
1162
|
|
|
1110
|
-
|
|
1163
|
+
// reuse inactive
|
|
1164
|
+
const inactiveTransceiverIndex = this.transceivers.findIndex(
|
|
1165
|
+
(t) => t.currentDirection === "inactive"
|
|
1166
|
+
);
|
|
1167
|
+
const inactiveTransceiver = this.transceivers.find(
|
|
1168
|
+
(t) => t.currentDirection === "inactive"
|
|
1169
|
+
)!;
|
|
1170
|
+
if (inactiveTransceiverIndex > -1) {
|
|
1171
|
+
this.transceivers[inactiveTransceiverIndex] = transceiver;
|
|
1172
|
+
transceiver.mLineIndex = inactiveTransceiver.mLineIndex;
|
|
1173
|
+
inactiveTransceiver.currentDirection = "stopped";
|
|
1174
|
+
} else {
|
|
1175
|
+
this.transceivers.push(transceiver);
|
|
1176
|
+
}
|
|
1111
1177
|
this.onTransceiverAdded.execute(transceiver);
|
|
1112
1178
|
|
|
1113
1179
|
this.updateIceConnectionState();
|
|
@@ -1471,17 +1537,12 @@ export function addTransportDescription(
|
|
|
1471
1537
|
media.iceParams = iceGatherer.localParameters;
|
|
1472
1538
|
media.iceOptions = "trickle";
|
|
1473
1539
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
media.host = candidate.ip;
|
|
1477
|
-
media.port = candidate.port;
|
|
1478
|
-
} else {
|
|
1479
|
-
media.host = DISCARD_HOST;
|
|
1480
|
-
media.port = DISCARD_PORT;
|
|
1481
|
-
}
|
|
1540
|
+
media.host = DISCARD_HOST;
|
|
1541
|
+
media.port = DISCARD_PORT;
|
|
1482
1542
|
|
|
1483
1543
|
if (media.direction === "inactive") {
|
|
1484
1544
|
media.port = 0;
|
|
1545
|
+
media.msid = undefined;
|
|
1485
1546
|
}
|
|
1486
1547
|
|
|
1487
1548
|
if (!media.dtlsParams) {
|
package/src/sdp.ts
CHANGED
|
@@ -97,6 +97,8 @@ export class SessionDescription {
|
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
+
const bundle = session.group.find((g) => g.semantic === "BUNDLE");
|
|
101
|
+
|
|
100
102
|
mediaGroups.forEach((mediaLines) => {
|
|
101
103
|
const target = mediaLines[0];
|
|
102
104
|
const m = target.match(/^m=([^ ]+) ([0-9]+) ([A-Z/]+) (.+)/);
|
|
@@ -121,11 +123,13 @@ export class SessionDescription {
|
|
|
121
123
|
[...session.dtlsFingerprints],
|
|
122
124
|
session.dtlsRole
|
|
123
125
|
);
|
|
126
|
+
|
|
124
127
|
currentMedia.iceParams = new RTCIceParameters({
|
|
125
128
|
iceLite: session.iceLite,
|
|
126
129
|
usernameFragment: session.iceUsernameFragment,
|
|
127
130
|
password: session.icePassword,
|
|
128
131
|
});
|
|
132
|
+
|
|
129
133
|
currentMedia.iceOptions = session.iceOptions;
|
|
130
134
|
session.media.push(currentMedia);
|
|
131
135
|
|
|
@@ -262,6 +266,32 @@ export class SessionDescription {
|
|
|
262
266
|
}
|
|
263
267
|
});
|
|
264
268
|
|
|
269
|
+
if (
|
|
270
|
+
!currentMedia.iceParams.usernameFragment ||
|
|
271
|
+
!currentMedia.iceParams.password
|
|
272
|
+
) {
|
|
273
|
+
if (
|
|
274
|
+
currentMedia.rtp.muxId &&
|
|
275
|
+
bundle &&
|
|
276
|
+
bundle.items.includes(currentMedia.rtp.muxId)
|
|
277
|
+
) {
|
|
278
|
+
for (let i = 0; i < bundle.items.length; i++) {
|
|
279
|
+
if (!bundle.items.includes(i.toString())) continue;
|
|
280
|
+
const check = session.media[i];
|
|
281
|
+
if (
|
|
282
|
+
check.iceParams &&
|
|
283
|
+
check.iceParams.usernameFragment &&
|
|
284
|
+
check.iceParams.password
|
|
285
|
+
) {
|
|
286
|
+
currentMedia.iceParams = {
|
|
287
|
+
...check.iceParams,
|
|
288
|
+
};
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
265
295
|
if (!currentMedia.dtlsParams.role) {
|
|
266
296
|
currentMedia.dtlsParams = undefined;
|
|
267
297
|
}
|
package/src/transport/dtls.ts
CHANGED
|
@@ -134,11 +134,11 @@ export class RTCDtlsTransport {
|
|
|
134
134
|
}
|
|
135
135
|
this.dataReceiver(buf);
|
|
136
136
|
});
|
|
137
|
-
this.dtls.onClose.
|
|
137
|
+
this.dtls.onClose.subscribe(() => {
|
|
138
138
|
this.setState("closed");
|
|
139
139
|
});
|
|
140
140
|
this.dtls.onConnect.once(r);
|
|
141
|
-
this.dtls.onError.
|
|
141
|
+
this.dtls.onError.subscribe((error) => {
|
|
142
142
|
this.setState("failed");
|
|
143
143
|
log("dtls failed", error);
|
|
144
144
|
});
|
|
@@ -155,16 +155,18 @@ export class RTCDtlsTransport {
|
|
|
155
155
|
if (this.srtpProfiles.length > 0) {
|
|
156
156
|
this.startSrtp();
|
|
157
157
|
}
|
|
158
|
+
this.dtls!.onConnect.subscribe(() => {
|
|
159
|
+
this.updateSrtpSession();
|
|
160
|
+
this.setState("connected");
|
|
161
|
+
});
|
|
158
162
|
this.setState("connected");
|
|
163
|
+
|
|
159
164
|
log("dtls connected");
|
|
160
165
|
}
|
|
161
166
|
|
|
162
|
-
|
|
167
|
+
updateSrtpSession() {
|
|
163
168
|
if (!this.dtls) throw new Error();
|
|
164
169
|
|
|
165
|
-
if (this.srtpStarted) return;
|
|
166
|
-
this.srtpStarted = true;
|
|
167
|
-
|
|
168
170
|
const profile = this.dtls.srtp.srtpProfile;
|
|
169
171
|
if (!profile) {
|
|
170
172
|
throw new Error("need srtpProfile");
|
|
@@ -185,6 +187,13 @@ export class RTCDtlsTransport {
|
|
|
185
187
|
};
|
|
186
188
|
this.srtp = new SrtpSession(config);
|
|
187
189
|
this.srtcp = new SrtcpSession(config);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
startSrtp() {
|
|
193
|
+
if (this.srtpStarted) return;
|
|
194
|
+
this.srtpStarted = true;
|
|
195
|
+
|
|
196
|
+
this.updateSrtpSession();
|
|
188
197
|
|
|
189
198
|
this.iceTransport.connection.onData.subscribe((data) => {
|
|
190
199
|
if (
|