werift 0.24.3 → 0.25.0-alpha.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/README.md +116 -113
- package/lib/common/src/event.js +2 -1
- package/lib/common/src/event.js.map +1 -1
- package/lib/common/src/transport.d.ts +22 -2
- package/lib/common/src/transport.js +84 -26
- package/lib/common/src/transport.js.map +1 -1
- package/lib/ice/src/exceptions.d.ts +9 -0
- package/lib/ice/src/exceptions.js +23 -1
- package/lib/ice/src/exceptions.js.map +1 -1
- package/lib/ice/src/ice.d.ts +40 -0
- package/lib/ice/src/ice.js +194 -28
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/iceBase.d.ts +26 -0
- package/lib/ice/src/iceBase.js.map +1 -1
- package/lib/ice/src/stun/const.d.ts +7 -0
- package/lib/ice/src/stun/const.js +8 -0
- package/lib/ice/src/stun/const.js.map +1 -1
- package/lib/ice/src/stun/protocol.js +1 -4
- package/lib/ice/src/stun/protocol.js.map +1 -1
- package/lib/ice/src/stun/tcpProtocol.d.ts +7 -1
- package/lib/ice/src/stun/tcpProtocol.js +65 -14
- package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
- package/lib/ice/src/stun/transaction.d.ts +12 -1
- package/lib/ice/src/stun/transaction.js +37 -4
- package/lib/ice/src/stun/transaction.js.map +1 -1
- package/lib/ice/src/turn/protocol.d.ts +79 -22
- package/lib/ice/src/turn/protocol.js +282 -78
- package/lib/ice/src/turn/protocol.js.map +1 -1
- package/lib/ice/src/types/model.d.ts +8 -0
- package/lib/ice/src/types/model.js.map +1 -1
- package/lib/index.mjs +5646 -3451
- package/lib/nonstandard/index.mjs +287 -1004
- package/lib/polyfill/dom.mjs +23794 -0
- package/lib/polyfill/index.mjs +23794 -0
- package/lib/rtp/src/extra/container/mp4/container.js +12 -4
- package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
- package/lib/rtp/src/extra/processor/mp4.js +8 -3
- package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
- package/lib/rtp/src/extra/processor/mp4Callback.js +3 -1
- package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
- package/lib/sctp/src/chunk.d.ts +5 -0
- package/lib/sctp/src/chunk.js +16 -11
- package/lib/sctp/src/chunk.js.map +1 -1
- package/lib/sctp/src/index.d.ts +3 -1
- package/lib/sctp/src/index.js +10 -1
- package/lib/sctp/src/index.js.map +1 -1
- package/lib/sctp/src/sctp.d.ts +12 -3
- package/lib/sctp/src/sctp.js +51 -18
- package/lib/sctp/src/sctp.js.map +1 -1
- package/lib/webrtc/src/const.js +2 -0
- package/lib/webrtc/src/const.js.map +1 -1
- package/lib/webrtc/src/errors.d.ts +9 -1
- package/lib/webrtc/src/errors.js +19 -0
- package/lib/webrtc/src/errors.js.map +1 -1
- package/lib/webrtc/src/media/codec.d.ts +5 -0
- package/lib/webrtc/src/media/codec.js +21 -0
- package/lib/webrtc/src/media/codec.js.map +1 -1
- package/lib/webrtc/src/media/codecCompatibility.d.ts +23 -0
- package/lib/webrtc/src/media/codecCompatibility.js +138 -0
- package/lib/webrtc/src/media/codecCompatibility.js.map +1 -0
- package/lib/webrtc/src/media/index.d.ts +1 -0
- package/lib/webrtc/src/media/index.js +1 -0
- package/lib/webrtc/src/media/index.js.map +1 -1
- package/lib/webrtc/src/media/router.d.ts +2 -0
- package/lib/webrtc/src/media/router.js +23 -3
- package/lib/webrtc/src/media/router.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.d.ts +12 -0
- package/lib/webrtc/src/media/rtpReceiver.js +35 -0
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +65 -4
- package/lib/webrtc/src/media/rtpSender.js +264 -35
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.d.ts +42 -0
- package/lib/webrtc/src/media/rtpTransceiver.js +157 -4
- package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
- package/lib/webrtc/src/media/track.d.ts +29 -1
- package/lib/webrtc/src/media/track.js +164 -5
- package/lib/webrtc/src/media/track.js.map +1 -1
- package/lib/webrtc/src/nonstandard/index.d.ts +0 -1
- package/lib/webrtc/src/nonstandard/index.js +0 -1
- package/lib/webrtc/src/nonstandard/index.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +2 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/nonstandard/userMedia.d.ts +1 -2
- package/lib/webrtc/src/nonstandard/userMedia.js +30 -14
- package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +127 -5
- package/lib/webrtc/src/peerConnection.js +629 -143
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/polyfill/api.d.ts +14 -0
- package/lib/webrtc/src/polyfill/api.js +23 -0
- package/lib/webrtc/src/polyfill/api.js.map +1 -0
- package/lib/webrtc/src/polyfill/browserIdentity.d.ts +11 -0
- package/lib/webrtc/src/polyfill/browserIdentity.js +59 -0
- package/lib/webrtc/src/polyfill/browserIdentity.js.map +1 -0
- package/lib/webrtc/src/polyfill/dom.d.ts +11 -0
- package/lib/webrtc/src/polyfill/dom.js +18 -0
- package/lib/webrtc/src/polyfill/dom.js.map +1 -0
- package/lib/webrtc/src/polyfill/existingMediaDevices.d.ts +2 -0
- package/lib/webrtc/src/polyfill/existingMediaDevices.js +22 -0
- package/lib/webrtc/src/polyfill/existingMediaDevices.js.map +1 -0
- package/lib/webrtc/src/polyfill/globals.d.ts +28 -0
- package/lib/webrtc/src/polyfill/globals.js +3 -0
- package/lib/webrtc/src/polyfill/globals.js.map +1 -0
- package/lib/webrtc/src/polyfill/index.d.ts +2 -0
- package/lib/webrtc/src/polyfill/index.js +19 -0
- package/lib/webrtc/src/polyfill/index.js.map +1 -0
- package/lib/webrtc/src/polyfill/install.d.ts +13 -0
- package/lib/webrtc/src/polyfill/install.js +266 -0
- package/lib/webrtc/src/polyfill/install.js.map +1 -0
- package/lib/webrtc/src/polyfill/mediaDevices.d.ts +38 -0
- package/lib/webrtc/src/polyfill/mediaDevices.js +228 -0
- package/lib/webrtc/src/polyfill/mediaDevices.js.map +1 -0
- package/lib/webrtc/src/polyfill/mediaRegister.d.ts +51 -0
- package/lib/webrtc/src/polyfill/mediaRegister.js +14 -0
- package/lib/webrtc/src/polyfill/mediaRegister.js.map +1 -0
- package/lib/webrtc/src/polyfill/peerConnectionConfig.d.ts +3 -0
- package/lib/webrtc/src/polyfill/peerConnectionConfig.js +52 -0
- package/lib/webrtc/src/polyfill/peerConnectionConfig.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/callback.d.ts +16 -0
- package/lib/webrtc/src/polyfill/registers/callback.js +57 -0
- package/lib/webrtc/src/polyfill/registers/callback.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/empty.d.ts +2 -0
- package/lib/webrtc/src/polyfill/registers/empty.js +28 -0
- package/lib/webrtc/src/polyfill/registers/empty.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/mp4Webm.d.ts +36 -0
- package/lib/webrtc/src/polyfill/registers/mp4Webm.js +242 -0
- package/lib/webrtc/src/polyfill/registers/mp4Webm.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/rtpRtcp.d.ts +17 -0
- package/lib/webrtc/src/polyfill/registers/rtpRtcp.js +143 -0
- package/lib/webrtc/src/polyfill/registers/rtpRtcp.js.map +1 -0
- package/lib/webrtc/src/polyfill/rtcSessionDescription.d.ts +18 -0
- package/lib/webrtc/src/polyfill/rtcSessionDescription.js +36 -0
- package/lib/webrtc/src/polyfill/rtcSessionDescription.js.map +1 -0
- package/lib/webrtc/src/polyfill/rtpCodec.d.ts +17 -0
- package/lib/webrtc/src/polyfill/rtpCodec.js +93 -0
- package/lib/webrtc/src/polyfill/rtpCodec.js.map +1 -0
- package/lib/webrtc/src/polyfill/selectSettings.d.ts +31 -0
- package/lib/webrtc/src/polyfill/selectSettings.js +156 -0
- package/lib/webrtc/src/polyfill/selectSettings.js.map +1 -0
- package/lib/webrtc/src/polyfill/sourceIo.d.ts +21 -0
- package/lib/webrtc/src/polyfill/sourceIo.js +298 -0
- package/lib/webrtc/src/polyfill/sourceIo.js.map +1 -0
- package/lib/webrtc/src/polyfill/trackStop.d.ts +4 -0
- package/lib/webrtc/src/polyfill/trackStop.js +16 -0
- package/lib/webrtc/src/polyfill/trackStop.js.map +1 -0
- package/lib/webrtc/src/sctpManager.d.ts +2 -1
- package/lib/webrtc/src/sctpManager.js +5 -2
- package/lib/webrtc/src/sctpManager.js.map +1 -1
- package/lib/webrtc/src/sdp.d.ts +1 -1
- package/lib/webrtc/src/sdp.js +5 -6
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/sdpManager.d.ts +38 -1
- package/lib/webrtc/src/sdpManager.js +236 -30
- package/lib/webrtc/src/sdpManager.js.map +1 -1
- package/lib/webrtc/src/secureTransportManager.d.ts +43 -12
- package/lib/webrtc/src/secureTransportManager.js +123 -47
- package/lib/webrtc/src/secureTransportManager.js.map +1 -1
- package/lib/webrtc/src/transceiverManager.d.ts +91 -6
- package/lib/webrtc/src/transceiverManager.js +477 -62
- package/lib/webrtc/src/transceiverManager.js.map +1 -1
- package/lib/webrtc/src/transport/ice.d.ts +8 -0
- package/lib/webrtc/src/transport/ice.js +17 -1
- package/lib/webrtc/src/transport/ice.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +3 -2
- package/lib/webrtc/src/transport/sctp.js +8 -2
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +14 -3
|
@@ -527,7 +527,7 @@ var Event2 = class {
|
|
|
527
527
|
};
|
|
528
528
|
allUnsubscribe = () => {
|
|
529
529
|
if (this.ended) {
|
|
530
|
-
|
|
530
|
+
return;
|
|
531
531
|
}
|
|
532
532
|
this.event = {
|
|
533
533
|
stack: [],
|
|
@@ -579,7 +579,7 @@ var Event2 = class {
|
|
|
579
579
|
error
|
|
580
580
|
);
|
|
581
581
|
};
|
|
582
|
-
watch = (cb, timeLimit) => new Promise((
|
|
582
|
+
watch = (cb, timeLimit) => new Promise((resolve, reject) => {
|
|
583
583
|
const timeout = timeLimit && setTimeout(() => {
|
|
584
584
|
reject("Event watch timeout");
|
|
585
585
|
}, timeLimit);
|
|
@@ -588,22 +588,22 @@ var Event2 = class {
|
|
|
588
588
|
if (done) {
|
|
589
589
|
if (timeout) clearTimeout(timeout);
|
|
590
590
|
unSubscribe();
|
|
591
|
-
|
|
591
|
+
resolve(args);
|
|
592
592
|
}
|
|
593
593
|
});
|
|
594
594
|
});
|
|
595
|
-
asPromise = (timeLimit) => new Promise((
|
|
595
|
+
asPromise = (timeLimit) => new Promise((resolve, reject) => {
|
|
596
596
|
const timeout = timeLimit && setTimeout(() => {
|
|
597
597
|
reject("Event asPromise timeout");
|
|
598
598
|
}, timeLimit);
|
|
599
599
|
this.once(
|
|
600
600
|
(...args) => {
|
|
601
601
|
if (timeout) clearTimeout(timeout);
|
|
602
|
-
|
|
602
|
+
resolve(args);
|
|
603
603
|
},
|
|
604
604
|
() => {
|
|
605
605
|
if (timeout) clearTimeout(timeout);
|
|
606
|
-
|
|
606
|
+
resolve([]);
|
|
607
607
|
},
|
|
608
608
|
(err5) => {
|
|
609
609
|
if (timeout) clearTimeout(timeout);
|
|
@@ -642,6 +642,7 @@ import * as net from "node:net";
|
|
|
642
642
|
import * as tls from "node:tls";
|
|
643
643
|
import { connect as connect2 } from "node:net";
|
|
644
644
|
var log = debug("werift-ice:packages/ice/src/transport.ts");
|
|
645
|
+
var DEFAULT_CONNECT_TIMEOUT_MS = 8e3;
|
|
645
646
|
var UdpTransport = class _UdpTransport {
|
|
646
647
|
constructor(socketType, options = {}) {
|
|
647
648
|
this.socketType = socketType;
|
|
@@ -710,6 +711,10 @@ var UdpTransport = class _UdpTransport {
|
|
|
710
711
|
get address() {
|
|
711
712
|
return this.socket.address();
|
|
712
713
|
}
|
|
714
|
+
/** IP family of the bound socket: 4 for udp4, 6 for udp6. */
|
|
715
|
+
get addressFamily() {
|
|
716
|
+
return this.socketType === "udp6" ? 6 : 4;
|
|
717
|
+
}
|
|
713
718
|
get host() {
|
|
714
719
|
return this.socket.address().address;
|
|
715
720
|
}
|
|
@@ -729,16 +734,23 @@ var UdpTransport = class _UdpTransport {
|
|
|
729
734
|
var TcpTransport = class _TcpTransport {
|
|
730
735
|
type = "tcp";
|
|
731
736
|
stream;
|
|
732
|
-
constructor(addr) {
|
|
737
|
+
constructor(addr, options = {}) {
|
|
733
738
|
this.stream = new StreamTransport(
|
|
734
739
|
"tcp",
|
|
735
|
-
() => connect2({ port: addr[1], host: addr[0] })
|
|
740
|
+
() => connect2({ port: addr[1], host: addr[0] }),
|
|
741
|
+
void 0,
|
|
742
|
+
options.connectTimeoutMs
|
|
736
743
|
);
|
|
737
744
|
}
|
|
738
|
-
static async init(addr) {
|
|
739
|
-
const transport = new _TcpTransport(addr);
|
|
740
|
-
|
|
741
|
-
|
|
745
|
+
static async init(addr, options = {}) {
|
|
746
|
+
const transport = new _TcpTransport(addr, options);
|
|
747
|
+
try {
|
|
748
|
+
await transport.init();
|
|
749
|
+
return transport;
|
|
750
|
+
} catch (error) {
|
|
751
|
+
await transport.close();
|
|
752
|
+
throw error;
|
|
753
|
+
}
|
|
742
754
|
}
|
|
743
755
|
async init() {
|
|
744
756
|
await this.stream.waitForConnect();
|
|
@@ -746,6 +758,9 @@ var TcpTransport = class _TcpTransport {
|
|
|
746
758
|
get address() {
|
|
747
759
|
return this.stream.address;
|
|
748
760
|
}
|
|
761
|
+
get remoteAddress() {
|
|
762
|
+
return this.stream.remoteAddress;
|
|
763
|
+
}
|
|
749
764
|
get closed() {
|
|
750
765
|
return this.stream.closed;
|
|
751
766
|
}
|
|
@@ -765,20 +780,27 @@ var TcpTransport = class _TcpTransport {
|
|
|
765
780
|
var TlsTransport = class _TlsTransport {
|
|
766
781
|
type = "tls";
|
|
767
782
|
stream;
|
|
768
|
-
constructor(addr, options = {}) {
|
|
783
|
+
constructor(addr, options = {}, streamOptions = {}) {
|
|
769
784
|
this.stream = new StreamTransport(
|
|
770
785
|
"tls",
|
|
771
786
|
() => tls.connect({
|
|
772
787
|
...options,
|
|
773
788
|
host: addr[0],
|
|
774
789
|
port: addr[1]
|
|
775
|
-
})
|
|
790
|
+
}),
|
|
791
|
+
void 0,
|
|
792
|
+
streamOptions.connectTimeoutMs
|
|
776
793
|
);
|
|
777
794
|
}
|
|
778
|
-
static async init(addr, options = {}) {
|
|
779
|
-
const transport = new _TlsTransport(addr, options);
|
|
780
|
-
|
|
781
|
-
|
|
795
|
+
static async init(addr, options = {}, streamOptions = {}) {
|
|
796
|
+
const transport = new _TlsTransport(addr, options, streamOptions);
|
|
797
|
+
try {
|
|
798
|
+
await transport.init();
|
|
799
|
+
return transport;
|
|
800
|
+
} catch (error) {
|
|
801
|
+
await transport.close();
|
|
802
|
+
throw error;
|
|
803
|
+
}
|
|
782
804
|
}
|
|
783
805
|
async init() {
|
|
784
806
|
await this.stream.waitForConnect();
|
|
@@ -786,6 +808,9 @@ var TlsTransport = class _TlsTransport {
|
|
|
786
808
|
get address() {
|
|
787
809
|
return this.stream.address;
|
|
788
810
|
}
|
|
811
|
+
get remoteAddress() {
|
|
812
|
+
return this.stream.remoteAddress;
|
|
813
|
+
}
|
|
789
814
|
get closed() {
|
|
790
815
|
return this.stream.closed;
|
|
791
816
|
}
|
|
@@ -803,9 +828,10 @@ var TlsTransport = class _TlsTransport {
|
|
|
803
828
|
};
|
|
804
829
|
};
|
|
805
830
|
var StreamTransport = class {
|
|
806
|
-
constructor(type, createClient, connectEvent = type === "tls" ? "secureConnect" : "connect") {
|
|
831
|
+
constructor(type, createClient, connectEvent = type === "tls" ? "secureConnect" : "connect", connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MS) {
|
|
807
832
|
this.createClient = createClient;
|
|
808
833
|
this.connectEvent = connectEvent;
|
|
834
|
+
this.connectTimeoutMs = connectTimeoutMs;
|
|
809
835
|
this.type = type;
|
|
810
836
|
this.connect();
|
|
811
837
|
}
|
|
@@ -815,6 +841,7 @@ var StreamTransport = class {
|
|
|
815
841
|
onData = () => {
|
|
816
842
|
};
|
|
817
843
|
closed = false;
|
|
844
|
+
rejectConnecting;
|
|
818
845
|
connect() {
|
|
819
846
|
if (this.closed) {
|
|
820
847
|
return;
|
|
@@ -824,27 +851,40 @@ var StreamTransport = class {
|
|
|
824
851
|
}
|
|
825
852
|
const client = this.createClient();
|
|
826
853
|
this.client = client;
|
|
827
|
-
this.connecting = new Promise((
|
|
828
|
-
|
|
854
|
+
this.connecting = new Promise((resolve, reject) => {
|
|
855
|
+
let settled = false;
|
|
856
|
+
const settle = (error) => {
|
|
857
|
+
if (settled) return;
|
|
858
|
+
settled = true;
|
|
859
|
+
clearTimeout(timer2);
|
|
860
|
+
client.off(this.connectEvent, onConnect);
|
|
829
861
|
client.off("error", onConnectError);
|
|
830
|
-
|
|
862
|
+
this.rejectConnecting = void 0;
|
|
863
|
+
error ? reject(error) : resolve();
|
|
864
|
+
};
|
|
865
|
+
const onConnect = () => {
|
|
866
|
+
settle();
|
|
831
867
|
};
|
|
832
868
|
const onConnectError = (error) => {
|
|
833
|
-
|
|
834
|
-
|
|
869
|
+
this.closed = true;
|
|
870
|
+
settle(error);
|
|
871
|
+
client.destroy();
|
|
835
872
|
};
|
|
873
|
+
const timer2 = setTimeout(() => {
|
|
874
|
+
this.closed = true;
|
|
875
|
+
settle(
|
|
876
|
+
new Error(
|
|
877
|
+
`${this.type} connect timed out after ${this.connectTimeoutMs}ms`
|
|
878
|
+
)
|
|
879
|
+
);
|
|
880
|
+
client.destroy();
|
|
881
|
+
}, this.connectTimeoutMs);
|
|
882
|
+
this.rejectConnecting = (error) => settle(error);
|
|
836
883
|
client.once(this.connectEvent, onConnect);
|
|
837
884
|
client.once("error", onConnectError);
|
|
838
885
|
});
|
|
839
886
|
client.on("data", (data) => {
|
|
840
|
-
|
|
841
|
-
this.client.remoteAddress,
|
|
842
|
-
this.client.remotePort
|
|
843
|
-
];
|
|
844
|
-
this.onData(data, addr);
|
|
845
|
-
});
|
|
846
|
-
client.on("end", () => {
|
|
847
|
-
this.connect();
|
|
887
|
+
this.onData(data, this.remoteAddress);
|
|
848
888
|
});
|
|
849
889
|
client.on("error", (error) => {
|
|
850
890
|
log(`${this.type} transport error`, error);
|
|
@@ -856,24 +896,36 @@ var StreamTransport = class {
|
|
|
856
896
|
get address() {
|
|
857
897
|
return {};
|
|
858
898
|
}
|
|
899
|
+
/** The peer the stream is connected to, once connected. */
|
|
900
|
+
get remoteAddress() {
|
|
901
|
+
const { remoteAddress, remotePort } = this.client;
|
|
902
|
+
if (!remoteAddress || !remotePort) {
|
|
903
|
+
return void 0;
|
|
904
|
+
}
|
|
905
|
+
return [stripZoneId(remoteAddress), remotePort];
|
|
906
|
+
}
|
|
859
907
|
send = async (data, addr) => {
|
|
860
908
|
void addr;
|
|
861
909
|
await this.connecting;
|
|
862
|
-
await new Promise((
|
|
910
|
+
await new Promise((resolve, reject) => {
|
|
863
911
|
this.client.write(data, (err5) => {
|
|
864
912
|
if (err5) {
|
|
865
913
|
reject(err5);
|
|
866
914
|
return;
|
|
867
915
|
}
|
|
868
|
-
|
|
916
|
+
resolve();
|
|
869
917
|
});
|
|
870
918
|
});
|
|
871
919
|
};
|
|
872
920
|
close = async () => {
|
|
873
921
|
this.closed = true;
|
|
922
|
+
this.rejectConnecting?.(new Error(`${this.type} transport closed`));
|
|
874
923
|
this.client?.destroy();
|
|
875
924
|
};
|
|
876
925
|
};
|
|
926
|
+
function stripZoneId(address) {
|
|
927
|
+
return address.split("%")[0];
|
|
928
|
+
}
|
|
877
929
|
|
|
878
930
|
// ../rtp/src/extra/container/mp4/container.ts
|
|
879
931
|
var Mp4Container = class {
|
|
@@ -897,6 +949,8 @@ var Mp4Container = class {
|
|
|
897
949
|
#startPromise;
|
|
898
950
|
#stopPromise;
|
|
899
951
|
#stopped = false;
|
|
952
|
+
// EncodedChunk timestamps may be negative; EncodedPacket requires >= 0.
|
|
953
|
+
#timestampOrigin = {};
|
|
900
954
|
#videoFrame;
|
|
901
955
|
#videoMeta;
|
|
902
956
|
#videoSource;
|
|
@@ -1131,10 +1185,17 @@ var Mp4Container = class {
|
|
|
1131
1185
|
async #writePacket(frame, duration) {
|
|
1132
1186
|
const data = new Uint8Array(frame.byteLength);
|
|
1133
1187
|
frame.copyTo(data.buffer);
|
|
1188
|
+
if (this.#timestampOrigin[frame.track] == void 0) {
|
|
1189
|
+
this.#timestampOrigin[frame.track] = Math.min(0, frame.timestamp);
|
|
1190
|
+
}
|
|
1191
|
+
const timestamp = Math.max(
|
|
1192
|
+
0,
|
|
1193
|
+
frame.timestamp - this.#timestampOrigin[frame.track]
|
|
1194
|
+
);
|
|
1134
1195
|
const packet = new EncodedPacket(
|
|
1135
1196
|
data,
|
|
1136
1197
|
frame.type,
|
|
1137
|
-
|
|
1198
|
+
timestamp / 1e6,
|
|
1138
1199
|
duration / 1e6
|
|
1139
1200
|
);
|
|
1140
1201
|
if (frame.track === "audio") {
|
|
@@ -1148,12 +1209,7 @@ var Mp4Container = class {
|
|
|
1148
1209
|
}
|
|
1149
1210
|
await this.#videoSource.add(packet, this.#videoMeta);
|
|
1150
1211
|
}
|
|
1151
|
-
this.#rememberFragmentPacket(
|
|
1152
|
-
frame.track,
|
|
1153
|
-
frame.type,
|
|
1154
|
-
frame.timestamp,
|
|
1155
|
-
duration
|
|
1156
|
-
);
|
|
1212
|
+
this.#rememberFragmentPacket(frame.track, frame.type, timestamp, duration);
|
|
1157
1213
|
}
|
|
1158
1214
|
#rememberFragmentPacket(kind, type, timestamp, duration) {
|
|
1159
1215
|
const end = timestamp + duration;
|
|
@@ -5809,17 +5865,17 @@ var JitterBufferBase = class {
|
|
|
5809
5865
|
this.rtpBuffer[rtp.header.sequenceNumber] = rtp;
|
|
5810
5866
|
}
|
|
5811
5867
|
resolveBuffer(seqNumFrom) {
|
|
5812
|
-
const
|
|
5868
|
+
const resolve = [];
|
|
5813
5869
|
for (let index = seqNumFrom; ; index = uint16Add(index, 1)) {
|
|
5814
5870
|
const rtp = this.rtpBuffer[index];
|
|
5815
5871
|
if (rtp) {
|
|
5816
|
-
|
|
5872
|
+
resolve.push(rtp);
|
|
5817
5873
|
delete this.rtpBuffer[index];
|
|
5818
5874
|
} else {
|
|
5819
5875
|
break;
|
|
5820
5876
|
}
|
|
5821
5877
|
}
|
|
5822
|
-
return
|
|
5878
|
+
return resolve;
|
|
5823
5879
|
}
|
|
5824
5880
|
sortAndClearBuffer(rtpBuffer) {
|
|
5825
5881
|
const buffer2 = [];
|
|
@@ -6141,7 +6197,7 @@ var MP4Base = class {
|
|
|
6141
6197
|
if (eol) {
|
|
6142
6198
|
this.videoStopped = true;
|
|
6143
6199
|
if (!this.tracks.some((track2) => track2.kind === "audio") || this.audioStopped) {
|
|
6144
|
-
void this.stop();
|
|
6200
|
+
void this.stop().catch(() => void 0);
|
|
6145
6201
|
}
|
|
6146
6202
|
}
|
|
6147
6203
|
return;
|
|
@@ -6198,7 +6254,7 @@ var MP4Base = class {
|
|
|
6198
6254
|
if (eol) {
|
|
6199
6255
|
this.audioStopped = true;
|
|
6200
6256
|
if (!this.tracks.some((track2) => track2.kind === "video") || this.videoStopped) {
|
|
6201
|
-
void this.stop();
|
|
6257
|
+
void this.stop().catch(() => void 0);
|
|
6202
6258
|
}
|
|
6203
6259
|
}
|
|
6204
6260
|
return;
|
|
@@ -6233,7 +6289,10 @@ var MP4Base = class {
|
|
|
6233
6289
|
return;
|
|
6234
6290
|
}
|
|
6235
6291
|
this.stopped = true;
|
|
6236
|
-
|
|
6292
|
+
try {
|
|
6293
|
+
await this.container.stop();
|
|
6294
|
+
} catch {
|
|
6295
|
+
}
|
|
6237
6296
|
await this.output({ eol: true });
|
|
6238
6297
|
await this.onStopped.execute();
|
|
6239
6298
|
}
|
|
@@ -6294,7 +6353,7 @@ var MP4Callback = class extends MP4Base {
|
|
|
6294
6353
|
this.processVideoInput(input);
|
|
6295
6354
|
};
|
|
6296
6355
|
destroy = () => {
|
|
6297
|
-
void this.stop().finally(() => {
|
|
6356
|
+
void this.stop().catch(() => void 0).finally(() => {
|
|
6298
6357
|
this.cb = void 0;
|
|
6299
6358
|
this.queue.cancel();
|
|
6300
6359
|
});
|
|
@@ -9242,10 +9301,6 @@ var log25 = debug("werift-ice : packages/ice/src/ice.ts : log");
|
|
|
9242
9301
|
|
|
9243
9302
|
// src/helper.ts
|
|
9244
9303
|
import { EventEmitter } from "node:events";
|
|
9245
|
-
function divide(from, split) {
|
|
9246
|
-
const arr = from.split(split);
|
|
9247
|
-
return [arr[0], arr.slice(1).join(split)];
|
|
9248
|
-
}
|
|
9249
9304
|
var EventTarget2 = class extends EventEmitter {
|
|
9250
9305
|
emit(type, ...args) {
|
|
9251
9306
|
if (typeof type !== "string") {
|
|
@@ -9357,6 +9412,12 @@ var usePCMU = (props = {}) => new RTCRtpCodecParameters({
|
|
|
9357
9412
|
payloadType: 0,
|
|
9358
9413
|
...props
|
|
9359
9414
|
});
|
|
9415
|
+
function defaultCodecs() {
|
|
9416
|
+
return {
|
|
9417
|
+
audio: [useOPUS(), usePCMU()],
|
|
9418
|
+
video: [useVP8()]
|
|
9419
|
+
};
|
|
9420
|
+
}
|
|
9360
9421
|
var supportedCodecs = [
|
|
9361
9422
|
useAV1X(),
|
|
9362
9423
|
useVP9(),
|
|
@@ -9385,23 +9446,83 @@ var DTLS_SETUP_ROLE = Object.keys(
|
|
|
9385
9446
|
acc[key] = cur;
|
|
9386
9447
|
return acc;
|
|
9387
9448
|
}, {});
|
|
9388
|
-
var FMTP_INT_PARAMETERS = [
|
|
9389
|
-
"apt",
|
|
9390
|
-
"max-fr",
|
|
9391
|
-
"max-fs",
|
|
9392
|
-
"maxplaybackrate",
|
|
9393
|
-
"minptime",
|
|
9394
|
-
"stereo",
|
|
9395
|
-
"useinbandfec"
|
|
9396
|
-
];
|
|
9397
9449
|
var SRTP_PROFILE = {
|
|
9398
9450
|
SRTP_AES128_CM_HMAC_SHA1_80: ProtectionProfileAes128CmHmacSha1_80,
|
|
9399
9451
|
SRTP_AEAD_AES_128_GCM: ProtectionProfileAeadAes128Gcm
|
|
9400
9452
|
};
|
|
9401
9453
|
|
|
9454
|
+
// src/transport/dtls.ts
|
|
9455
|
+
import { Certificate as Certificate3, PrivateKey as PrivateKey2 } from "@fidm/x509";
|
|
9456
|
+
|
|
9402
9457
|
// src/media/track.ts
|
|
9403
9458
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
9404
|
-
var
|
|
9459
|
+
var sourceCodecsByTrack = /* @__PURE__ */ new WeakMap();
|
|
9460
|
+
var sourceCodecsCapturedByTrack = /* @__PURE__ */ new WeakSet();
|
|
9461
|
+
function setTrackSourceCodecs(track, codecs) {
|
|
9462
|
+
sourceCodecsCapturedByTrack.add(track);
|
|
9463
|
+
if (codecs == void 0) sourceCodecsByTrack.delete(track);
|
|
9464
|
+
else sourceCodecsByTrack.set(track, codecs);
|
|
9465
|
+
}
|
|
9466
|
+
function getTrackSourceCodecs(track) {
|
|
9467
|
+
return track == void 0 ? void 0 : sourceCodecsByTrack.get(track);
|
|
9468
|
+
}
|
|
9469
|
+
function captureTrackSourceCodecs(track) {
|
|
9470
|
+
if (sourceCodecsCapturedByTrack.has(track)) return;
|
|
9471
|
+
sourceCodecsCapturedByTrack.add(track);
|
|
9472
|
+
if (track.codec != void 0) {
|
|
9473
|
+
sourceCodecsByTrack.set(track, [track.codec]);
|
|
9474
|
+
}
|
|
9475
|
+
}
|
|
9476
|
+
var TrackBroadcastSource = class {
|
|
9477
|
+
tracks = /* @__PURE__ */ new Set();
|
|
9478
|
+
upstreamStops = /* @__PURE__ */ new Set();
|
|
9479
|
+
attach(track) {
|
|
9480
|
+
this.tracks.add(track);
|
|
9481
|
+
}
|
|
9482
|
+
detach(track) {
|
|
9483
|
+
this.tracks.delete(track);
|
|
9484
|
+
if (this.tracks.size > 0) {
|
|
9485
|
+
return;
|
|
9486
|
+
}
|
|
9487
|
+
for (const stop of [...this.upstreamStops]) {
|
|
9488
|
+
stop();
|
|
9489
|
+
}
|
|
9490
|
+
this.upstreamStops.clear();
|
|
9491
|
+
}
|
|
9492
|
+
addUpstreamStop(stop) {
|
|
9493
|
+
const once = () => {
|
|
9494
|
+
this.upstreamStops.delete(once);
|
|
9495
|
+
stop();
|
|
9496
|
+
};
|
|
9497
|
+
this.upstreamStops.add(once);
|
|
9498
|
+
}
|
|
9499
|
+
deliverRtp(packet, extensions) {
|
|
9500
|
+
const live = [...this.tracks].filter((track) => !track.stopped);
|
|
9501
|
+
for (const track of live) {
|
|
9502
|
+
track.applyIncomingRtp(packet.clone(), extensions);
|
|
9503
|
+
}
|
|
9504
|
+
}
|
|
9505
|
+
deliverRtcp(packet) {
|
|
9506
|
+
for (const track of this.tracks) {
|
|
9507
|
+
if (!track.stopped) {
|
|
9508
|
+
track.onReceiveRtcp.execute(packet);
|
|
9509
|
+
}
|
|
9510
|
+
}
|
|
9511
|
+
}
|
|
9512
|
+
deliverSourceChanged(header) {
|
|
9513
|
+
for (const track of this.tracks) {
|
|
9514
|
+
if (!track.stopped) {
|
|
9515
|
+
track.onSourceChanged.execute(header);
|
|
9516
|
+
}
|
|
9517
|
+
}
|
|
9518
|
+
}
|
|
9519
|
+
stopAllTracks() {
|
|
9520
|
+
for (const track of [...this.tracks]) {
|
|
9521
|
+
track.stop();
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9524
|
+
};
|
|
9525
|
+
var MediaStreamTrack = class _MediaStreamTrack extends EventTarget2 {
|
|
9405
9526
|
uuid = randomUUID5().toString();
|
|
9406
9527
|
/**MediaStream ID*/
|
|
9407
9528
|
streamId;
|
|
@@ -9421,34 +9542,83 @@ var MediaStreamTrack = class extends EventTarget2 {
|
|
|
9421
9542
|
onSourceChanged = new Event2();
|
|
9422
9543
|
stopped = false;
|
|
9423
9544
|
muted = true;
|
|
9545
|
+
broadcastSource;
|
|
9424
9546
|
constructor(props) {
|
|
9425
9547
|
super();
|
|
9548
|
+
const sharedSource = props.broadcastSource;
|
|
9426
9549
|
Object.assign(this, props);
|
|
9550
|
+
this.id ??= this.uuid;
|
|
9551
|
+
this.broadcastSource = sharedSource ?? new TrackBroadcastSource();
|
|
9552
|
+
if (!this.stopped) {
|
|
9553
|
+
this.broadcastSource.attach(this);
|
|
9554
|
+
}
|
|
9427
9555
|
this.onReceiveRtp.subscribe((rtp) => {
|
|
9428
9556
|
this.muted = false;
|
|
9429
9557
|
this.header = rtp.header;
|
|
9430
9558
|
});
|
|
9431
9559
|
this.label = `${this.remote ? "remote" : "local"} ${this.kind}`;
|
|
9432
9560
|
}
|
|
9561
|
+
get readyState() {
|
|
9562
|
+
return this.stopped ? "ended" : "live";
|
|
9563
|
+
}
|
|
9433
9564
|
stop = () => {
|
|
9565
|
+
if (this.stopped) {
|
|
9566
|
+
return;
|
|
9567
|
+
}
|
|
9434
9568
|
this.stopped = true;
|
|
9435
9569
|
this.muted = true;
|
|
9436
9570
|
this.onReceiveRtp.complete();
|
|
9437
9571
|
this.emit("ended");
|
|
9572
|
+
this.broadcastSource.detach(this);
|
|
9438
9573
|
};
|
|
9439
9574
|
writeRtp = (rtp) => {
|
|
9440
9575
|
if (this.remote) {
|
|
9441
9576
|
throw new Error("this is remoteTrack");
|
|
9442
9577
|
}
|
|
9578
|
+
const packet = Buffer.isBuffer(rtp) ? RtpPacket.deSerialize(rtp) : rtp.clone();
|
|
9579
|
+
packet.header.payloadType = this.codec?.payloadType ?? packet.header.payloadType;
|
|
9580
|
+
this.broadcastSource.deliverRtp(packet);
|
|
9581
|
+
};
|
|
9582
|
+
writeRtcp = (rtcp) => {
|
|
9583
|
+
this.broadcastSource.deliverRtcp(rtcp);
|
|
9584
|
+
};
|
|
9585
|
+
notifySourceChanged(header) {
|
|
9586
|
+
this.broadcastSource.deliverSourceChanged(header);
|
|
9587
|
+
}
|
|
9588
|
+
applyIncomingRtp(packet, extensions) {
|
|
9443
9589
|
if (this.stopped) {
|
|
9444
9590
|
return;
|
|
9445
9591
|
}
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9592
|
+
this.onReceiveRtp.execute(packet, extensions);
|
|
9593
|
+
}
|
|
9594
|
+
bindUpstreamStop(stop) {
|
|
9595
|
+
this.broadcastSource.addUpstreamStop(stop);
|
|
9596
|
+
}
|
|
9597
|
+
stopMediaSource() {
|
|
9598
|
+
this.broadcastSource.stopAllTracks();
|
|
9599
|
+
}
|
|
9600
|
+
clone() {
|
|
9601
|
+
const cloned = new _MediaStreamTrack({
|
|
9602
|
+
kind: this.kind,
|
|
9603
|
+
remote: this.remote,
|
|
9604
|
+
enabled: this.enabled,
|
|
9605
|
+
muted: this.muted,
|
|
9606
|
+
stopped: this.stopped,
|
|
9607
|
+
codec: this.codec,
|
|
9608
|
+
ssrc: this.ssrc,
|
|
9609
|
+
rid: this.rid,
|
|
9610
|
+
header: this.header,
|
|
9611
|
+
broadcastSource: this.broadcastSource
|
|
9612
|
+
});
|
|
9613
|
+
if (sourceCodecsCapturedByTrack.has(this)) {
|
|
9614
|
+
setTrackSourceCodecs(cloned, getTrackSourceCodecs(this));
|
|
9615
|
+
} else {
|
|
9616
|
+
captureTrackSourceCodecs(cloned);
|
|
9617
|
+
}
|
|
9618
|
+
return cloned;
|
|
9619
|
+
}
|
|
9450
9620
|
};
|
|
9451
|
-
var MediaStream = class {
|
|
9621
|
+
var MediaStream = class _MediaStream {
|
|
9452
9622
|
id;
|
|
9453
9623
|
tracks = [];
|
|
9454
9624
|
constructor(props = {}) {
|
|
@@ -9478,6 +9648,19 @@ var MediaStream = class {
|
|
|
9478
9648
|
getVideoTracks() {
|
|
9479
9649
|
return this.tracks.filter((track) => track.kind === "video");
|
|
9480
9650
|
}
|
|
9651
|
+
getTrackById(id) {
|
|
9652
|
+
return this.tracks.find((track) => track.id === id);
|
|
9653
|
+
}
|
|
9654
|
+
get active() {
|
|
9655
|
+
return this.tracks.some((track) => !track.stopped);
|
|
9656
|
+
}
|
|
9657
|
+
clone() {
|
|
9658
|
+
const cloned = new _MediaStream();
|
|
9659
|
+
for (const track of this.tracks) {
|
|
9660
|
+
cloned.addTrack(track.clone());
|
|
9661
|
+
}
|
|
9662
|
+
return cloned;
|
|
9663
|
+
}
|
|
9481
9664
|
};
|
|
9482
9665
|
|
|
9483
9666
|
// src/utils.ts
|
|
@@ -9486,21 +9669,17 @@ var milliTime = Date.now;
|
|
|
9486
9669
|
var startupTimestampInMicroseconds = BigInt(Date.now()) * 1000n - process.hrtime.bigint() / 1000n;
|
|
9487
9670
|
var createSelfSignedCertificate = CipherContext.createSelfSignedCertificateWithKey;
|
|
9488
9671
|
|
|
9489
|
-
// src/media/receiver/nack.ts
|
|
9490
|
-
var log28 = debug("werift:packages/webrtc/src/media/receiver/nack.ts");
|
|
9491
|
-
var LOST_SIZE2 = 30 * 5;
|
|
9492
|
-
|
|
9493
|
-
// src/media/receiver/receiverTwcc.ts
|
|
9494
|
-
var log29 = debug("werift:packages/webrtc/media/receiver/receiverTwcc");
|
|
9495
|
-
|
|
9496
9672
|
// src/transport/dtls.ts
|
|
9497
|
-
|
|
9498
|
-
var log30 = debug("werift:packages/webrtc/src/transport/dtls.ts");
|
|
9673
|
+
var log28 = debug("werift:packages/webrtc/src/transport/dtls.ts");
|
|
9499
9674
|
|
|
9500
9675
|
// src/transport/ice.ts
|
|
9501
|
-
var
|
|
9676
|
+
var log29 = debug("werift:packages/webrtc/src/transport/ice.ts");
|
|
9502
9677
|
|
|
9503
9678
|
// ../sctp/src/chunk.ts
|
|
9679
|
+
var SCTP_PADDING_MULTIPLE = 4;
|
|
9680
|
+
var SCTP_CHUNK_HEADER_SIZE = 4;
|
|
9681
|
+
var SCTP_DATA_FIXED_HEADER_SIZE = 12;
|
|
9682
|
+
var SCTP_DATA_CHUNK_HEADER_SIZE = SCTP_CHUNK_HEADER_SIZE + SCTP_DATA_FIXED_HEADER_SIZE;
|
|
9504
9683
|
var Chunk = class _Chunk {
|
|
9505
9684
|
constructor(flags = 0, _body = Buffer.from("")) {
|
|
9506
9685
|
this.flags = flags;
|
|
@@ -9518,10 +9697,10 @@ var Chunk = class _Chunk {
|
|
|
9518
9697
|
}
|
|
9519
9698
|
get bytes() {
|
|
9520
9699
|
if (!this.body) throw new Error();
|
|
9521
|
-
const header = Buffer.alloc(
|
|
9700
|
+
const header = Buffer.alloc(SCTP_CHUNK_HEADER_SIZE);
|
|
9522
9701
|
header.writeUInt8(this.type, 0);
|
|
9523
9702
|
header.writeUInt8(this.flags, 1);
|
|
9524
|
-
header.writeUInt16BE(this.body.length +
|
|
9703
|
+
header.writeUInt16BE(this.body.length + SCTP_CHUNK_HEADER_SIZE, 2);
|
|
9525
9704
|
const data = Buffer.concat([
|
|
9526
9705
|
header,
|
|
9527
9706
|
this.body,
|
|
@@ -9646,8 +9825,8 @@ var DataChunk = class _DataChunk extends Chunk {
|
|
|
9646
9825
|
maxRetransmits;
|
|
9647
9826
|
sentTime;
|
|
9648
9827
|
get bytes() {
|
|
9649
|
-
const length =
|
|
9650
|
-
const header = Buffer.alloc(
|
|
9828
|
+
const length = SCTP_DATA_CHUNK_HEADER_SIZE + this.userData.length;
|
|
9829
|
+
const header = Buffer.alloc(SCTP_DATA_CHUNK_HEADER_SIZE);
|
|
9651
9830
|
header.writeUInt8(this.type, 0);
|
|
9652
9831
|
header.writeUInt8(this.flags, 1);
|
|
9653
9832
|
header.writeUInt16BE(length, 2);
|
|
@@ -9857,8 +10036,8 @@ var CHUNK_BY_TYPE = CHUNK_CLASSES.reduce(
|
|
|
9857
10036
|
{}
|
|
9858
10037
|
);
|
|
9859
10038
|
function padL(l) {
|
|
9860
|
-
const m = l %
|
|
9861
|
-
return m ?
|
|
10039
|
+
const m = l % SCTP_PADDING_MULTIPLE;
|
|
10040
|
+
return m ? SCTP_PADDING_MULTIPLE - m : 0;
|
|
9862
10041
|
}
|
|
9863
10042
|
function encodeParams(params) {
|
|
9864
10043
|
let body = Buffer.from("");
|
|
@@ -9888,35 +10067,22 @@ function decodeParams(body) {
|
|
|
9888
10067
|
}
|
|
9889
10068
|
|
|
9890
10069
|
// ../sctp/src/sctp.ts
|
|
9891
|
-
var
|
|
10070
|
+
var log30 = debug("werift/sctp/sctp");
|
|
10071
|
+
var DEFAULT_SCTP_MTU = 1191;
|
|
9892
10072
|
var SCTP_RTO_ALPHA = 1 / 8;
|
|
9893
10073
|
var SCTP_RTO_BETA = 1 / 4;
|
|
9894
10074
|
var SCTP_TSN_MODULO = 2 ** 32;
|
|
9895
10075
|
|
|
9896
10076
|
// src/transport/sctp.ts
|
|
9897
|
-
var
|
|
10077
|
+
var log31 = debug("werift:packages/webrtc/src/transport/sctp.ts");
|
|
9898
10078
|
var DEFAULT_MAX_MESSAGE_SIZE = 65536;
|
|
9899
10079
|
|
|
9900
|
-
// src/
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
if (FMTP_INT_PARAMETERS.includes(k)) {
|
|
9907
|
-
parameters[k] = Number(v);
|
|
9908
|
-
} else {
|
|
9909
|
-
parameters[k] = v;
|
|
9910
|
-
}
|
|
9911
|
-
} else if (param.includes(":")) {
|
|
9912
|
-
const [k, v] = param.split(":");
|
|
9913
|
-
parameters[k] = Number.isNaN(Number(v)) ? v : Number(v);
|
|
9914
|
-
} else {
|
|
9915
|
-
parameters[param] = void 0;
|
|
9916
|
-
}
|
|
9917
|
-
});
|
|
9918
|
-
return parameters;
|
|
9919
|
-
}
|
|
10080
|
+
// src/media/receiver/nack.ts
|
|
10081
|
+
var log32 = debug("werift:packages/webrtc/src/media/receiver/nack.ts");
|
|
10082
|
+
var LOST_SIZE2 = 30 * 5;
|
|
10083
|
+
|
|
10084
|
+
// src/media/receiver/receiverTwcc.ts
|
|
10085
|
+
var log33 = debug("werift:packages/webrtc/media/receiver/receiverTwcc");
|
|
9920
10086
|
|
|
9921
10087
|
// src/media/rtpReceiver.ts
|
|
9922
10088
|
var log34 = debug("werift:packages/webrtc/src/media/rtpReceiver.ts");
|
|
@@ -9927,11 +10093,14 @@ var log35 = debug("werift:packages/webrtc/src/media/router.ts");
|
|
|
9927
10093
|
// src/media/rtpSender.ts
|
|
9928
10094
|
var log36 = debug("werift:packages/webrtc/src/media/rtpSender.ts");
|
|
9929
10095
|
|
|
10096
|
+
// src/transceiverManager.ts
|
|
10097
|
+
var log37 = debug("werift:packages/webrtc/src/media/rtpTransceiverManager.ts");
|
|
10098
|
+
|
|
9930
10099
|
// src/sctpManager.ts
|
|
9931
|
-
var
|
|
10100
|
+
var log38 = debug("werift:packages/webrtc/src/transport/sctpManager.ts");
|
|
9932
10101
|
|
|
9933
10102
|
// src/secureTransportManager.ts
|
|
9934
|
-
var
|
|
10103
|
+
var log39 = debug(
|
|
9935
10104
|
"werift:packages/webrtc/src/transport/secureTransportManager.ts"
|
|
9936
10105
|
);
|
|
9937
10106
|
var srtpProfiles = [
|
|
@@ -9941,13 +10110,10 @@ var srtpProfiles = [
|
|
|
9941
10110
|
];
|
|
9942
10111
|
|
|
9943
10112
|
// src/peerConnection.ts
|
|
9944
|
-
var
|
|
10113
|
+
var log40 = debug("werift:packages/webrtc/src/peerConnection.ts");
|
|
9945
10114
|
function generateDefaultPeerConfig() {
|
|
9946
10115
|
return {
|
|
9947
|
-
codecs:
|
|
9948
|
-
audio: [useOPUS(), usePCMU()],
|
|
9949
|
-
video: [useVP8()]
|
|
9950
|
-
},
|
|
10116
|
+
codecs: defaultCodecs(),
|
|
9951
10117
|
headerExtensions: {
|
|
9952
10118
|
audio: [],
|
|
9953
10119
|
video: []
|
|
@@ -9961,8 +10127,12 @@ function generateDefaultPeerConfig() {
|
|
|
9961
10127
|
iceUseIpv4: true,
|
|
9962
10128
|
iceUseIpv6: true,
|
|
9963
10129
|
iceUseTcp: false,
|
|
10130
|
+
iceTcpPassive: true,
|
|
10131
|
+
iceStunGatherTimeout: void 0,
|
|
10132
|
+
iceTurnConnectTimeout: void 0,
|
|
9964
10133
|
turnTransport: void 0,
|
|
9965
10134
|
turnTlsOptions: void 0,
|
|
10135
|
+
turnUdpFamily: void 0,
|
|
9966
10136
|
iceFilterStunResponse: void 0,
|
|
9967
10137
|
iceFilterCandidatePair: void 0,
|
|
9968
10138
|
icePasswordPrefix: void 0,
|
|
@@ -9975,14 +10145,14 @@ function generateDefaultPeerConfig() {
|
|
|
9975
10145
|
debug: {},
|
|
9976
10146
|
midSuffix: false,
|
|
9977
10147
|
forceTurnTCP: false,
|
|
9978
|
-
maxMessageSize: DEFAULT_MAX_MESSAGE_SIZE
|
|
10148
|
+
maxMessageSize: DEFAULT_MAX_MESSAGE_SIZE,
|
|
10149
|
+
sctp: { mtu: DEFAULT_SCTP_MTU },
|
|
10150
|
+
pendingRtp: false,
|
|
10151
|
+
mLineReuse: "compatible"
|
|
9979
10152
|
};
|
|
9980
10153
|
}
|
|
9981
10154
|
var defaultPeerConfig = generateDefaultPeerConfig();
|
|
9982
10155
|
|
|
9983
|
-
// src/transceiverManager.ts
|
|
9984
|
-
var log40 = debug("werift:packages/webrtc/src/media/rtpTransceiverManager.ts");
|
|
9985
|
-
|
|
9986
10156
|
// src/nonstandard/dummyMedia.ts
|
|
9987
10157
|
var AUDIO_PACKET_MS = 20;
|
|
9988
10158
|
var AUDIO_TIMESTAMP_STEP = 960;
|
|
@@ -10268,6 +10438,7 @@ var WebmFactory = class extends MediaWriter {
|
|
|
10268
10438
|
return "VP9";
|
|
10269
10439
|
case "h264":
|
|
10270
10440
|
return "MPEG4/ISO/AVC";
|
|
10441
|
+
case "av1":
|
|
10271
10442
|
case "av1x":
|
|
10272
10443
|
return "AV1";
|
|
10273
10444
|
default:
|
|
@@ -10425,893 +10596,6 @@ var MediaRecorder = class {
|
|
|
10425
10596
|
await this.writer.stop();
|
|
10426
10597
|
}
|
|
10427
10598
|
};
|
|
10428
|
-
|
|
10429
|
-
// src/nonstandard/userMedia.ts
|
|
10430
|
-
import { randomUUID as randomUUID6 } from "crypto";
|
|
10431
|
-
import { homedir } from "os";
|
|
10432
|
-
import { isAbsolute, resolve } from "path";
|
|
10433
|
-
import { Readable } from "stream";
|
|
10434
|
-
import { readFile } from "fs/promises";
|
|
10435
|
-
import {
|
|
10436
|
-
setImmediate as onNextTurn,
|
|
10437
|
-
setTimeout as wait
|
|
10438
|
-
} from "timers/promises";
|
|
10439
|
-
import {
|
|
10440
|
-
BufferSource,
|
|
10441
|
-
EncodedPacketSink,
|
|
10442
|
-
Input,
|
|
10443
|
-
MP4,
|
|
10444
|
-
WEBM
|
|
10445
|
-
} from "mediabunny";
|
|
10446
|
-
|
|
10447
|
-
// src/nonstandard/userMedia/packetizer.ts
|
|
10448
|
-
var DEFAULT_MAX_RTP_PAYLOAD_SIZE = 1200;
|
|
10449
|
-
var supportedSourceCodecs = [
|
|
10450
|
-
"avc",
|
|
10451
|
-
"vp8",
|
|
10452
|
-
"vp9",
|
|
10453
|
-
"av1",
|
|
10454
|
-
"opus"
|
|
10455
|
-
];
|
|
10456
|
-
function toSupportedMimeType(codec) {
|
|
10457
|
-
switch (codec) {
|
|
10458
|
-
case "avc":
|
|
10459
|
-
return "video/h264";
|
|
10460
|
-
case "vp8":
|
|
10461
|
-
return "video/vp8";
|
|
10462
|
-
case "vp9":
|
|
10463
|
-
return "video/vp9";
|
|
10464
|
-
case "av1":
|
|
10465
|
-
return "video/av1x";
|
|
10466
|
-
case "opus":
|
|
10467
|
-
return "audio/opus";
|
|
10468
|
-
}
|
|
10469
|
-
}
|
|
10470
|
-
function createPacketizer({
|
|
10471
|
-
codec,
|
|
10472
|
-
sourceCodec,
|
|
10473
|
-
decoderDescription
|
|
10474
|
-
}) {
|
|
10475
|
-
switch (sourceCodec) {
|
|
10476
|
-
case "avc":
|
|
10477
|
-
return new H264Packetizer(codec, decoderDescription ?? null);
|
|
10478
|
-
case "vp8":
|
|
10479
|
-
return new Vp8Packetizer(codec);
|
|
10480
|
-
case "vp9":
|
|
10481
|
-
return new Vp9Packetizer(codec);
|
|
10482
|
-
case "av1":
|
|
10483
|
-
return new Av1Packetizer(codec);
|
|
10484
|
-
case "opus":
|
|
10485
|
-
return new OpusPacketizer(codec);
|
|
10486
|
-
}
|
|
10487
|
-
}
|
|
10488
|
-
var BasePacketizer = class {
|
|
10489
|
-
constructor(codec, maxPayloadSize = DEFAULT_MAX_RTP_PAYLOAD_SIZE) {
|
|
10490
|
-
this.codec = codec;
|
|
10491
|
-
this.maxPayloadSize = maxPayloadSize;
|
|
10492
|
-
}
|
|
10493
|
-
sequenceNumber = random16();
|
|
10494
|
-
buildPacket(payload, timestamp, marker) {
|
|
10495
|
-
const packet = new RtpPacket(
|
|
10496
|
-
new RtpHeader({
|
|
10497
|
-
payloadType: this.codec.payloadType ?? 96,
|
|
10498
|
-
sequenceNumber: this.sequenceNumber,
|
|
10499
|
-
timestamp,
|
|
10500
|
-
marker
|
|
10501
|
-
}),
|
|
10502
|
-
payload
|
|
10503
|
-
);
|
|
10504
|
-
this.sequenceNumber = this.sequenceNumber + 1 & 65535;
|
|
10505
|
-
return packet;
|
|
10506
|
-
}
|
|
10507
|
-
};
|
|
10508
|
-
var OpusPacketizer = class extends BasePacketizer {
|
|
10509
|
-
packetize(packet, rtpTimestamp) {
|
|
10510
|
-
return [this.buildPacket(toBuffer(packet.data), rtpTimestamp, true)];
|
|
10511
|
-
}
|
|
10512
|
-
};
|
|
10513
|
-
var Vp8Packetizer = class extends BasePacketizer {
|
|
10514
|
-
packetize(packet, rtpTimestamp) {
|
|
10515
|
-
const frame = toBuffer(packet.data);
|
|
10516
|
-
const chunkSize = this.maxPayloadSize - 1;
|
|
10517
|
-
if (chunkSize <= 0) {
|
|
10518
|
-
throw new Error("invalid VP8 RTP payload size");
|
|
10519
|
-
}
|
|
10520
|
-
const packets = [];
|
|
10521
|
-
for (let offset = 0; offset < frame.length; offset += chunkSize) {
|
|
10522
|
-
const chunk = frame.subarray(
|
|
10523
|
-
offset,
|
|
10524
|
-
Math.min(frame.length, offset + chunkSize)
|
|
10525
|
-
);
|
|
10526
|
-
const descriptor = Buffer.from([offset === 0 ? 16 : 0]);
|
|
10527
|
-
packets.push(
|
|
10528
|
-
this.buildPacket(
|
|
10529
|
-
Buffer.concat([descriptor, chunk]),
|
|
10530
|
-
rtpTimestamp,
|
|
10531
|
-
offset + chunk.length >= frame.length
|
|
10532
|
-
)
|
|
10533
|
-
);
|
|
10534
|
-
}
|
|
10535
|
-
return packets;
|
|
10536
|
-
}
|
|
10537
|
-
};
|
|
10538
|
-
var Vp9Packetizer = class extends BasePacketizer {
|
|
10539
|
-
packetize(packet, rtpTimestamp) {
|
|
10540
|
-
const frame = toBuffer(packet.data);
|
|
10541
|
-
const chunkSize = this.maxPayloadSize - 1;
|
|
10542
|
-
if (chunkSize <= 0) {
|
|
10543
|
-
throw new Error("invalid VP9 RTP payload size");
|
|
10544
|
-
}
|
|
10545
|
-
const packets = [];
|
|
10546
|
-
for (let offset = 0; offset < frame.length; offset += chunkSize) {
|
|
10547
|
-
const chunk = frame.subarray(
|
|
10548
|
-
offset,
|
|
10549
|
-
Math.min(frame.length, offset + chunkSize)
|
|
10550
|
-
);
|
|
10551
|
-
const descriptor = new BitWriter(8).set(1, 0, 0).set(1, 1, packet.type === "delta" ? 1 : 0).set(1, 2, 0).set(1, 3, 0).set(1, 4, offset === 0 ? 1 : 0).set(1, 5, offset + chunk.length >= frame.length ? 1 : 0).set(1, 6, 0).set(1, 7, 0).buffer;
|
|
10552
|
-
packets.push(
|
|
10553
|
-
this.buildPacket(
|
|
10554
|
-
Buffer.concat([descriptor, chunk]),
|
|
10555
|
-
rtpTimestamp,
|
|
10556
|
-
offset + chunk.length >= frame.length
|
|
10557
|
-
)
|
|
10558
|
-
);
|
|
10559
|
-
}
|
|
10560
|
-
return packets;
|
|
10561
|
-
}
|
|
10562
|
-
};
|
|
10563
|
-
var Av1Packetizer = class extends BasePacketizer {
|
|
10564
|
-
packetize(packet, rtpTimestamp) {
|
|
10565
|
-
const obus = splitAv1Obus(toBuffer(packet.data));
|
|
10566
|
-
const packets = [];
|
|
10567
|
-
const fragmentSize = this.maxPayloadSize - 1;
|
|
10568
|
-
if (fragmentSize <= 0) {
|
|
10569
|
-
throw new Error("invalid AV1 RTP payload size");
|
|
10570
|
-
}
|
|
10571
|
-
let firstPacketInFrame = true;
|
|
10572
|
-
const startsNewCodedVideoSequence = packet.type === "key";
|
|
10573
|
-
for (const obu of obus) {
|
|
10574
|
-
if (obu.length <= fragmentSize) {
|
|
10575
|
-
const aggregationHeader = createAv1AggregationHeader({
|
|
10576
|
-
startsWithFragment: false,
|
|
10577
|
-
endsWithFragment: false,
|
|
10578
|
-
startsNewCodedVideoSequence: firstPacketInFrame && startsNewCodedVideoSequence
|
|
10579
|
-
});
|
|
10580
|
-
packets.push(
|
|
10581
|
-
this.buildPacket(
|
|
10582
|
-
Buffer.concat([aggregationHeader, obu]),
|
|
10583
|
-
rtpTimestamp,
|
|
10584
|
-
false
|
|
10585
|
-
)
|
|
10586
|
-
);
|
|
10587
|
-
firstPacketInFrame = false;
|
|
10588
|
-
continue;
|
|
10589
|
-
}
|
|
10590
|
-
for (let offset = 0; offset < obu.length; offset += fragmentSize) {
|
|
10591
|
-
const chunk = obu.subarray(
|
|
10592
|
-
offset,
|
|
10593
|
-
Math.min(obu.length, offset + fragmentSize)
|
|
10594
|
-
);
|
|
10595
|
-
const aggregationHeader = createAv1AggregationHeader({
|
|
10596
|
-
startsWithFragment: offset > 0,
|
|
10597
|
-
endsWithFragment: offset + chunk.length < obu.length,
|
|
10598
|
-
startsNewCodedVideoSequence: firstPacketInFrame && startsNewCodedVideoSequence
|
|
10599
|
-
});
|
|
10600
|
-
packets.push(
|
|
10601
|
-
this.buildPacket(
|
|
10602
|
-
Buffer.concat([aggregationHeader, chunk]),
|
|
10603
|
-
rtpTimestamp,
|
|
10604
|
-
false
|
|
10605
|
-
)
|
|
10606
|
-
);
|
|
10607
|
-
firstPacketInFrame = false;
|
|
10608
|
-
}
|
|
10609
|
-
}
|
|
10610
|
-
if (packets.length === 0) {
|
|
10611
|
-
throw new Error("AV1 sample did not contain any OBU data");
|
|
10612
|
-
}
|
|
10613
|
-
packets.at(-1).header.marker = true;
|
|
10614
|
-
return packets;
|
|
10615
|
-
}
|
|
10616
|
-
};
|
|
10617
|
-
var H264Packetizer = class extends BasePacketizer {
|
|
10618
|
-
naluLengthSize;
|
|
10619
|
-
parameterSets;
|
|
10620
|
-
constructor(codec, decoderDescription) {
|
|
10621
|
-
super(codec);
|
|
10622
|
-
const packetizationMode = getH264PacketizationMode(codec.parameters);
|
|
10623
|
-
if (packetizationMode !== 1) {
|
|
10624
|
-
throw new Error(
|
|
10625
|
-
`Unsupported H264 packetization-mode=${packetizationMode}. File playback requires packetization-mode=1.`
|
|
10626
|
-
);
|
|
10627
|
-
}
|
|
10628
|
-
const avcConfig = parseAvcDecoderConfiguration(decoderDescription);
|
|
10629
|
-
this.naluLengthSize = avcConfig?.naluLengthSize ?? 4;
|
|
10630
|
-
this.parameterSets = avcConfig ? [...avcConfig.sps.map(Buffer.from), ...avcConfig.pps.map(Buffer.from)] : [];
|
|
10631
|
-
}
|
|
10632
|
-
packetize(packet, rtpTimestamp) {
|
|
10633
|
-
let nalUnits = splitH264Sample(toBuffer(packet.data), this.naluLengthSize);
|
|
10634
|
-
if (packet.type === "key" && this.parameterSets.length > 0 && !containsH264ParameterSets(nalUnits)) {
|
|
10635
|
-
nalUnits = [...this.parameterSets, ...nalUnits];
|
|
10636
|
-
}
|
|
10637
|
-
const packets = [];
|
|
10638
|
-
nalUnits.forEach((nalUnit, index) => {
|
|
10639
|
-
const marker = index === nalUnits.length - 1;
|
|
10640
|
-
if (nalUnit.length <= this.maxPayloadSize) {
|
|
10641
|
-
packets.push(this.buildPacket(nalUnit, rtpTimestamp, marker));
|
|
10642
|
-
return;
|
|
10643
|
-
}
|
|
10644
|
-
const nalHeader = nalUnit[0];
|
|
10645
|
-
const fragmentPayload = nalUnit.subarray(1);
|
|
10646
|
-
const fragmentSize = this.maxPayloadSize - 2;
|
|
10647
|
-
if (fragmentSize <= 0) {
|
|
10648
|
-
throw new Error("invalid H264 RTP payload size");
|
|
10649
|
-
}
|
|
10650
|
-
const fuIndicator = nalHeader & 224 | 28;
|
|
10651
|
-
const nalType = nalHeader & 31;
|
|
10652
|
-
for (let offset = 0; offset < fragmentPayload.length; offset += fragmentSize) {
|
|
10653
|
-
const chunk = fragmentPayload.subarray(
|
|
10654
|
-
offset,
|
|
10655
|
-
Math.min(fragmentPayload.length, offset + fragmentSize)
|
|
10656
|
-
);
|
|
10657
|
-
const fuHeader = Buffer.from([
|
|
10658
|
-
(offset === 0 ? 128 : 0) | (offset + chunk.length >= fragmentPayload.length ? 64 : 0) | nalType
|
|
10659
|
-
]);
|
|
10660
|
-
packets.push(
|
|
10661
|
-
this.buildPacket(
|
|
10662
|
-
Buffer.concat([Buffer.from([fuIndicator]), fuHeader, chunk]),
|
|
10663
|
-
rtpTimestamp,
|
|
10664
|
-
marker && offset + chunk.length >= fragmentPayload.length
|
|
10665
|
-
)
|
|
10666
|
-
);
|
|
10667
|
-
}
|
|
10668
|
-
});
|
|
10669
|
-
return packets;
|
|
10670
|
-
}
|
|
10671
|
-
};
|
|
10672
|
-
function createAv1AggregationHeader({
|
|
10673
|
-
startsWithFragment,
|
|
10674
|
-
endsWithFragment,
|
|
10675
|
-
startsNewCodedVideoSequence
|
|
10676
|
-
}) {
|
|
10677
|
-
return new BitWriter(8).set(1, 0, startsWithFragment ? 1 : 0).set(1, 1, endsWithFragment ? 1 : 0).set(2, 2, 1).set(1, 4, startsNewCodedVideoSequence ? 1 : 0).set(3, 5, 0).buffer;
|
|
10678
|
-
}
|
|
10679
|
-
function parseAvcDecoderConfiguration(decoderDescription) {
|
|
10680
|
-
if (!decoderDescription) {
|
|
10681
|
-
return null;
|
|
10682
|
-
}
|
|
10683
|
-
const description = toDescriptionBuffer(decoderDescription);
|
|
10684
|
-
if (description.length < 7) {
|
|
10685
|
-
throw new Error("invalid H264 decoder configuration");
|
|
10686
|
-
}
|
|
10687
|
-
const naluLengthSize = (description[4] & 3) + 1;
|
|
10688
|
-
const spsCount = description[5] & 31;
|
|
10689
|
-
let offset = 6;
|
|
10690
|
-
const sps = [];
|
|
10691
|
-
for (let index = 0; index < spsCount; index++) {
|
|
10692
|
-
const length = description.readUInt16BE(offset);
|
|
10693
|
-
offset += 2;
|
|
10694
|
-
sps.push(description.subarray(offset, offset + length));
|
|
10695
|
-
offset += length;
|
|
10696
|
-
}
|
|
10697
|
-
const ppsCount = description[offset] ?? 0;
|
|
10698
|
-
offset++;
|
|
10699
|
-
const pps = [];
|
|
10700
|
-
for (let index = 0; index < ppsCount; index++) {
|
|
10701
|
-
const length = description.readUInt16BE(offset);
|
|
10702
|
-
offset += 2;
|
|
10703
|
-
pps.push(description.subarray(offset, offset + length));
|
|
10704
|
-
offset += length;
|
|
10705
|
-
}
|
|
10706
|
-
return { naluLengthSize, sps, pps };
|
|
10707
|
-
}
|
|
10708
|
-
function splitH264Sample(sample, naluLengthSize) {
|
|
10709
|
-
if (looksLikeAnnexB(sample)) {
|
|
10710
|
-
const nalUnits2 = [];
|
|
10711
|
-
const parser = new H264AnnexBParser(sample);
|
|
10712
|
-
let payload = parser.readNextNaluPayload();
|
|
10713
|
-
while (payload) {
|
|
10714
|
-
nalUnits2.push(Buffer.from(payload.data));
|
|
10715
|
-
payload = parser.readNextNaluPayload();
|
|
10716
|
-
}
|
|
10717
|
-
return nalUnits2;
|
|
10718
|
-
}
|
|
10719
|
-
const nalUnits = [];
|
|
10720
|
-
let offset = 0;
|
|
10721
|
-
while (offset < sample.length) {
|
|
10722
|
-
const length = readUintLength(sample, offset, naluLengthSize);
|
|
10723
|
-
offset += naluLengthSize;
|
|
10724
|
-
const end = offset + length;
|
|
10725
|
-
if (end > sample.length) {
|
|
10726
|
-
throw new Error("invalid H264 sample length");
|
|
10727
|
-
}
|
|
10728
|
-
nalUnits.push(sample.subarray(offset, end));
|
|
10729
|
-
offset = end;
|
|
10730
|
-
}
|
|
10731
|
-
return nalUnits;
|
|
10732
|
-
}
|
|
10733
|
-
function splitAv1Obus(sample) {
|
|
10734
|
-
const obus = [];
|
|
10735
|
-
let offset = 0;
|
|
10736
|
-
while (offset < sample.length) {
|
|
10737
|
-
const start = offset;
|
|
10738
|
-
const header = sample[offset];
|
|
10739
|
-
offset += 1;
|
|
10740
|
-
if (header == void 0) {
|
|
10741
|
-
break;
|
|
10742
|
-
}
|
|
10743
|
-
const extensionFlag = getBit(header, 5);
|
|
10744
|
-
const hasSizeField = getBit(header, 6);
|
|
10745
|
-
if (extensionFlag) {
|
|
10746
|
-
offset += 1;
|
|
10747
|
-
}
|
|
10748
|
-
if (!hasSizeField) {
|
|
10749
|
-
obus.push(sample.subarray(start));
|
|
10750
|
-
break;
|
|
10751
|
-
}
|
|
10752
|
-
const [obuSize, leb128Length] = leb128decode(sample.subarray(offset));
|
|
10753
|
-
offset += leb128Length;
|
|
10754
|
-
const end = offset + obuSize;
|
|
10755
|
-
if (end > sample.length) {
|
|
10756
|
-
throw new Error("invalid AV1 OBU size");
|
|
10757
|
-
}
|
|
10758
|
-
obus.push(sample.subarray(start, end));
|
|
10759
|
-
offset = end;
|
|
10760
|
-
}
|
|
10761
|
-
return obus;
|
|
10762
|
-
}
|
|
10763
|
-
function containsH264ParameterSets(nalUnits) {
|
|
10764
|
-
return nalUnits.some((nalUnit) => {
|
|
10765
|
-
const nalType = nalUnit[0] & 31;
|
|
10766
|
-
return nalType === 7 || nalType === 8;
|
|
10767
|
-
});
|
|
10768
|
-
}
|
|
10769
|
-
function looksLikeAnnexB(sample) {
|
|
10770
|
-
return sample.length >= 4 && sample[0] === 0 && sample[1] === 0 && (sample[2] === 0 && sample[3] === 1 || sample[2] === 1);
|
|
10771
|
-
}
|
|
10772
|
-
function readUintLength(buffer2, offset, length) {
|
|
10773
|
-
switch (length) {
|
|
10774
|
-
case 1:
|
|
10775
|
-
return buffer2.readUInt8(offset);
|
|
10776
|
-
case 2:
|
|
10777
|
-
return buffer2.readUInt16BE(offset);
|
|
10778
|
-
case 3:
|
|
10779
|
-
return buffer2.readUIntBE(offset, 3);
|
|
10780
|
-
case 4:
|
|
10781
|
-
return buffer2.readUInt32BE(offset);
|
|
10782
|
-
default:
|
|
10783
|
-
throw new Error(`unsupported H264 NALU length size: ${length}`);
|
|
10784
|
-
}
|
|
10785
|
-
}
|
|
10786
|
-
function getH264PacketizationMode(parameters) {
|
|
10787
|
-
if (!parameters) {
|
|
10788
|
-
return 1;
|
|
10789
|
-
}
|
|
10790
|
-
const packetizationMode = parameters.split(";").map((part) => part.trim()).find((part) => part.startsWith("packetization-mode="));
|
|
10791
|
-
if (!packetizationMode) {
|
|
10792
|
-
return 1;
|
|
10793
|
-
}
|
|
10794
|
-
return Number(packetizationMode.split("=")[1] ?? 1);
|
|
10795
|
-
}
|
|
10796
|
-
function toDescriptionBuffer(decoderDescription) {
|
|
10797
|
-
if (ArrayBuffer.isView(decoderDescription)) {
|
|
10798
|
-
return Buffer.from(
|
|
10799
|
-
decoderDescription.buffer,
|
|
10800
|
-
decoderDescription.byteOffset,
|
|
10801
|
-
decoderDescription.byteLength
|
|
10802
|
-
);
|
|
10803
|
-
}
|
|
10804
|
-
return Buffer.from(decoderDescription);
|
|
10805
|
-
}
|
|
10806
|
-
function toBuffer(data) {
|
|
10807
|
-
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
10808
|
-
}
|
|
10809
|
-
|
|
10810
|
-
// src/nonstandard/userMedia.ts
|
|
10811
|
-
var getUserMedia = async (options) => {
|
|
10812
|
-
assertSupportedOptions(options);
|
|
10813
|
-
const replayableSource = await createReplayableSource(options);
|
|
10814
|
-
const input = await createInput(replayableSource);
|
|
10815
|
-
try {
|
|
10816
|
-
if (!await input.canRead()) {
|
|
10817
|
-
throw new Error("Only MP4 and WebM file playback is supported");
|
|
10818
|
-
}
|
|
10819
|
-
const streamId = randomUUID6().toString();
|
|
10820
|
-
const playbackTracks = await selectPlaybackTracks(input, streamId);
|
|
10821
|
-
if (playbackTracks.length === 0) {
|
|
10822
|
-
throw new Error(
|
|
10823
|
-
"The media source does not contain playable audio or video tracks"
|
|
10824
|
-
);
|
|
10825
|
-
}
|
|
10826
|
-
const mediaStartTimestamp = await input.getFirstTimestamp(
|
|
10827
|
-
playbackTracks.map(({ inputTrack }) => inputTrack)
|
|
10828
|
-
);
|
|
10829
|
-
return new MediaPlayer({
|
|
10830
|
-
source: replayableSource,
|
|
10831
|
-
loop: options.loop ?? false,
|
|
10832
|
-
streamId,
|
|
10833
|
-
session: createPlaybackSession({
|
|
10834
|
-
input,
|
|
10835
|
-
mediaStartTimestamp,
|
|
10836
|
-
playbackTracks
|
|
10837
|
-
})
|
|
10838
|
-
});
|
|
10839
|
-
} catch (error) {
|
|
10840
|
-
input.dispose();
|
|
10841
|
-
throw error;
|
|
10842
|
-
}
|
|
10843
|
-
};
|
|
10844
|
-
var MediaPlayer = class {
|
|
10845
|
-
audio;
|
|
10846
|
-
video;
|
|
10847
|
-
onError = new Event2();
|
|
10848
|
-
source;
|
|
10849
|
-
loop;
|
|
10850
|
-
streamId;
|
|
10851
|
-
session;
|
|
10852
|
-
running;
|
|
10853
|
-
abortController;
|
|
10854
|
-
hasStartedPlayback = false;
|
|
10855
|
-
stopped = false;
|
|
10856
|
-
constructor({
|
|
10857
|
-
source,
|
|
10858
|
-
loop,
|
|
10859
|
-
streamId,
|
|
10860
|
-
session
|
|
10861
|
-
}) {
|
|
10862
|
-
this.source = source;
|
|
10863
|
-
this.loop = loop;
|
|
10864
|
-
this.streamId = streamId;
|
|
10865
|
-
this.session = session;
|
|
10866
|
-
this.audio = session.playbackTracks.find(
|
|
10867
|
-
({ track }) => track.kind === "audio"
|
|
10868
|
-
)?.track;
|
|
10869
|
-
this.video = session.playbackTracks.find(
|
|
10870
|
-
({ track }) => track.kind === "video"
|
|
10871
|
-
)?.track;
|
|
10872
|
-
}
|
|
10873
|
-
async start() {
|
|
10874
|
-
if (this.stopped) {
|
|
10875
|
-
throw new Error("The media source has already been stopped");
|
|
10876
|
-
}
|
|
10877
|
-
if (this.running) {
|
|
10878
|
-
return;
|
|
10879
|
-
}
|
|
10880
|
-
const abortController = new AbortController();
|
|
10881
|
-
this.abortController = abortController;
|
|
10882
|
-
let startupPending = true;
|
|
10883
|
-
let session;
|
|
10884
|
-
const playback = (async () => {
|
|
10885
|
-
session = await this.getOrCreateSession();
|
|
10886
|
-
if (abortController.signal.aborted || this.stopped) {
|
|
10887
|
-
return;
|
|
10888
|
-
}
|
|
10889
|
-
session.runners.forEach((runner) => runner.assertReady());
|
|
10890
|
-
const initialSourceChanged = this.hasStartedPlayback;
|
|
10891
|
-
this.hasStartedPlayback = true;
|
|
10892
|
-
await this.run(session, abortController, initialSourceChanged);
|
|
10893
|
-
})();
|
|
10894
|
-
const observedPlayback = playback.catch((error) => {
|
|
10895
|
-
if (abortController.signal.aborted) {
|
|
10896
|
-
return;
|
|
10897
|
-
}
|
|
10898
|
-
this.onError.execute(toError(error));
|
|
10899
|
-
if (startupPending) {
|
|
10900
|
-
throw error;
|
|
10901
|
-
}
|
|
10902
|
-
});
|
|
10903
|
-
this.running = observedPlayback.finally(() => {
|
|
10904
|
-
if (this.abortController === abortController) {
|
|
10905
|
-
this.abortController = void 0;
|
|
10906
|
-
}
|
|
10907
|
-
this.running = void 0;
|
|
10908
|
-
this.disposeSession(session);
|
|
10909
|
-
});
|
|
10910
|
-
try {
|
|
10911
|
-
await Promise.race([this.running, onNextTurn()]);
|
|
10912
|
-
} finally {
|
|
10913
|
-
startupPending = false;
|
|
10914
|
-
}
|
|
10915
|
-
}
|
|
10916
|
-
stop() {
|
|
10917
|
-
if (this.stopped) {
|
|
10918
|
-
return;
|
|
10919
|
-
}
|
|
10920
|
-
this.stopped = true;
|
|
10921
|
-
this.abortController?.abort();
|
|
10922
|
-
if (!this.running) {
|
|
10923
|
-
this.disposeSession();
|
|
10924
|
-
}
|
|
10925
|
-
}
|
|
10926
|
-
async run(session, abortController, initialSourceChanged) {
|
|
10927
|
-
let sourceChanged = initialSourceChanged;
|
|
10928
|
-
do {
|
|
10929
|
-
const startedAt = performance.now();
|
|
10930
|
-
await Promise.all(
|
|
10931
|
-
session.runners.map(
|
|
10932
|
-
(runner) => runner.play({
|
|
10933
|
-
startedAt,
|
|
10934
|
-
signal: abortController.signal,
|
|
10935
|
-
sourceChanged
|
|
10936
|
-
})
|
|
10937
|
-
)
|
|
10938
|
-
);
|
|
10939
|
-
if (!this.loop || abortController.signal.aborted) {
|
|
10940
|
-
break;
|
|
10941
|
-
}
|
|
10942
|
-
sourceChanged = true;
|
|
10943
|
-
} while (!abortController.signal.aborted);
|
|
10944
|
-
}
|
|
10945
|
-
async getOrCreateSession() {
|
|
10946
|
-
if (this.session) {
|
|
10947
|
-
return this.session;
|
|
10948
|
-
}
|
|
10949
|
-
const input = await createInput(this.source);
|
|
10950
|
-
try {
|
|
10951
|
-
if (!await input.canRead()) {
|
|
10952
|
-
throw new Error("Only MP4 and WebM file playback is supported");
|
|
10953
|
-
}
|
|
10954
|
-
const playbackTracks = await selectPlaybackTracks(
|
|
10955
|
-
input,
|
|
10956
|
-
this.streamId,
|
|
10957
|
-
buildExistingTrackMap(this.audio, this.video)
|
|
10958
|
-
);
|
|
10959
|
-
const mediaStartTimestamp = await input.getFirstTimestamp(
|
|
10960
|
-
playbackTracks.map(({ inputTrack }) => inputTrack)
|
|
10961
|
-
);
|
|
10962
|
-
const session = createPlaybackSession({
|
|
10963
|
-
input,
|
|
10964
|
-
mediaStartTimestamp,
|
|
10965
|
-
playbackTracks
|
|
10966
|
-
});
|
|
10967
|
-
this.session = session;
|
|
10968
|
-
return session;
|
|
10969
|
-
} catch (error) {
|
|
10970
|
-
input.dispose();
|
|
10971
|
-
throw error;
|
|
10972
|
-
}
|
|
10973
|
-
}
|
|
10974
|
-
disposeSession(session = this.session) {
|
|
10975
|
-
if (!session) {
|
|
10976
|
-
return;
|
|
10977
|
-
}
|
|
10978
|
-
session.input.dispose();
|
|
10979
|
-
if (this.session === session) {
|
|
10980
|
-
this.session = void 0;
|
|
10981
|
-
}
|
|
10982
|
-
}
|
|
10983
|
-
};
|
|
10984
|
-
var TrackPlaybackRunner = class {
|
|
10985
|
-
constructor(props) {
|
|
10986
|
-
this.props = props;
|
|
10987
|
-
}
|
|
10988
|
-
async play({
|
|
10989
|
-
startedAt,
|
|
10990
|
-
signal,
|
|
10991
|
-
sourceChanged
|
|
10992
|
-
}) {
|
|
10993
|
-
const codec = this.requireNegotiatedCodec();
|
|
10994
|
-
const packetizer = createPacketizer({
|
|
10995
|
-
codec,
|
|
10996
|
-
sourceCodec: this.props.sourceCodec,
|
|
10997
|
-
decoderDescription: this.props.decoderDescription
|
|
10998
|
-
});
|
|
10999
|
-
const packetSink = new EncodedPacketSink(this.props.inputTrack);
|
|
11000
|
-
let sourceChangeNotified = false;
|
|
11001
|
-
try {
|
|
11002
|
-
for await (const packet of packetSink.packets(void 0, void 0, {
|
|
11003
|
-
verifyKeyPackets: this.props.track.kind === "video"
|
|
11004
|
-
})) {
|
|
11005
|
-
signal.throwIfAborted?.();
|
|
11006
|
-
const dueAtMs = (packet.timestamp - this.props.mediaStartTimestamp) * 1e3;
|
|
11007
|
-
const remainingMs = dueAtMs - (performance.now() - startedAt);
|
|
11008
|
-
if (remainingMs > 0) {
|
|
11009
|
-
await wait(remainingMs, void 0, { signal });
|
|
11010
|
-
}
|
|
11011
|
-
const rtpTimestamp = toRtpTimestamp(
|
|
11012
|
-
packet.timestamp,
|
|
11013
|
-
this.props.mediaStartTimestamp,
|
|
11014
|
-
codec.clockRate
|
|
11015
|
-
);
|
|
11016
|
-
const packets = packetizer.packetize(packet, rtpTimestamp);
|
|
11017
|
-
if (packets.length === 0) {
|
|
11018
|
-
continue;
|
|
11019
|
-
}
|
|
11020
|
-
if (sourceChanged && !sourceChangeNotified) {
|
|
11021
|
-
this.props.track.onSourceChanged.execute(packets[0].header);
|
|
11022
|
-
sourceChangeNotified = true;
|
|
11023
|
-
}
|
|
11024
|
-
for (const rtpPacket of packets) {
|
|
11025
|
-
this.props.track.writeRtp(rtpPacket);
|
|
11026
|
-
}
|
|
11027
|
-
}
|
|
11028
|
-
} catch (error) {
|
|
11029
|
-
if (signal.aborted || isAbortError(error)) {
|
|
11030
|
-
return;
|
|
11031
|
-
}
|
|
11032
|
-
throw error;
|
|
11033
|
-
}
|
|
11034
|
-
}
|
|
11035
|
-
assertReady() {
|
|
11036
|
-
const codec = this.requireNegotiatedCodec();
|
|
11037
|
-
createPacketizer({
|
|
11038
|
-
codec,
|
|
11039
|
-
sourceCodec: this.props.sourceCodec,
|
|
11040
|
-
decoderDescription: this.props.decoderDescription
|
|
11041
|
-
});
|
|
11042
|
-
}
|
|
11043
|
-
requireNegotiatedCodec() {
|
|
11044
|
-
const codec = this.props.track.codec;
|
|
11045
|
-
if (!codec) {
|
|
11046
|
-
throw new Error(
|
|
11047
|
-
`Cannot start ${this.props.track.kind} playback before the track is attached to an RTCRtpSender`
|
|
11048
|
-
);
|
|
11049
|
-
}
|
|
11050
|
-
const expectedMimeType = toSupportedMimeType(this.props.sourceCodec);
|
|
11051
|
-
const negotiatedMimeType = normalizeMimeType(codec.mimeType);
|
|
11052
|
-
if (negotiatedMimeType !== expectedMimeType) {
|
|
11053
|
-
throw new Error(
|
|
11054
|
-
`Input ${this.props.track.kind} codec ${expectedMimeType} does not match negotiated codec ${codec.mimeType}`
|
|
11055
|
-
);
|
|
11056
|
-
}
|
|
11057
|
-
const expectedClockRate = this.props.track.kind === "audio" ? 48e3 : 9e4;
|
|
11058
|
-
if (codec.clockRate !== expectedClockRate) {
|
|
11059
|
-
throw new Error(
|
|
11060
|
-
`Input ${this.props.track.kind} clock rate ${expectedClockRate} does not match negotiated clock rate ${codec.clockRate}`
|
|
11061
|
-
);
|
|
11062
|
-
}
|
|
11063
|
-
assertCodecParameters({
|
|
11064
|
-
trackKind: this.props.track.kind === "audio" ? "audio" : "video",
|
|
11065
|
-
codec,
|
|
11066
|
-
sourceCodec: this.props.sourceCodec,
|
|
11067
|
-
decoderDescription: this.props.decoderDescription,
|
|
11068
|
-
sourceChannels: this.props.sourceChannels
|
|
11069
|
-
});
|
|
11070
|
-
return codec;
|
|
11071
|
-
}
|
|
11072
|
-
};
|
|
11073
|
-
async function selectPlaybackTracks(input, streamId, existingTracks = {}) {
|
|
11074
|
-
const primaryVideoTrack = await input.getPrimaryVideoTrack();
|
|
11075
|
-
const primaryAudioTrack = primaryVideoTrack ? await primaryVideoTrack.getPrimaryPairableAudioTrack() ?? await input.getPrimaryAudioTrack() : await input.getPrimaryAudioTrack();
|
|
11076
|
-
const playbackTracks = [];
|
|
11077
|
-
if (primaryAudioTrack) {
|
|
11078
|
-
playbackTracks.push(
|
|
11079
|
-
await createPlaybackTrack(
|
|
11080
|
-
primaryAudioTrack,
|
|
11081
|
-
streamId,
|
|
11082
|
-
existingTracks.audio
|
|
11083
|
-
)
|
|
11084
|
-
);
|
|
11085
|
-
}
|
|
11086
|
-
if (primaryVideoTrack) {
|
|
11087
|
-
playbackTracks.push(
|
|
11088
|
-
await createPlaybackTrack(
|
|
11089
|
-
primaryVideoTrack,
|
|
11090
|
-
streamId,
|
|
11091
|
-
existingTracks.video
|
|
11092
|
-
)
|
|
11093
|
-
);
|
|
11094
|
-
}
|
|
11095
|
-
if (!primaryVideoTrack && !primaryAudioTrack) {
|
|
11096
|
-
const fallbackAudioTrack = await input.getPrimaryAudioTrack();
|
|
11097
|
-
if (fallbackAudioTrack) {
|
|
11098
|
-
playbackTracks.push(
|
|
11099
|
-
await createPlaybackTrack(
|
|
11100
|
-
fallbackAudioTrack,
|
|
11101
|
-
streamId,
|
|
11102
|
-
existingTracks.audio
|
|
11103
|
-
)
|
|
11104
|
-
);
|
|
11105
|
-
}
|
|
11106
|
-
}
|
|
11107
|
-
return playbackTracks;
|
|
11108
|
-
}
|
|
11109
|
-
async function createPlaybackTrack(inputTrack, streamId, track) {
|
|
11110
|
-
const sourceCodec = await requireSupportedCodec(inputTrack);
|
|
11111
|
-
const decoderConfig = await inputTrack.getDecoderConfig();
|
|
11112
|
-
const kind = inputTrack.isAudioTrack() ? "audio" : "video";
|
|
11113
|
-
return {
|
|
11114
|
-
inputTrack,
|
|
11115
|
-
sourceCodec,
|
|
11116
|
-
decoderDescription: decoderConfig && "description" in decoderConfig ? decoderConfig.description ?? null : null,
|
|
11117
|
-
sourceChannels: decoderConfig && "numberOfChannels" in decoderConfig ? decoderConfig.numberOfChannels : void 0,
|
|
11118
|
-
track: track ?? new MediaStreamTrack({
|
|
11119
|
-
kind,
|
|
11120
|
-
streamId
|
|
11121
|
-
})
|
|
11122
|
-
};
|
|
11123
|
-
}
|
|
11124
|
-
async function requireSupportedCodec(inputTrack) {
|
|
11125
|
-
const codec = await inputTrack.getCodec();
|
|
11126
|
-
if (codec && supportedSourceCodecs.includes(codec)) {
|
|
11127
|
-
return codec;
|
|
11128
|
-
}
|
|
11129
|
-
const codecLabel = codec ?? await inputTrack.getCodecParameterString() ?? String(await inputTrack.getInternalCodecId() ?? "unknown");
|
|
11130
|
-
throw new Error(
|
|
11131
|
-
`Unsupported ${inputTrack.type} codec "${codecLabel}". File playback supports H264, VP8, VP9, AV1, and Opus only.`
|
|
11132
|
-
);
|
|
11133
|
-
}
|
|
11134
|
-
async function createReplayableSource(options) {
|
|
11135
|
-
if (typeof options.path === "string") {
|
|
11136
|
-
return { path: options.path };
|
|
11137
|
-
}
|
|
11138
|
-
const buffer2 = options.buffer != void 0 ? toBuffer2(options.buffer) : await readStreamToBuffer(options.stream);
|
|
11139
|
-
return { buffer: buffer2 };
|
|
11140
|
-
}
|
|
11141
|
-
async function createInput(options) {
|
|
11142
|
-
if (typeof options.path === "string") {
|
|
11143
|
-
const buffer2 = await readFile(resolveUserMediaPath(options.path));
|
|
11144
|
-
return new Input({
|
|
11145
|
-
source: new BufferSource(buffer2),
|
|
11146
|
-
formats: [MP4, WEBM]
|
|
11147
|
-
});
|
|
11148
|
-
}
|
|
11149
|
-
return new Input({
|
|
11150
|
-
source: new BufferSource(options.buffer),
|
|
11151
|
-
formats: [MP4, WEBM]
|
|
11152
|
-
});
|
|
11153
|
-
}
|
|
11154
|
-
function resolveUserMediaPath(path2) {
|
|
11155
|
-
if (path2 === "~") {
|
|
11156
|
-
return homedir();
|
|
11157
|
-
}
|
|
11158
|
-
if (path2.startsWith("~/")) {
|
|
11159
|
-
return resolve(homedir(), path2.slice(2));
|
|
11160
|
-
}
|
|
11161
|
-
return isAbsolute(path2) ? path2 : resolve(path2);
|
|
11162
|
-
}
|
|
11163
|
-
async function readStreamToBuffer(stream) {
|
|
11164
|
-
const chunks = [];
|
|
11165
|
-
if (stream instanceof Readable) {
|
|
11166
|
-
for await (const chunk of stream) {
|
|
11167
|
-
chunks.push(toBuffer2(chunk));
|
|
11168
|
-
}
|
|
11169
|
-
return Buffer.concat(chunks);
|
|
11170
|
-
}
|
|
11171
|
-
const reader = stream.getReader();
|
|
11172
|
-
try {
|
|
11173
|
-
for (; ; ) {
|
|
11174
|
-
const { done, value } = await reader.read();
|
|
11175
|
-
if (done) {
|
|
11176
|
-
break;
|
|
11177
|
-
}
|
|
11178
|
-
if (value) {
|
|
11179
|
-
chunks.push(
|
|
11180
|
-
Buffer.from(value.buffer, value.byteOffset, value.byteLength)
|
|
11181
|
-
);
|
|
11182
|
-
}
|
|
11183
|
-
}
|
|
11184
|
-
} finally {
|
|
11185
|
-
reader.releaseLock();
|
|
11186
|
-
}
|
|
11187
|
-
return Buffer.concat(chunks);
|
|
11188
|
-
}
|
|
11189
|
-
function toBuffer2(value) {
|
|
11190
|
-
if (Buffer.isBuffer(value)) {
|
|
11191
|
-
return value;
|
|
11192
|
-
}
|
|
11193
|
-
if (typeof value === "string") {
|
|
11194
|
-
return Buffer.from(value);
|
|
11195
|
-
}
|
|
11196
|
-
if (ArrayBuffer.isView(value)) {
|
|
11197
|
-
return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
11198
|
-
}
|
|
11199
|
-
return Buffer.from(new Uint8Array(value));
|
|
11200
|
-
}
|
|
11201
|
-
function normalizeMimeType(mimeType) {
|
|
11202
|
-
return mimeType.toLowerCase();
|
|
11203
|
-
}
|
|
11204
|
-
function assertSupportedOptions(options) {
|
|
11205
|
-
const legacyOptions = options;
|
|
11206
|
-
if (legacyOptions.width != void 0 || legacyOptions.height != void 0) {
|
|
11207
|
-
throw new Error(
|
|
11208
|
-
"getUserMedia({ width, height }) is no longer supported for file playback. Resize or re-encode the source before calling getUserMedia()."
|
|
11209
|
-
);
|
|
11210
|
-
}
|
|
11211
|
-
}
|
|
11212
|
-
function createPlaybackSession({
|
|
11213
|
-
input,
|
|
11214
|
-
mediaStartTimestamp,
|
|
11215
|
-
playbackTracks
|
|
11216
|
-
}) {
|
|
11217
|
-
return {
|
|
11218
|
-
input,
|
|
11219
|
-
mediaStartTimestamp,
|
|
11220
|
-
playbackTracks,
|
|
11221
|
-
runners: playbackTracks.map(
|
|
11222
|
-
(playbackTrack) => new TrackPlaybackRunner({
|
|
11223
|
-
mediaStartTimestamp,
|
|
11224
|
-
...playbackTrack
|
|
11225
|
-
})
|
|
11226
|
-
)
|
|
11227
|
-
};
|
|
11228
|
-
}
|
|
11229
|
-
function buildExistingTrackMap(audio, video) {
|
|
11230
|
-
return {
|
|
11231
|
-
...audio ? { audio } : {},
|
|
11232
|
-
...video ? { video } : {}
|
|
11233
|
-
};
|
|
11234
|
-
}
|
|
11235
|
-
function assertCodecParameters({
|
|
11236
|
-
trackKind,
|
|
11237
|
-
codec,
|
|
11238
|
-
sourceCodec,
|
|
11239
|
-
decoderDescription,
|
|
11240
|
-
sourceChannels
|
|
11241
|
-
}) {
|
|
11242
|
-
if (sourceCodec === "opus" && sourceChannels && codec.channels != void 0) {
|
|
11243
|
-
if (codec.channels !== sourceChannels) {
|
|
11244
|
-
throw new Error(
|
|
11245
|
-
`Input ${trackKind} channels ${sourceChannels} do not match negotiated channels ${codec.channels}`
|
|
11246
|
-
);
|
|
11247
|
-
}
|
|
11248
|
-
return;
|
|
11249
|
-
}
|
|
11250
|
-
if (sourceCodec !== "avc") {
|
|
11251
|
-
return;
|
|
11252
|
-
}
|
|
11253
|
-
const negotiatedParameters = codecParametersFromString(
|
|
11254
|
-
codec.parameters ?? ""
|
|
11255
|
-
);
|
|
11256
|
-
const negotiatedPacketizationMode = Number(
|
|
11257
|
-
negotiatedParameters["packetization-mode"] ?? 1
|
|
11258
|
-
);
|
|
11259
|
-
if (negotiatedPacketizationMode !== 1) {
|
|
11260
|
-
throw new Error(
|
|
11261
|
-
`Input ${trackKind} packetization-mode 1 does not match negotiated packetization-mode ${negotiatedPacketizationMode}`
|
|
11262
|
-
);
|
|
11263
|
-
}
|
|
11264
|
-
const sourceProfileLevelId = getH264ProfileLevelId(decoderDescription);
|
|
11265
|
-
const negotiatedProfileLevelId = normalizeOptionalHexParameter(
|
|
11266
|
-
negotiatedParameters["profile-level-id"]
|
|
11267
|
-
);
|
|
11268
|
-
if (!sourceProfileLevelId) {
|
|
11269
|
-
return;
|
|
11270
|
-
}
|
|
11271
|
-
if (!negotiatedProfileLevelId) {
|
|
11272
|
-
throw new Error(
|
|
11273
|
-
`Input ${trackKind} profile-level-id ${sourceProfileLevelId} does not match negotiated profile-level-id <missing>`
|
|
11274
|
-
);
|
|
11275
|
-
}
|
|
11276
|
-
if (sourceProfileLevelId !== negotiatedProfileLevelId) {
|
|
11277
|
-
throw new Error(
|
|
11278
|
-
`Input ${trackKind} profile-level-id ${sourceProfileLevelId} does not match negotiated profile-level-id ${negotiatedProfileLevelId}`
|
|
11279
|
-
);
|
|
11280
|
-
}
|
|
11281
|
-
}
|
|
11282
|
-
function getH264ProfileLevelId(decoderDescription) {
|
|
11283
|
-
if (!decoderDescription) {
|
|
11284
|
-
return void 0;
|
|
11285
|
-
}
|
|
11286
|
-
const description = toDescriptionBuffer2(decoderDescription);
|
|
11287
|
-
if (description.length < 4) {
|
|
11288
|
-
throw new Error("invalid H264 decoder configuration");
|
|
11289
|
-
}
|
|
11290
|
-
return description.subarray(1, 4).toString("hex");
|
|
11291
|
-
}
|
|
11292
|
-
function normalizeOptionalHexParameter(value) {
|
|
11293
|
-
return typeof value === "string" ? value.toLowerCase() : void 0;
|
|
11294
|
-
}
|
|
11295
|
-
function toRtpTimestamp(packetTimestamp, mediaStartTimestamp, clockRate) {
|
|
11296
|
-
const relativeSeconds = Math.max(0, packetTimestamp - mediaStartTimestamp);
|
|
11297
|
-
return Math.round(relativeSeconds * clockRate) >>> 0;
|
|
11298
|
-
}
|
|
11299
|
-
function isAbortError(error) {
|
|
11300
|
-
return error instanceof Error && (error.name === "AbortError" || error.message === "The operation was aborted");
|
|
11301
|
-
}
|
|
11302
|
-
function toError(error) {
|
|
11303
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
11304
|
-
}
|
|
11305
|
-
function toDescriptionBuffer2(decoderDescription) {
|
|
11306
|
-
if (ArrayBuffer.isView(decoderDescription)) {
|
|
11307
|
-
return Buffer.from(
|
|
11308
|
-
decoderDescription.buffer,
|
|
11309
|
-
decoderDescription.byteOffset,
|
|
11310
|
-
decoderDescription.byteLength
|
|
11311
|
-
);
|
|
11312
|
-
}
|
|
11313
|
-
return Buffer.from(decoderDescription);
|
|
11314
|
-
}
|
|
11315
10599
|
export {
|
|
11316
10600
|
AV1Obu,
|
|
11317
10601
|
AV1RtpPayload,
|
|
@@ -11451,7 +10735,6 @@ export {
|
|
|
11451
10735
|
getEBMLByteLength,
|
|
11452
10736
|
getNumberByteLength,
|
|
11453
10737
|
getSizeMask,
|
|
11454
|
-
getUserMedia,
|
|
11455
10738
|
growBufferSize,
|
|
11456
10739
|
int,
|
|
11457
10740
|
int16Bit,
|