werift 0.13.7 → 0.14.2-debug0
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/common/src/binary.d.ts +10 -0
- package/lib/common/src/binary.js +83 -1
- package/lib/common/src/binary.js.map +1 -1
- package/lib/dtls/src/context/cipher.d.ts +1 -2
- package/lib/dtls/src/context/cipher.js +69 -68
- package/lib/dtls/src/context/cipher.js.map +1 -1
- package/lib/ice/src/ice.js +10 -4
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/rtp/src/index.d.ts +12 -9
- package/lib/rtp/src/index.js +12 -18
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/processor/jitterBuffer.js +1 -1
- package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
- package/lib/rtp/src/processor/webm.d.ts +5 -1
- package/lib/rtp/src/processor/webm.js +12 -29
- package/lib/rtp/src/processor/webm.js.map +1 -1
- package/lib/rtp/src/rtp/red/encoder.d.ts +14 -0
- package/lib/rtp/src/rtp/red/encoder.js +40 -0
- package/lib/rtp/src/rtp/red/encoder.js.map +1 -0
- package/lib/rtp/src/rtp/{red.d.ts → red/packet.d.ts} +5 -5
- package/lib/rtp/src/rtp/red/packet.js +115 -0
- package/lib/rtp/src/rtp/red/packet.js.map +1 -0
- package/lib/rtp/src/rtp/rtp.d.ts +1 -1
- package/lib/rtp/src/rtp/rtp.js +1 -1
- package/lib/rtp/src/rtp/rtp.js.map +1 -1
- package/lib/sctp/src/sctp.d.ts +2 -1
- package/lib/sctp/src/sctp.js +4 -2
- package/lib/sctp/src/sctp.js.map +1 -1
- package/lib/webrtc/src/const.d.ts +2 -0
- package/lib/webrtc/src/const.js +3 -1
- package/lib/webrtc/src/const.js.map +1 -1
- package/lib/webrtc/src/index.d.ts +1 -0
- package/lib/webrtc/src/index.js +1 -0
- package/lib/webrtc/src/index.js.map +1 -1
- package/lib/webrtc/src/media/parameters.d.ts +1 -1
- package/lib/webrtc/src/media/parameters.js +0 -1
- package/lib/webrtc/src/media/parameters.js.map +1 -1
- package/lib/webrtc/src/media/receiver/red.js +8 -6
- package/lib/webrtc/src/media/receiver/red.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.d.ts +1 -1
- package/lib/webrtc/src/media/rtpReceiver.js +3 -1
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +8 -6
- package/lib/webrtc/src/media/rtpSender.js +21 -28
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +21 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +10 -4
- package/lib/webrtc/src/peerConnection.js +39 -12
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sdp.d.ts +4 -0
- package/lib/webrtc/src/sdp.js +11 -9
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +6 -1
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +1 -0
- package/lib/webrtc/src/transport/sctp.js +5 -1
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/lib/webrtc/src/utils.d.ts +10 -0
- package/lib/webrtc/src/utils.js +8 -1
- package/lib/webrtc/src/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/const.ts +6 -0
- package/src/index.ts +1 -0
- package/src/media/parameters.ts +1 -1
- package/src/media/receiver/red.ts +11 -12
- package/src/media/rtpReceiver.ts +3 -1
- package/src/media/rtpSender.ts +26 -45
- package/src/nonstandard/recorder/writer/webm.ts +3 -0
- package/src/peerConnection.ts +52 -15
- package/src/sdp.ts +10 -8
- package/src/transport/dtls.ts +6 -0
- package/src/transport/sctp.ts +6 -1
- package/src/utils.ts +9 -0
- package/lib/rtp/src/rtp/red.js +0 -104
- package/lib/rtp/src/rtp/red.js.map +0 -1
package/src/media/rtpReceiver.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
RtpHeader,
|
|
17
17
|
RtpPacket,
|
|
18
18
|
} from "../../../rtp/src";
|
|
19
|
+
import { codecParametersFromString } from "..";
|
|
19
20
|
import { RTCDtlsTransport } from "../transport/dtls";
|
|
20
21
|
import { Kind } from "../types/domain";
|
|
21
22
|
import { compactNtp } from "../utils";
|
|
@@ -251,7 +252,8 @@ export class RTCRtpReceiver {
|
|
|
251
252
|
|
|
252
253
|
if (codec.name.toLowerCase() === "rtx") {
|
|
253
254
|
const originalSsrc = this.ssrcByRtx[packet.header.ssrc];
|
|
254
|
-
const
|
|
255
|
+
const codecParams = codecParametersFromString(codec.parameters ?? "");
|
|
256
|
+
const rtxCodec = this.codecs[codecParams["apt"]];
|
|
255
257
|
if (packet.payload.length < 2) return;
|
|
256
258
|
|
|
257
259
|
packet = unwrapRtx(packet, rtxCodec.payloadType, originalSsrc);
|
package/src/media/rtpSender.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
GenericNack,
|
|
17
17
|
PictureLossIndication,
|
|
18
18
|
ReceiverEstimatedMaxBitrate,
|
|
19
|
-
|
|
19
|
+
RedEncoder,
|
|
20
20
|
RtcpPacket,
|
|
21
21
|
RtcpPayloadSpecificFeedback,
|
|
22
22
|
RtcpRrPacket,
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
SourceDescriptionItem,
|
|
31
31
|
TransportWideCC,
|
|
32
32
|
} from "../../../rtp/src";
|
|
33
|
+
import { codecParametersFromString } from "..";
|
|
33
34
|
import { RTCDtlsTransport } from "../transport/dtls";
|
|
34
35
|
import { Kind } from "../types/domain";
|
|
35
36
|
import { compactNtp, milliTime, ntpTime } from "../utils";
|
|
@@ -69,8 +70,9 @@ export class RTCRtpSender {
|
|
|
69
70
|
private repairedRtpStreamId?: string;
|
|
70
71
|
private rtxPayloadType?: number;
|
|
71
72
|
private rtxSequenceNumber = random16();
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
redRedundantPayloadType?: number;
|
|
74
|
+
private _redDistance = 2;
|
|
75
|
+
redEncoder = new RedEncoder(this._redDistance);
|
|
74
76
|
private headerExtensions: RTCRtpHeaderExtensionParameters[] = [];
|
|
75
77
|
private disposeTrack?: () => void;
|
|
76
78
|
|
|
@@ -90,7 +92,7 @@ export class RTCRtpSender {
|
|
|
90
92
|
private timestampOffset = 0;
|
|
91
93
|
private seqOffset = 0;
|
|
92
94
|
private rtpCache: RtpPacket[] = [];
|
|
93
|
-
|
|
95
|
+
codec?: RTCRtpCodecParameters;
|
|
94
96
|
|
|
95
97
|
track?: MediaStreamTrack;
|
|
96
98
|
stopped = false;
|
|
@@ -114,6 +116,14 @@ export class RTCRtpSender {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
get redDistance() {
|
|
120
|
+
return this._redDistance;
|
|
121
|
+
}
|
|
122
|
+
set redDistance(n: number) {
|
|
123
|
+
this._redDistance = n;
|
|
124
|
+
this.redEncoder.distance = n;
|
|
125
|
+
}
|
|
126
|
+
|
|
117
127
|
prepareSend(params: RTCRtpSendParameters) {
|
|
118
128
|
this.cname = params.rtcp?.cname;
|
|
119
129
|
this.mid = params.muxId;
|
|
@@ -126,15 +136,18 @@ export class RTCRtpSender {
|
|
|
126
136
|
this.track.codec = this.codec;
|
|
127
137
|
}
|
|
128
138
|
|
|
129
|
-
params.codecs.forEach((codec
|
|
139
|
+
params.codecs.forEach((codec) => {
|
|
140
|
+
const codecParams = codecParametersFromString(codec.parameters ?? "");
|
|
130
141
|
if (
|
|
131
142
|
codec.name.toLowerCase() === "rtx" &&
|
|
132
|
-
|
|
143
|
+
codecParams["apt"] === this.codec?.payloadType
|
|
133
144
|
) {
|
|
134
145
|
this.rtxPayloadType = codec.payloadType;
|
|
135
146
|
}
|
|
136
147
|
if (codec.name.toLowerCase() === "red") {
|
|
137
|
-
this.redRedundantPayloadType =
|
|
148
|
+
this.redRedundantPayloadType = Number(
|
|
149
|
+
(codec.parameters ?? "").split("/")[0]
|
|
150
|
+
);
|
|
138
151
|
}
|
|
139
152
|
});
|
|
140
153
|
}
|
|
@@ -323,20 +336,12 @@ export class RTCRtpSender {
|
|
|
323
336
|
let rtpPayload = rtp.payload;
|
|
324
337
|
|
|
325
338
|
if (this.redRedundantPayloadType) {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
);
|
|
333
|
-
})
|
|
334
|
-
.filter((p): p is NonNullable<typeof p> => typeof p !== "undefined");
|
|
335
|
-
const red = buildRedPacket(
|
|
336
|
-
redundantPackets,
|
|
337
|
-
this.redRedundantPayloadType,
|
|
338
|
-
rtp
|
|
339
|
-
);
|
|
339
|
+
this.redEncoder.push({
|
|
340
|
+
block: rtpPayload,
|
|
341
|
+
timestamp: header.timestamp,
|
|
342
|
+
blockPT: this.redRedundantPayloadType,
|
|
343
|
+
});
|
|
344
|
+
const red = this.redEncoder.build();
|
|
340
345
|
rtpPayload = red.serialize();
|
|
341
346
|
}
|
|
342
347
|
|
|
@@ -458,27 +463,3 @@ export function wrapRtx(
|
|
|
458
463
|
);
|
|
459
464
|
return rtx;
|
|
460
465
|
}
|
|
461
|
-
|
|
462
|
-
export function buildRedPacket(
|
|
463
|
-
redundantPackets: RtpPacket[],
|
|
464
|
-
blockPT: number,
|
|
465
|
-
presentPacket: RtpPacket
|
|
466
|
-
) {
|
|
467
|
-
const red = new Red();
|
|
468
|
-
redundantPackets.forEach((redundant) => {
|
|
469
|
-
red.payloads.push({
|
|
470
|
-
bin: redundant.payload,
|
|
471
|
-
blockPT,
|
|
472
|
-
timestampOffset: uint32Add(
|
|
473
|
-
presentPacket.header.timestamp,
|
|
474
|
-
-redundant.header.timestamp
|
|
475
|
-
),
|
|
476
|
-
});
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
red.payloads.push({
|
|
480
|
-
bin: presentPacket.payload,
|
|
481
|
-
blockPT,
|
|
482
|
-
});
|
|
483
|
-
return red;
|
|
484
|
-
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
|
|
1
3
|
import { SupportedCodec } from "../../../../../rtp/src/container/webm";
|
|
2
4
|
import {
|
|
3
5
|
JitterBuffer,
|
|
@@ -12,6 +14,7 @@ export class WebmFactory extends MediaWriter {
|
|
|
12
14
|
|
|
13
15
|
start(tracks: MediaStreamTrack[]) {
|
|
14
16
|
this.webm = new WebmOutput(
|
|
17
|
+
fs,
|
|
15
18
|
"./test.webm",
|
|
16
19
|
tracks.map((track, i) => {
|
|
17
20
|
const trackNumber = i + 1;
|
package/src/peerConnection.ts
CHANGED
|
@@ -4,6 +4,7 @@ import Event from "rx.mini";
|
|
|
4
4
|
import * as uuid from "uuid";
|
|
5
5
|
|
|
6
6
|
import { Profile } from "../../dtls/src/context/srtp";
|
|
7
|
+
import { codecParametersFromString, DtlsKeys } from ".";
|
|
7
8
|
import {
|
|
8
9
|
DISCARD_HOST,
|
|
9
10
|
DISCARD_PORT,
|
|
@@ -96,7 +97,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
96
97
|
|
|
97
98
|
private readonly router = new RtpRouter();
|
|
98
99
|
private readonly certificates: RTCCertificate[] = [];
|
|
99
|
-
|
|
100
|
+
sctpRemotePort?: number;
|
|
100
101
|
private seenMid = new Set<string>();
|
|
101
102
|
private currentLocalDescription?: SessionDescription;
|
|
102
103
|
private currentRemoteDescription?: SessionDescription;
|
|
@@ -111,6 +112,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
111
112
|
iceServers,
|
|
112
113
|
iceTransportPolicy,
|
|
113
114
|
icePortRange,
|
|
115
|
+
dtls,
|
|
114
116
|
}: Partial<PeerConfig> = {}) {
|
|
115
117
|
super();
|
|
116
118
|
|
|
@@ -126,15 +128,27 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
126
128
|
if (codecs?.audio) this.configuration.codecs.audio = codecs.audio;
|
|
127
129
|
if (codecs?.video) this.configuration.codecs.video = codecs.video;
|
|
128
130
|
|
|
129
|
-
[
|
|
131
|
+
for (const [i, codecParams] of enumerate([
|
|
130
132
|
...(this.configuration.codecs.audio || []),
|
|
131
133
|
...(this.configuration.codecs.video || []),
|
|
132
|
-
]
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
])) {
|
|
135
|
+
codecParams.payloadType = 96 + i;
|
|
136
|
+
switch (codecParams.name.toLowerCase()) {
|
|
137
|
+
case "rtx":
|
|
138
|
+
{
|
|
139
|
+
codecParams.parameters = `apt=${codecParams.payloadType - 1}`;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
case "red":
|
|
143
|
+
{
|
|
144
|
+
const redundant = codecParams.payloadType + 1;
|
|
145
|
+
codecParams.parameters = `${redundant}/${redundant}`;
|
|
146
|
+
codecParams.payloadType = 63;
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
136
149
|
}
|
|
137
|
-
}
|
|
150
|
+
}
|
|
151
|
+
|
|
138
152
|
if (headerExtensions?.audio)
|
|
139
153
|
this.configuration.headerExtensions.audio = headerExtensions.audio;
|
|
140
154
|
if (headerExtensions?.video)
|
|
@@ -146,6 +160,15 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
146
160
|
v.id = 1 + i;
|
|
147
161
|
});
|
|
148
162
|
|
|
163
|
+
if (dtls) {
|
|
164
|
+
const { keys } = dtls;
|
|
165
|
+
if (keys) {
|
|
166
|
+
this.certificates.push(
|
|
167
|
+
new RTCCertificate(keys.keyPem, keys.certPem, keys.signatureHash)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
149
172
|
this.iceConnectionStateChange.subscribe((state) => {
|
|
150
173
|
switch (state) {
|
|
151
174
|
case "disconnected":
|
|
@@ -576,7 +599,8 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
576
599
|
transceiver.codecs.reduce(
|
|
577
600
|
(acc: { [pt: number]: RTCRtpCodingParameters }, codec) => {
|
|
578
601
|
if (codec.name.toLowerCase() === "rtx") {
|
|
579
|
-
const
|
|
602
|
+
const params = codecParametersFromString(codec.parameters ?? "");
|
|
603
|
+
const apt = acc[params["apt"]];
|
|
580
604
|
if (apt && media.ssrc.length === 2) {
|
|
581
605
|
apt.rtx = new RTCRtpRtxParameters({ ssrc: media.ssrc[1].ssrc });
|
|
582
606
|
}
|
|
@@ -639,7 +663,10 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
639
663
|
if (!existCodec) return false;
|
|
640
664
|
|
|
641
665
|
if (existCodec?.name.toLowerCase() === "rtx") {
|
|
642
|
-
const
|
|
666
|
+
const params = codecParametersFromString(
|
|
667
|
+
existCodec.parameters ?? ""
|
|
668
|
+
);
|
|
669
|
+
const pt = params["apt"];
|
|
643
670
|
const origin = remoteMedia.rtp.codecs.find(
|
|
644
671
|
(c) => c.payloadType === pt
|
|
645
672
|
);
|
|
@@ -711,16 +738,18 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
711
738
|
|
|
712
739
|
transceiver.receiver.setupTWCC(remoteMedia.ssrc[0]?.ssrc);
|
|
713
740
|
} else if (remoteMedia.kind === "application") {
|
|
741
|
+
// # configure sctp
|
|
742
|
+
this.sctpRemotePort = remoteMedia.sctpPort;
|
|
714
743
|
if (!this.sctpTransport) {
|
|
744
|
+
if (!this.sctpRemotePort) {
|
|
745
|
+
throw new Error("sctpRemotePort not exist");
|
|
746
|
+
}
|
|
715
747
|
this.sctpTransport = this.createSctpTransport();
|
|
748
|
+
this.sctpTransport.setRemotePort(this.sctpRemotePort);
|
|
716
749
|
}
|
|
717
|
-
|
|
718
750
|
if (!this.sctpTransport.mid) {
|
|
719
751
|
this.sctpTransport.mid = remoteMedia.rtp.muxId;
|
|
720
752
|
}
|
|
721
|
-
|
|
722
|
-
// # configure sctp
|
|
723
|
-
this.sctpRemotePort = remoteMedia.sctpPort;
|
|
724
753
|
}
|
|
725
754
|
|
|
726
755
|
if (remoteMedia.iceParams && remoteMedia.dtlsParams) {
|
|
@@ -879,7 +908,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
879
908
|
return this.transceivers;
|
|
880
909
|
}
|
|
881
910
|
|
|
882
|
-
getSenders() {
|
|
911
|
+
getSenders(): RTCRtpSender[] {
|
|
883
912
|
return this.getTransceivers().map((t) => t.sender);
|
|
884
913
|
}
|
|
885
914
|
|
|
@@ -888,7 +917,11 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
888
917
|
}
|
|
889
918
|
|
|
890
919
|
// todo fix
|
|
891
|
-
addTrack(
|
|
920
|
+
addTrack(
|
|
921
|
+
track: MediaStreamTrack,
|
|
922
|
+
/**todo impl */
|
|
923
|
+
ms?: MediaStream
|
|
924
|
+
) {
|
|
892
925
|
if (this.isClosed) throw new Error("is closed");
|
|
893
926
|
if (this.getSenders().find((sender) => sender.track?.uuid === track.uuid)) {
|
|
894
927
|
throw new Error("track exist");
|
|
@@ -1185,6 +1218,9 @@ export interface PeerConfig {
|
|
|
1185
1218
|
iceServers: RTCIceServer[];
|
|
1186
1219
|
/**Minimum port and Maximum port must not be the same value */
|
|
1187
1220
|
icePortRange: [number, number] | undefined;
|
|
1221
|
+
dtls: Partial<{
|
|
1222
|
+
keys: DtlsKeys;
|
|
1223
|
+
}>;
|
|
1188
1224
|
}
|
|
1189
1225
|
|
|
1190
1226
|
export const findCodecByMimeType = (
|
|
@@ -1235,6 +1271,7 @@ export const defaultPeerConfig: PeerConfig = {
|
|
|
1235
1271
|
iceTransportPolicy: "all",
|
|
1236
1272
|
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
|
|
1237
1273
|
icePortRange: undefined,
|
|
1274
|
+
dtls: {},
|
|
1238
1275
|
};
|
|
1239
1276
|
|
|
1240
1277
|
export interface RTCTrackEvent {
|
package/src/sdp.ts
CHANGED
|
@@ -223,7 +223,8 @@ export class SessionDescription {
|
|
|
223
223
|
case "sctpmap":
|
|
224
224
|
if (!value) throw new Error();
|
|
225
225
|
const [formatId, formatDesc] = divide(value, " ");
|
|
226
|
-
|
|
226
|
+
currentMedia.sctpMap[parseInt(formatId)] = formatDesc;
|
|
227
|
+
currentMedia.sctpPort = parseInt(formatId);
|
|
227
228
|
break;
|
|
228
229
|
case "sctp-port":
|
|
229
230
|
if (!value) throw new Error();
|
|
@@ -274,7 +275,7 @@ export class SessionDescription {
|
|
|
274
275
|
if (attr === "fmtp") {
|
|
275
276
|
const [formatId, formatDesc] = divide(value, " ");
|
|
276
277
|
const codec = findCodec(Number(formatId))!;
|
|
277
|
-
codec.parameters =
|
|
278
|
+
codec.parameters = formatDesc;
|
|
278
279
|
} else if (attr === "rtcp-fb") {
|
|
279
280
|
const [payloadType, feedbackType, feedbackParam] = value.split(" ");
|
|
280
281
|
currentMedia.rtp.codecs.forEach((codec) => {
|
|
@@ -453,9 +454,8 @@ export class MediaDescription {
|
|
|
453
454
|
lines.push(`a=rtcp-fb:${codec.payloadType} ${value}`);
|
|
454
455
|
});
|
|
455
456
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
lines.push(`a=fmtp:${codec.payloadType} ${params}`);
|
|
457
|
+
if (codec.parameters) {
|
|
458
|
+
lines.push(`a=fmtp:${codec.payloadType} ${codec.parameters}`);
|
|
459
459
|
}
|
|
460
460
|
});
|
|
461
461
|
|
|
@@ -634,9 +634,9 @@ export function addSDPHeader(
|
|
|
634
634
|
description.type = type;
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
function
|
|
637
|
+
export function codecParametersFromString(str: string) {
|
|
638
638
|
const parameters = {};
|
|
639
|
-
|
|
639
|
+
str.split(";").forEach((param) => {
|
|
640
640
|
if (param.includes("=")) {
|
|
641
641
|
const [k, v] = divide(param, "=");
|
|
642
642
|
if (FMTP_INT_PARAMETERS.includes(k)) {
|
|
@@ -651,7 +651,9 @@ function parametersFromSdp(sdp: string) {
|
|
|
651
651
|
return parameters;
|
|
652
652
|
}
|
|
653
653
|
|
|
654
|
-
function
|
|
654
|
+
export function codecParametersToString(parameters: {
|
|
655
|
+
[key: string]: string | number;
|
|
656
|
+
}) {
|
|
655
657
|
const params = Object.entries(parameters).map(([k, v]) => {
|
|
656
658
|
if (v) return `${k}=${v}`;
|
|
657
659
|
else return k;
|
package/src/transport/dtls.ts
CHANGED
|
@@ -261,6 +261,12 @@ export class RTCCertificate {
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
export type DtlsKeys = {
|
|
265
|
+
certPem: string;
|
|
266
|
+
keyPem: string;
|
|
267
|
+
signatureHash: SignatureHash;
|
|
268
|
+
};
|
|
269
|
+
|
|
264
270
|
export class RTCDtlsFingerprint {
|
|
265
271
|
constructor(public algorithm: string, public value: string) {}
|
|
266
272
|
}
|
package/src/transport/sctp.ts
CHANGED
|
@@ -301,6 +301,10 @@ export class RTCSctpTransport {
|
|
|
301
301
|
return new RTCSctpCapabilities(65536);
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
setRemotePort(port: number) {
|
|
305
|
+
this.sctp.setRemotePort(port);
|
|
306
|
+
}
|
|
307
|
+
|
|
304
308
|
async start(remotePort: number) {
|
|
305
309
|
if (this.isServer) {
|
|
306
310
|
this.dataChannelId = 0;
|
|
@@ -309,7 +313,8 @@ export class RTCSctpTransport {
|
|
|
309
313
|
}
|
|
310
314
|
this.sctp.isServer = this.isServer;
|
|
311
315
|
|
|
312
|
-
|
|
316
|
+
this.setRemotePort(remotePort);
|
|
317
|
+
await this.sctp.start();
|
|
313
318
|
}
|
|
314
319
|
|
|
315
320
|
async stop() {
|
package/src/utils.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
uint16Add,
|
|
12
12
|
uint32Add,
|
|
13
13
|
} from "../../common/src";
|
|
14
|
+
import { CipherContext } from "../../dtls/src/context/cipher";
|
|
14
15
|
import { Address } from "../../ice/src";
|
|
15
16
|
import { RtpHeader, RtpPacket } from "../../rtp/src";
|
|
16
17
|
import { Direction, Directions } from "./media/rtpTransceiver";
|
|
@@ -128,3 +129,11 @@ export class RtpBuilder {
|
|
|
128
129
|
return rtp;
|
|
129
130
|
}
|
|
130
131
|
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* @param signatureHash
|
|
136
|
+
* @param namedCurveAlgorithm necessary when use ecdsa
|
|
137
|
+
*/
|
|
138
|
+
export const createSelfSignedCertificate =
|
|
139
|
+
CipherContext.createSelfSignedCertificateWithKey;
|
package/lib/rtp/src/rtp/red.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// rfc2198
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.RedHeader = exports.Red = void 0;
|
|
5
|
-
const src_1 = require("../../../common/src");
|
|
6
|
-
// 0 1 2 3
|
|
7
|
-
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
8
|
-
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
9
|
-
// |F| block PT | timestamp offset | block length |
|
|
10
|
-
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
11
|
-
// 0 1 2 3 4 5 6 7
|
|
12
|
-
// +-+-+-+-+-+-+-+-+
|
|
13
|
-
// |0| Block PT |
|
|
14
|
-
// +-+-+-+-+-+-+-+-+
|
|
15
|
-
class Red {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.payloads = [];
|
|
18
|
-
}
|
|
19
|
-
static deSerialize(buf) {
|
|
20
|
-
const red = new Red();
|
|
21
|
-
let offset = 0;
|
|
22
|
-
[red.header, offset] = RedHeader.deSerialize(buf);
|
|
23
|
-
red.header.payloads.forEach(({ blockLength, timestampOffset, blockPT }) => {
|
|
24
|
-
if (blockLength && timestampOffset) {
|
|
25
|
-
const payload = buf.slice(offset, offset + blockLength);
|
|
26
|
-
red.payloads.push({ bin: payload, blockPT, timestampOffset });
|
|
27
|
-
offset += blockLength;
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
const payload = buf.slice(offset);
|
|
31
|
-
red.payloads.push({ bin: payload, blockPT });
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
return red;
|
|
35
|
-
}
|
|
36
|
-
serialize() {
|
|
37
|
-
this.header = new RedHeader();
|
|
38
|
-
for (const { timestampOffset, blockPT, bin } of this.payloads) {
|
|
39
|
-
if (timestampOffset) {
|
|
40
|
-
this.header.payloads.push({
|
|
41
|
-
fBit: 1,
|
|
42
|
-
blockPT,
|
|
43
|
-
blockLength: bin.length,
|
|
44
|
-
timestampOffset,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
this.header.payloads.push({ fBit: 0, blockPT });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
let buf = this.header.serialize();
|
|
52
|
-
for (const { bin } of this.payloads) {
|
|
53
|
-
buf = Buffer.concat([buf, bin]);
|
|
54
|
-
}
|
|
55
|
-
return buf;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
exports.Red = Red;
|
|
59
|
-
class RedHeader {
|
|
60
|
-
constructor() {
|
|
61
|
-
this.payloads = [];
|
|
62
|
-
}
|
|
63
|
-
static deSerialize(buf) {
|
|
64
|
-
let offset = 0;
|
|
65
|
-
const header = new RedHeader();
|
|
66
|
-
for (;;) {
|
|
67
|
-
const payload = {};
|
|
68
|
-
header.payloads.push(payload);
|
|
69
|
-
payload.fBit = (0, src_1.getBit)(buf[offset], 0);
|
|
70
|
-
payload.blockPT = (0, src_1.getBit)(buf[offset], 1, 7);
|
|
71
|
-
offset++;
|
|
72
|
-
if (payload.fBit === 0) {
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
payload.timestampOffset =
|
|
76
|
-
(buf[offset] << 6) + ((buf[offset + 1] & 0b11111100) >> 2);
|
|
77
|
-
offset++;
|
|
78
|
-
payload.blockLength = ((buf[offset] & 0b11) << 8) + buf[offset + 1];
|
|
79
|
-
offset += 2;
|
|
80
|
-
}
|
|
81
|
-
return [header, offset];
|
|
82
|
-
}
|
|
83
|
-
serialize() {
|
|
84
|
-
let buf = Buffer.alloc(0);
|
|
85
|
-
for (const payload of this.payloads) {
|
|
86
|
-
if (payload.timestampOffset && payload.blockLength) {
|
|
87
|
-
const a = new src_1.BitWriter2(8)
|
|
88
|
-
.set(payload.fBit)
|
|
89
|
-
.set(payload.blockPT, 7).buffer;
|
|
90
|
-
const b = Buffer.alloc(3);
|
|
91
|
-
b.writeUInt16BE((payload.timestampOffset << 2) | (payload.blockLength >> 8));
|
|
92
|
-
b.writeUInt8(payload.blockLength & 0b11111111, 2);
|
|
93
|
-
buf = Buffer.concat([buf, a, b]);
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
const chunk = new src_1.BitWriter2(8).set(0).set(payload.blockPT, 7).buffer;
|
|
97
|
-
buf = Buffer.concat([buf, chunk]);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return buf;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
exports.RedHeader = RedHeader;
|
|
104
|
-
//# sourceMappingURL=red.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"red.js","sourceRoot":"","sources":["../../../../../rtp/src/rtp/red.ts"],"names":[],"mappings":"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","sourcesContent":["// rfc2198\n\nimport { BitWriter2, getBit } from \"../../../common/src\";\n\n// 0 1 2 3\n// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n// |F| block PT | timestamp offset | block length |\n// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n// 0 1 2 3 4 5 6 7\n// +-+-+-+-+-+-+-+-+\n// |0| Block PT |\n// +-+-+-+-+-+-+-+-+\n\nexport class Red {\n header!: RedHeader;\n payloads: {\n bin: Buffer;\n blockPT: number;\n /**14bit */\n timestampOffset?: number;\n }[] = [];\n\n static deSerialize(buf: Buffer) {\n const red = new Red();\n let offset = 0;\n [red.header, offset] = RedHeader.deSerialize(buf);\n\n red.header.payloads.forEach(({ blockLength, timestampOffset, blockPT }) => {\n if (blockLength && timestampOffset) {\n const payload = buf.slice(offset, offset + blockLength);\n red.payloads.push({ bin: payload, blockPT, timestampOffset });\n offset += blockLength;\n } else {\n const payload = buf.slice(offset);\n red.payloads.push({ bin: payload, blockPT });\n }\n });\n\n return red;\n }\n\n serialize() {\n this.header = new RedHeader();\n\n for (const { timestampOffset, blockPT, bin } of this.payloads) {\n if (timestampOffset) {\n this.header.payloads.push({\n fBit: 1,\n blockPT,\n blockLength: bin.length,\n timestampOffset,\n });\n } else {\n this.header.payloads.push({ fBit: 0, blockPT });\n }\n }\n\n let buf = this.header.serialize();\n for (const { bin } of this.payloads) {\n buf = Buffer.concat([buf, bin]);\n }\n\n return buf;\n }\n}\n\nexport class RedHeader {\n payloads: RedHeaderPayload[] = [];\n\n static deSerialize(buf: Buffer) {\n let offset = 0;\n const header = new RedHeader();\n\n for (;;) {\n const payload: RedHeaderPayload = {} as any;\n header.payloads.push(payload);\n payload.fBit = getBit(buf[offset], 0);\n payload.blockPT = getBit(buf[offset], 1, 7);\n offset++;\n\n if (payload.fBit === 0) {\n break;\n }\n\n payload.timestampOffset =\n (buf[offset] << 6) + ((buf[offset + 1] & 0b11111100) >> 2);\n offset++;\n payload.blockLength = ((buf[offset] & 0b11) << 8) + buf[offset + 1];\n offset += 2;\n }\n\n return [header, offset] as const;\n }\n\n serialize() {\n let buf = Buffer.alloc(0);\n for (const payload of this.payloads) {\n if (payload.timestampOffset && payload.blockLength) {\n const a = new BitWriter2(8)\n .set(payload.fBit)\n .set(payload.blockPT, 7).buffer;\n const b = Buffer.alloc(3);\n b.writeUInt16BE(\n (payload.timestampOffset << 2) | (payload.blockLength >> 8)\n );\n b.writeUInt8(payload.blockLength & 0b11111111, 2);\n\n buf = Buffer.concat([buf, a, b]);\n } else {\n const chunk = new BitWriter2(8).set(0).set(payload.blockPT, 7).buffer;\n buf = Buffer.concat([buf, chunk]);\n }\n }\n return buf;\n }\n}\n\ninterface RedHeaderPayload {\n fBit: number;\n blockPT: number;\n /**14bit */\n timestampOffset?: number;\n /**10bit */\n blockLength?: number;\n}\n"]}
|