werift 0.24.4 → 0.25.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/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 +40 -15
- package/lib/ice/src/turn/protocol.js +141 -32
- 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 +6175 -4073
- package/lib/nonstandard/index.mjs +286 -1003
- 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 +126 -5
- package/lib/webrtc/src/peerConnection.js +609 -136
- 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 +13 -3
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMp4WebmRegister = createMp4WebmRegister;
|
|
4
|
+
const errors_1 = require("../../errors");
|
|
5
|
+
const parameters_1 = require("../../media/parameters");
|
|
6
|
+
const track_1 = require("../../media/track");
|
|
7
|
+
const userMedia_1 = require("../../nonstandard/userMedia");
|
|
8
|
+
const rtpCodec_1 = require("../rtpCodec");
|
|
9
|
+
const sourceIo_1 = require("../sourceIo");
|
|
10
|
+
const trackStop_1 = require("../trackStop");
|
|
11
|
+
/**
|
|
12
|
+
* Synchronous factory. Container I/O and player setup run in `prepare` /
|
|
13
|
+
* `createTracks`, so install does not open files or consume live streams.
|
|
14
|
+
*/
|
|
15
|
+
function createMp4WebmRegister(options) {
|
|
16
|
+
let mimeType = initialMimeType(options);
|
|
17
|
+
const kinds = [...initialKinds(options)];
|
|
18
|
+
let playerPromise;
|
|
19
|
+
let resolvedFile;
|
|
20
|
+
let started = false;
|
|
21
|
+
const liveTracks = new Set();
|
|
22
|
+
const ioAbort = new AbortController();
|
|
23
|
+
const register = {
|
|
24
|
+
get mimeType() {
|
|
25
|
+
return mimeType;
|
|
26
|
+
},
|
|
27
|
+
get kinds() {
|
|
28
|
+
return kinds;
|
|
29
|
+
},
|
|
30
|
+
deviceId: options.deviceId,
|
|
31
|
+
groupId: options.groupId,
|
|
32
|
+
label: options.label,
|
|
33
|
+
async prepare() {
|
|
34
|
+
await getPlayer();
|
|
35
|
+
},
|
|
36
|
+
async createTracks(request) {
|
|
37
|
+
const player = await getPlayer(request.signal);
|
|
38
|
+
const source = request.kind === "audio" ? player.audio : player.video;
|
|
39
|
+
if (!source) {
|
|
40
|
+
throw (0, errors_1.createWebRtcDomException)("NotFoundError", `mp4/webm source has no ${request.kind} track`);
|
|
41
|
+
}
|
|
42
|
+
const track = source.clone();
|
|
43
|
+
applyInspectedOrExplicitCodec(source, track, request.kind, options.codecs?.[request.kind]);
|
|
44
|
+
liveTracks.add(track);
|
|
45
|
+
(0, trackStop_1.bindOwnTrackStop)(track, () => {
|
|
46
|
+
liveTracks.delete(track);
|
|
47
|
+
if (liveTracks.size === 0) {
|
|
48
|
+
releasePlayer();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
if (!started) {
|
|
52
|
+
started = true;
|
|
53
|
+
void player.start().catch(() => undefined);
|
|
54
|
+
}
|
|
55
|
+
return [track];
|
|
56
|
+
},
|
|
57
|
+
stop() {
|
|
58
|
+
ioAbort.abort();
|
|
59
|
+
for (const track of [...liveTracks]) {
|
|
60
|
+
track.stop();
|
|
61
|
+
}
|
|
62
|
+
liveTracks.clear();
|
|
63
|
+
releasePlayer();
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
return register;
|
|
67
|
+
function releasePlayer() {
|
|
68
|
+
started = false;
|
|
69
|
+
const pending = playerPromise;
|
|
70
|
+
playerPromise = undefined;
|
|
71
|
+
void pending?.then((player) => player.stop(), () => undefined);
|
|
72
|
+
}
|
|
73
|
+
async function getPlayer(signal) {
|
|
74
|
+
const onAbort = () => ioAbort.abort();
|
|
75
|
+
if (signal?.aborted) {
|
|
76
|
+
ioAbort.abort();
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
80
|
+
}
|
|
81
|
+
playerPromise ?? (playerPromise = (async () => {
|
|
82
|
+
try {
|
|
83
|
+
resolvedFile ?? (resolvedFile = await resolveFile(options, ioAbort.signal));
|
|
84
|
+
const player = await (0, userMedia_1.createFileMediaPlayer)({
|
|
85
|
+
loop: options.loop,
|
|
86
|
+
...resolvedFile,
|
|
87
|
+
});
|
|
88
|
+
applyInspectedMetadata(resolvedFile, player);
|
|
89
|
+
return player;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
playerPromise = undefined;
|
|
93
|
+
throw mapMediaIoError(error);
|
|
94
|
+
}
|
|
95
|
+
})());
|
|
96
|
+
try {
|
|
97
|
+
return await playerPromise;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
signal?.removeEventListener("abort", onAbort);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function applyInspectedMetadata(file, player) {
|
|
104
|
+
kinds.splice(0, kinds.length, ...kindsFromPlayer(player));
|
|
105
|
+
const container = containerOf(options, "buffer" in file ? file.buffer : undefined);
|
|
106
|
+
mimeType = mimeTypeFromContainer(container, kinds);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function initialKinds(options) {
|
|
110
|
+
if ("binary" in options && options.binary != undefined) {
|
|
111
|
+
return (inspectKindsFromBuffer((0, sourceIo_1.toBuffer)(options.binary)) ?? ["audio", "video"]);
|
|
112
|
+
}
|
|
113
|
+
return ["audio", "video"];
|
|
114
|
+
}
|
|
115
|
+
function initialMimeType(options) {
|
|
116
|
+
const kinds = initialKinds(options);
|
|
117
|
+
return mimeTypeFromContainer(containerOf(options), kinds);
|
|
118
|
+
}
|
|
119
|
+
function containerOf(options, buffer) {
|
|
120
|
+
if (buffer) {
|
|
121
|
+
return (0, sourceIo_1.isWebmContainer)(buffer) ? "webm" : "mp4";
|
|
122
|
+
}
|
|
123
|
+
if ("path" in options && options.path != undefined) {
|
|
124
|
+
return containerFromPath(options.path);
|
|
125
|
+
}
|
|
126
|
+
if ("binary" in options && options.binary != undefined) {
|
|
127
|
+
return (0, sourceIo_1.isWebmContainer)((0, sourceIo_1.toBuffer)(options.binary)) ? "webm" : "mp4";
|
|
128
|
+
}
|
|
129
|
+
return "mp4";
|
|
130
|
+
}
|
|
131
|
+
async function resolveFile(options, signal) {
|
|
132
|
+
if ("path" in options && options.path != undefined) {
|
|
133
|
+
return { path: options.path };
|
|
134
|
+
}
|
|
135
|
+
if ("binary" in options && options.binary != undefined) {
|
|
136
|
+
return { buffer: (0, sourceIo_1.toBuffer)(options.binary) };
|
|
137
|
+
}
|
|
138
|
+
return { buffer: await (0, sourceIo_1.readEntireStream)(options.stream, signal) };
|
|
139
|
+
}
|
|
140
|
+
function kindsFromPlayer(player) {
|
|
141
|
+
const next = [];
|
|
142
|
+
if (player.audio) {
|
|
143
|
+
next.push("audio");
|
|
144
|
+
}
|
|
145
|
+
if (player.video) {
|
|
146
|
+
next.push("video");
|
|
147
|
+
}
|
|
148
|
+
return next;
|
|
149
|
+
}
|
|
150
|
+
function containerFromPath(path) {
|
|
151
|
+
const lower = path.toLowerCase();
|
|
152
|
+
if (lower.endsWith(".webm") || lower.endsWith(".weba")) {
|
|
153
|
+
return "webm";
|
|
154
|
+
}
|
|
155
|
+
return "mp4";
|
|
156
|
+
}
|
|
157
|
+
function mimeTypeFromContainer(container, kinds) {
|
|
158
|
+
const hasVideo = kinds.includes("video");
|
|
159
|
+
if (container === "webm") {
|
|
160
|
+
return hasVideo ? "video/webm" : "audio/webm";
|
|
161
|
+
}
|
|
162
|
+
return hasVideo ? "video/mp4" : "audio/mp4";
|
|
163
|
+
}
|
|
164
|
+
function inspectKindsFromBuffer(buffer) {
|
|
165
|
+
try {
|
|
166
|
+
const kinds = (0, sourceIo_1.isWebmContainer)(buffer)
|
|
167
|
+
? inspectWebmKinds(buffer)
|
|
168
|
+
: inspectMp4Kinds(buffer);
|
|
169
|
+
return kinds.length > 0 ? kinds : undefined;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function inspectMp4Kinds(buffer) {
|
|
176
|
+
const found = new Set();
|
|
177
|
+
for (let index = 4; index < buffer.length - 16; index++) {
|
|
178
|
+
if (buffer.toString("ascii", index, index + 4) !== "hdlr") {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const handler = buffer.toString("ascii", index + 12, index + 16);
|
|
182
|
+
if (handler === "soun") {
|
|
183
|
+
found.add("audio");
|
|
184
|
+
}
|
|
185
|
+
else if (handler === "vide") {
|
|
186
|
+
found.add("video");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return [...found];
|
|
190
|
+
}
|
|
191
|
+
function inspectWebmKinds(buffer) {
|
|
192
|
+
const found = new Set();
|
|
193
|
+
for (let index = 0; index < buffer.length - 2; index++) {
|
|
194
|
+
if (buffer[index] !== 0x83 || buffer[index + 1] !== 0x81) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const trackType = buffer[index + 2];
|
|
198
|
+
if (trackType === 0x01) {
|
|
199
|
+
found.add("video");
|
|
200
|
+
}
|
|
201
|
+
else if (trackType === 0x02) {
|
|
202
|
+
found.add("audio");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return [...found];
|
|
206
|
+
}
|
|
207
|
+
function mapMediaIoError(error) {
|
|
208
|
+
if (error instanceof DOMException) {
|
|
209
|
+
return error;
|
|
210
|
+
}
|
|
211
|
+
return (0, errors_1.createWebRtcDomException)("NotReadableError", error instanceof Error ? error.message : "Failed to read media source");
|
|
212
|
+
}
|
|
213
|
+
function applyInspectedOrExplicitCodec(source, track, kind, hint) {
|
|
214
|
+
const inspected = source.codec;
|
|
215
|
+
if (hint == undefined) {
|
|
216
|
+
if (inspected == undefined) {
|
|
217
|
+
throw (0, errors_1.createWebRtcDomException)("NotReadableError", `mp4/webm source has no RTP codec for ${kind}`);
|
|
218
|
+
}
|
|
219
|
+
track.codec = inspected;
|
|
220
|
+
(0, track_1.setTrackSourceCodecs)(track, [inspected]);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const explicit = resolveMp4WebmCodecHint(hint);
|
|
224
|
+
if (inspected &&
|
|
225
|
+
inspected.mimeType.toLowerCase() !== explicit.mimeType.toLowerCase()) {
|
|
226
|
+
throw new errors_1.OverconstrainedError("mimeType", `explicit ${kind} codec ${explicit.mimeType} does not match inspected ${inspected.mimeType}`);
|
|
227
|
+
}
|
|
228
|
+
source.codec = explicit;
|
|
229
|
+
track.codec = explicit;
|
|
230
|
+
(0, track_1.setTrackSourceCodecs)(source, [explicit]);
|
|
231
|
+
(0, track_1.setTrackSourceCodecs)(track, [explicit]);
|
|
232
|
+
}
|
|
233
|
+
function resolveMp4WebmCodecHint(hint) {
|
|
234
|
+
if (typeof hint === "string") {
|
|
235
|
+
return (0, rtpCodec_1.rtpCodecFromMimeType)({ mimeType: hint });
|
|
236
|
+
}
|
|
237
|
+
if (hint instanceof parameters_1.RTCRtpCodecParameters) {
|
|
238
|
+
return hint;
|
|
239
|
+
}
|
|
240
|
+
return (0, rtpCodec_1.rtpCodecFromMimeType)(hint);
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=mp4Webm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mp4Webm.js","sourceRoot":"","sources":["../../../../../src/polyfill/registers/mp4Webm.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Readable } from \"stream\";\n\nimport { OverconstrainedError, createWebRtcDomException } from \"../../errors\";\nimport { RTCRtpCodecParameters } from \"../../media/parameters\";\nimport { type MediaStreamTrack, setTrackSourceCodecs } from \"../../media/track\";\nimport { createFileMediaPlayer } from \"../../nonstandard/userMedia\";\nimport type {\n MediaGetUserMediaRequest,\n MediaKind,\n MediaRegister,\n MediaRegisterCommonOptions,\n} from \"../mediaRegister\";\nimport {\n type RtpCodecFromMimeTypeOptions,\n rtpCodecFromMimeType,\n} from \"../rtpCodec\";\nimport {\n type BinaryLike,\n isWebmContainer,\n readEntireStream,\n toBuffer,\n} from \"../sourceIo\";\nimport { bindOwnTrackStop } from \"../trackStop\";\n\ntype Mp4WebmSource =\n | { path: string; binary?: never; stream?: never }\n | { path?: never; binary: BinaryLike; stream?: never }\n | {\n path?: never;\n binary?: never;\n stream: Readable | ReadableStream<Uint8Array>;\n };\n\nexport type Mp4WebmCodecHint =\n | string\n | RtpCodecFromMimeTypeOptions\n | RTCRtpCodecParameters;\n\nexport type CreateMp4WebmRegisterOptions = Mp4WebmSource &\n MediaRegisterCommonOptions & {\n loop?: boolean;\n /**\n * RTP codecs advertised on acquired tracks.\n * Omitted kinds are filled from the container via mediabunny.\n */\n codecs?: {\n audio?: Mp4WebmCodecHint;\n video?: Mp4WebmCodecHint;\n };\n };\n\ntype FilePlayer = Awaited<ReturnType<typeof createFileMediaPlayer>>;\n\n/**\n * Synchronous factory. Container I/O and player setup run in `prepare` /\n * `createTracks`, so install does not open files or consume live streams.\n */\nexport function createMp4WebmRegister(\n options: CreateMp4WebmRegisterOptions,\n): MediaRegister {\n let mimeType = initialMimeType(options);\n const kinds: MediaKind[] = [...initialKinds(options)];\n let playerPromise: Promise<FilePlayer> | undefined;\n let resolvedFile: { path: string } | { buffer: Buffer } | undefined;\n let started = false;\n const liveTracks = new Set<MediaStreamTrack>();\n const ioAbort = new AbortController();\n\n const register: MediaRegister = {\n get mimeType() {\n return mimeType;\n },\n get kinds() {\n return kinds;\n },\n deviceId: options.deviceId,\n groupId: options.groupId,\n label: options.label,\n async prepare() {\n await getPlayer();\n },\n async createTracks(request: MediaGetUserMediaRequest) {\n const player = await getPlayer(request.signal);\n const source = request.kind === \"audio\" ? player.audio : player.video;\n if (!source) {\n throw createWebRtcDomException(\n \"NotFoundError\",\n `mp4/webm source has no ${request.kind} track`,\n );\n }\n const track = source.clone();\n applyInspectedOrExplicitCodec(\n source,\n track,\n request.kind,\n options.codecs?.[request.kind],\n );\n liveTracks.add(track);\n bindOwnTrackStop(track, () => {\n liveTracks.delete(track);\n if (liveTracks.size === 0) {\n releasePlayer();\n }\n });\n if (!started) {\n started = true;\n void player.start().catch(() => undefined);\n }\n return [track];\n },\n stop() {\n ioAbort.abort();\n for (const track of [...liveTracks]) {\n track.stop();\n }\n liveTracks.clear();\n releasePlayer();\n },\n };\n return register;\n\n function releasePlayer() {\n started = false;\n const pending = playerPromise;\n playerPromise = undefined;\n void pending?.then(\n (player) => player.stop(),\n () => undefined,\n );\n }\n\n async function getPlayer(signal?: AbortSignal) {\n const onAbort = () => ioAbort.abort();\n if (signal?.aborted) {\n ioAbort.abort();\n } else {\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n }\n playerPromise ??= (async () => {\n try {\n resolvedFile ??= await resolveFile(options, ioAbort.signal);\n const player = await createFileMediaPlayer({\n loop: options.loop,\n ...resolvedFile,\n });\n applyInspectedMetadata(resolvedFile, player);\n return player;\n } catch (error) {\n playerPromise = undefined;\n throw mapMediaIoError(error);\n }\n })();\n try {\n return await playerPromise;\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n function applyInspectedMetadata(\n file: { path: string } | { buffer: Buffer },\n player: FilePlayer,\n ) {\n kinds.splice(0, kinds.length, ...kindsFromPlayer(player));\n const container = containerOf(\n options,\n \"buffer\" in file ? file.buffer : undefined,\n );\n mimeType = mimeTypeFromContainer(container, kinds);\n }\n}\n\nfunction initialKinds(options: CreateMp4WebmRegisterOptions): MediaKind[] {\n if (\"binary\" in options && options.binary != undefined) {\n return (\n inspectKindsFromBuffer(toBuffer(options.binary)) ?? [\"audio\", \"video\"]\n );\n }\n return [\"audio\", \"video\"];\n}\n\nfunction initialMimeType(options: CreateMp4WebmRegisterOptions): string {\n const kinds = initialKinds(options);\n return mimeTypeFromContainer(containerOf(options), kinds);\n}\n\nfunction containerOf(\n options: CreateMp4WebmRegisterOptions,\n buffer?: Buffer,\n): \"webm\" | \"mp4\" {\n if (buffer) {\n return isWebmContainer(buffer) ? \"webm\" : \"mp4\";\n }\n if (\"path\" in options && options.path != undefined) {\n return containerFromPath(options.path);\n }\n if (\"binary\" in options && options.binary != undefined) {\n return isWebmContainer(toBuffer(options.binary)) ? \"webm\" : \"mp4\";\n }\n return \"mp4\";\n}\n\nasync function resolveFile(\n options: CreateMp4WebmRegisterOptions,\n signal: AbortSignal,\n): Promise<{ path: string } | { buffer: Buffer }> {\n if (\"path\" in options && options.path != undefined) {\n return { path: options.path };\n }\n if (\"binary\" in options && options.binary != undefined) {\n return { buffer: toBuffer(options.binary) };\n }\n return { buffer: await readEntireStream(options.stream, signal) };\n}\n\nfunction kindsFromPlayer(player: FilePlayer): MediaKind[] {\n const next: MediaKind[] = [];\n if (player.audio) {\n next.push(\"audio\");\n }\n if (player.video) {\n next.push(\"video\");\n }\n return next;\n}\n\nfunction containerFromPath(path: string): \"webm\" | \"mp4\" {\n const lower = path.toLowerCase();\n if (lower.endsWith(\".webm\") || lower.endsWith(\".weba\")) {\n return \"webm\";\n }\n return \"mp4\";\n}\n\nfunction mimeTypeFromContainer(\n container: \"webm\" | \"mp4\",\n kinds: readonly MediaKind[],\n): string {\n const hasVideo = kinds.includes(\"video\");\n if (container === \"webm\") {\n return hasVideo ? \"video/webm\" : \"audio/webm\";\n }\n return hasVideo ? \"video/mp4\" : \"audio/mp4\";\n}\n\nfunction inspectKindsFromBuffer(buffer: Buffer): MediaKind[] | undefined {\n try {\n const kinds = isWebmContainer(buffer)\n ? inspectWebmKinds(buffer)\n : inspectMp4Kinds(buffer);\n return kinds.length > 0 ? kinds : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction inspectMp4Kinds(buffer: Buffer): MediaKind[] {\n const found = new Set<MediaKind>();\n for (let index = 4; index < buffer.length - 16; index++) {\n if (buffer.toString(\"ascii\", index, index + 4) !== \"hdlr\") {\n continue;\n }\n const handler = buffer.toString(\"ascii\", index + 12, index + 16);\n if (handler === \"soun\") {\n found.add(\"audio\");\n } else if (handler === \"vide\") {\n found.add(\"video\");\n }\n }\n return [...found];\n}\n\nfunction inspectWebmKinds(buffer: Buffer): MediaKind[] {\n const found = new Set<MediaKind>();\n for (let index = 0; index < buffer.length - 2; index++) {\n if (buffer[index] !== 0x83 || buffer[index + 1] !== 0x81) {\n continue;\n }\n const trackType = buffer[index + 2];\n if (trackType === 0x01) {\n found.add(\"video\");\n } else if (trackType === 0x02) {\n found.add(\"audio\");\n }\n }\n return [...found];\n}\n\nfunction mapMediaIoError(error: unknown) {\n if (error instanceof DOMException) {\n return error;\n }\n return createWebRtcDomException(\n \"NotReadableError\",\n error instanceof Error ? error.message : \"Failed to read media source\",\n );\n}\n\nfunction applyInspectedOrExplicitCodec(\n source: MediaStreamTrack,\n track: MediaStreamTrack,\n kind: MediaKind,\n hint: Mp4WebmCodecHint | undefined,\n) {\n const inspected = source.codec;\n if (hint == undefined) {\n if (inspected == undefined) {\n throw createWebRtcDomException(\n \"NotReadableError\",\n `mp4/webm source has no RTP codec for ${kind}`,\n );\n }\n track.codec = inspected;\n setTrackSourceCodecs(track, [inspected]);\n return;\n }\n const explicit = resolveMp4WebmCodecHint(hint);\n if (\n inspected &&\n inspected.mimeType.toLowerCase() !== explicit.mimeType.toLowerCase()\n ) {\n throw new OverconstrainedError(\n \"mimeType\",\n `explicit ${kind} codec ${explicit.mimeType} does not match inspected ${inspected.mimeType}`,\n );\n }\n source.codec = explicit;\n track.codec = explicit;\n setTrackSourceCodecs(source, [explicit]);\n setTrackSourceCodecs(track, [explicit]);\n}\n\nfunction resolveMp4WebmCodecHint(\n hint: Mp4WebmCodecHint,\n): RTCRtpCodecParameters {\n if (typeof hint === \"string\") {\n return rtpCodecFromMimeType({ mimeType: hint });\n }\n if (hint instanceof RTCRtpCodecParameters) {\n return hint;\n }\n return rtpCodecFromMimeType(hint);\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Readable } from "stream";
|
|
2
|
+
import type { MediaRegister, MediaRegisterCommonOptions } from "../mediaRegister";
|
|
3
|
+
import { type UdpOrStreamSource } from "../sourceIo";
|
|
4
|
+
export type CreateRtpRtcpRegisterOptions = MediaRegisterCommonOptions & UdpOrStreamSource & {
|
|
5
|
+
mimeType: string;
|
|
6
|
+
clockRate?: number;
|
|
7
|
+
channels?: number;
|
|
8
|
+
payloadType?: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function createRtpRtcpRegister(options: CreateRtpRtcpRegisterOptions): MediaRegister;
|
|
11
|
+
export type CreateEncodedBinaryRegisterOptions = MediaRegisterCommonOptions & UdpOrStreamSource & {
|
|
12
|
+
mimeType: string;
|
|
13
|
+
clockRate?: number;
|
|
14
|
+
channels?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function createEncodedBinaryRegister(options: CreateEncodedBinaryRegisterOptions): MediaRegister;
|
|
17
|
+
export type { Readable };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRtpRtcpRegister = createRtpRtcpRegister;
|
|
4
|
+
exports.createEncodedBinaryRegister = createEncodedBinaryRegister;
|
|
5
|
+
const mediabunny_1 = require("mediabunny");
|
|
6
|
+
const rtp_1 = require("../../imports/rtp");
|
|
7
|
+
const track_1 = require("../../media/track");
|
|
8
|
+
const packetizer_1 = require("../../nonstandard/userMedia/packetizer");
|
|
9
|
+
const rtpCodec_1 = require("../rtpCodec");
|
|
10
|
+
const sourceIo_1 = require("../sourceIo");
|
|
11
|
+
const trackStop_1 = require("../trackStop");
|
|
12
|
+
function createRtpRtcpRegister(options) {
|
|
13
|
+
const kind = (0, rtpCodec_1.kindFromMimeType)(options.mimeType);
|
|
14
|
+
const codec = (0, rtpCodec_1.rtpCodecFromMimeType)(options);
|
|
15
|
+
const sessions = createSessionBag();
|
|
16
|
+
return {
|
|
17
|
+
mimeType: options.mimeType,
|
|
18
|
+
kinds: [kind],
|
|
19
|
+
deviceId: options.deviceId,
|
|
20
|
+
groupId: options.groupId,
|
|
21
|
+
label: options.label,
|
|
22
|
+
async createTracks(request) {
|
|
23
|
+
(0, sourceIo_1.throwIfAborted)(request.signal);
|
|
24
|
+
const track = new track_1.MediaStreamTrack({ kind, codec });
|
|
25
|
+
return startTrackedAcquisition(sessions, request.signal, track, (signal) => (0, sourceIo_1.openPacketSource)(options, (packet) => {
|
|
26
|
+
if (isMuxedRtcp(packet)) {
|
|
27
|
+
try {
|
|
28
|
+
for (const rtcp of rtp_1.RtcpPacketConverter.deSerialize(packet)) {
|
|
29
|
+
track.writeRtcp(rtcp);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// drop unparsable RTCP
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
track.writeRtp(packet);
|
|
38
|
+
}, () => {
|
|
39
|
+
track.stopMediaSource();
|
|
40
|
+
}, signal, () => {
|
|
41
|
+
track.stopMediaSource();
|
|
42
|
+
}));
|
|
43
|
+
},
|
|
44
|
+
stop() {
|
|
45
|
+
sessions.stopAll();
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function createEncodedBinaryRegister(options) {
|
|
50
|
+
const kind = (0, rtpCodec_1.kindFromMimeType)(options.mimeType);
|
|
51
|
+
const sourceCodec = (0, rtpCodec_1.sourceCodecFromMimeType)(options.mimeType);
|
|
52
|
+
const codec = (0, rtpCodec_1.codecFromMimeType)(options);
|
|
53
|
+
const clockRate = options.clockRate ?? (0, rtpCodec_1.defaultClockRateForMimeType)(options.mimeType);
|
|
54
|
+
const sessions = createSessionBag();
|
|
55
|
+
return {
|
|
56
|
+
mimeType: options.mimeType,
|
|
57
|
+
kinds: [kind],
|
|
58
|
+
deviceId: options.deviceId,
|
|
59
|
+
groupId: options.groupId,
|
|
60
|
+
label: options.label,
|
|
61
|
+
async createTracks(request) {
|
|
62
|
+
(0, sourceIo_1.throwIfAborted)(request.signal);
|
|
63
|
+
const packetizer = (0, packetizer_1.createPacketizer)({
|
|
64
|
+
codec,
|
|
65
|
+
sourceCodec,
|
|
66
|
+
});
|
|
67
|
+
const track = new track_1.MediaStreamTrack({ kind, codec });
|
|
68
|
+
let lastReceivedAt;
|
|
69
|
+
let rtpTimestamp = 0;
|
|
70
|
+
return startTrackedAcquisition(sessions, request.signal, track, (signal) => (0, sourceIo_1.openPacketSource)(options, (accessUnit) => {
|
|
71
|
+
const now = performance.now();
|
|
72
|
+
if (lastReceivedAt != undefined) {
|
|
73
|
+
const elapsedSeconds = Math.max(0, (now - lastReceivedAt) / 1000);
|
|
74
|
+
rtpTimestamp =
|
|
75
|
+
(rtpTimestamp + Math.round(elapsedSeconds * clockRate)) >>> 0;
|
|
76
|
+
}
|
|
77
|
+
lastReceivedAt = now;
|
|
78
|
+
// EncodedPacket requires a non-negative duration. Packetizers
|
|
79
|
+
// read only data/type, and RTP timestamps come from AU arrival
|
|
80
|
+
// intervals above, so this dummy value does not affect sent
|
|
81
|
+
// packets.
|
|
82
|
+
const encoded = new mediabunny_1.EncodedPacket(new Uint8Array(accessUnit), "key", rtpTimestamp / clockRate, 1 / 30);
|
|
83
|
+
for (const rtp of packetizer.packetize(encoded, rtpTimestamp)) {
|
|
84
|
+
track.writeRtp(rtp);
|
|
85
|
+
}
|
|
86
|
+
}, () => {
|
|
87
|
+
track.stopMediaSource();
|
|
88
|
+
}, signal, () => {
|
|
89
|
+
track.stopMediaSource();
|
|
90
|
+
}));
|
|
91
|
+
},
|
|
92
|
+
stop() {
|
|
93
|
+
sessions.stopAll();
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function createSessionBag() {
|
|
98
|
+
const sessions = new Set();
|
|
99
|
+
return {
|
|
100
|
+
add(stop) {
|
|
101
|
+
sessions.add(stop);
|
|
102
|
+
},
|
|
103
|
+
remove(stop) {
|
|
104
|
+
sessions.delete(stop);
|
|
105
|
+
},
|
|
106
|
+
stopAll() {
|
|
107
|
+
for (const stop of [...sessions]) {
|
|
108
|
+
stop();
|
|
109
|
+
}
|
|
110
|
+
sessions.clear();
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async function startTrackedAcquisition(sessions, signal, track, open) {
|
|
115
|
+
let stopSource = () => undefined;
|
|
116
|
+
const stopSession = () => {
|
|
117
|
+
sessions.remove(stopSession);
|
|
118
|
+
stopSource();
|
|
119
|
+
};
|
|
120
|
+
sessions.add(stopSession);
|
|
121
|
+
try {
|
|
122
|
+
stopSource = await open(signal);
|
|
123
|
+
(0, sourceIo_1.throwIfAborted)(signal);
|
|
124
|
+
(0, trackStop_1.bindTrackStop)(track, stopSession);
|
|
125
|
+
return [track];
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
stopSession();
|
|
129
|
+
track.stop();
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function isMuxedRtcp(packet) {
|
|
134
|
+
if ((0, rtp_1.isRtcp)(packet)) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
if (packet.length < 2) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const payloadType = packet[1] & 0x7f;
|
|
141
|
+
return payloadType >= 64 && payloadType <= 95;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=rtpRtcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtpRtcp.js","sourceRoot":"","sources":["../../../../../src/polyfill/registers/rtpRtcp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Readable } from \"stream\";\n\nimport { EncodedPacket } from \"mediabunny\";\n\nimport { RtcpPacketConverter, isRtcp } from \"../../imports/rtp\";\nimport { MediaStreamTrack } from \"../../media/track\";\nimport { createPacketizer } from \"../../nonstandard/userMedia/packetizer\";\nimport type {\n MediaGetUserMediaRequest,\n MediaRegister,\n MediaRegisterCommonOptions,\n} from \"../mediaRegister\";\nimport {\n codecFromMimeType,\n defaultClockRateForMimeType,\n kindFromMimeType,\n rtpCodecFromMimeType,\n sourceCodecFromMimeType,\n} from \"../rtpCodec\";\nimport {\n type UdpOrStreamSource,\n openPacketSource,\n throwIfAborted,\n} from \"../sourceIo\";\nimport { bindTrackStop } from \"../trackStop\";\n\nexport type CreateRtpRtcpRegisterOptions = MediaRegisterCommonOptions &\n UdpOrStreamSource & {\n mimeType: string;\n clockRate?: number;\n channels?: number;\n payloadType?: number;\n };\n\nexport function createRtpRtcpRegister(\n options: CreateRtpRtcpRegisterOptions,\n): MediaRegister {\n const kind = kindFromMimeType(options.mimeType);\n const codec = rtpCodecFromMimeType(options);\n const sessions = createSessionBag();\n\n return {\n mimeType: options.mimeType,\n kinds: [kind],\n deviceId: options.deviceId,\n groupId: options.groupId,\n label: options.label,\n async createTracks(request: MediaGetUserMediaRequest) {\n throwIfAborted(request.signal);\n const track = new MediaStreamTrack({ kind, codec });\n return startTrackedAcquisition(\n sessions,\n request.signal,\n track,\n (signal) =>\n openPacketSource(\n options,\n (packet) => {\n if (isMuxedRtcp(packet)) {\n try {\n for (const rtcp of RtcpPacketConverter.deSerialize(packet)) {\n track.writeRtcp(rtcp);\n }\n } catch {\n // drop unparsable RTCP\n }\n return;\n }\n track.writeRtp(packet);\n },\n () => {\n track.stopMediaSource();\n },\n signal,\n () => {\n track.stopMediaSource();\n },\n ),\n );\n },\n stop() {\n sessions.stopAll();\n },\n };\n}\n\nexport type CreateEncodedBinaryRegisterOptions = MediaRegisterCommonOptions &\n UdpOrStreamSource & {\n mimeType: string;\n clockRate?: number;\n channels?: number;\n };\n\nexport function createEncodedBinaryRegister(\n options: CreateEncodedBinaryRegisterOptions,\n): MediaRegister {\n const kind = kindFromMimeType(options.mimeType);\n const sourceCodec = sourceCodecFromMimeType(options.mimeType);\n const codec = codecFromMimeType(options);\n const clockRate =\n options.clockRate ?? defaultClockRateForMimeType(options.mimeType);\n const sessions = createSessionBag();\n\n return {\n mimeType: options.mimeType,\n kinds: [kind],\n deviceId: options.deviceId,\n groupId: options.groupId,\n label: options.label,\n async createTracks(request: MediaGetUserMediaRequest) {\n throwIfAborted(request.signal);\n const packetizer = createPacketizer({\n codec,\n sourceCodec,\n });\n const track = new MediaStreamTrack({ kind, codec });\n let lastReceivedAt: number | undefined;\n let rtpTimestamp = 0;\n return startTrackedAcquisition(\n sessions,\n request.signal,\n track,\n (signal) =>\n openPacketSource(\n options,\n (accessUnit) => {\n const now = performance.now();\n if (lastReceivedAt != undefined) {\n const elapsedSeconds = Math.max(\n 0,\n (now - lastReceivedAt) / 1_000,\n );\n rtpTimestamp =\n (rtpTimestamp + Math.round(elapsedSeconds * clockRate)) >>> 0;\n }\n lastReceivedAt = now;\n // EncodedPacket requires a non-negative duration. Packetizers\n // read only data/type, and RTP timestamps come from AU arrival\n // intervals above, so this dummy value does not affect sent\n // packets.\n const encoded = new EncodedPacket(\n new Uint8Array(accessUnit),\n \"key\",\n rtpTimestamp / clockRate,\n 1 / 30,\n );\n for (const rtp of packetizer.packetize(encoded, rtpTimestamp)) {\n track.writeRtp(rtp);\n }\n },\n () => {\n track.stopMediaSource();\n },\n signal,\n () => {\n track.stopMediaSource();\n },\n ),\n );\n },\n stop() {\n sessions.stopAll();\n },\n };\n}\n\nfunction createSessionBag() {\n const sessions = new Set<() => void>();\n return {\n add(stop: () => void) {\n sessions.add(stop);\n },\n remove(stop: () => void) {\n sessions.delete(stop);\n },\n stopAll() {\n for (const stop of [...sessions]) {\n stop();\n }\n sessions.clear();\n },\n };\n}\n\nasync function startTrackedAcquisition(\n sessions: ReturnType<typeof createSessionBag>,\n signal: AbortSignal | undefined,\n track: MediaStreamTrack,\n open: (signal?: AbortSignal) => Promise<() => void>,\n) {\n let stopSource = () => undefined as void;\n const stopSession = () => {\n sessions.remove(stopSession);\n stopSource();\n };\n sessions.add(stopSession);\n try {\n stopSource = await open(signal);\n throwIfAborted(signal);\n bindTrackStop(track, stopSession);\n return [track];\n } catch (error) {\n stopSession();\n track.stop();\n throw error;\n }\n}\n\nfunction isMuxedRtcp(packet: Buffer) {\n if (isRtcp(packet)) {\n return true;\n }\n if (packet.length < 2) {\n return false;\n }\n const payloadType = packet[1] & 0x7f;\n return payloadType >= 64 && payloadType <= 95;\n}\n\nexport type { Readable };\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type PolyfillSdpType = "offer" | "answer" | "pranswer" | "rollback";
|
|
2
|
+
export interface RTCSessionDescriptionInit {
|
|
3
|
+
type: PolyfillSdpType;
|
|
4
|
+
sdp?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Browser-compatible `RTCSessionDescription` constructor.
|
|
8
|
+
* Core `werift` still exports `(sdp, type)` for backward compatibility.
|
|
9
|
+
*/
|
|
10
|
+
export declare class PolyfillRTCSessionDescription {
|
|
11
|
+
readonly type: PolyfillSdpType;
|
|
12
|
+
readonly sdp: string;
|
|
13
|
+
constructor(init?: RTCSessionDescriptionInit);
|
|
14
|
+
toJSON(): {
|
|
15
|
+
type: PolyfillSdpType;
|
|
16
|
+
sdp: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PolyfillRTCSessionDescription = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Browser-compatible `RTCSessionDescription` constructor.
|
|
6
|
+
* Core `werift` still exports `(sdp, type)` for backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
class PolyfillRTCSessionDescription {
|
|
9
|
+
constructor(init = {}) {
|
|
10
|
+
Object.defineProperty(this, "type", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: void 0
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, "sdp", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
if (!init?.type) {
|
|
23
|
+
throw new TypeError("RTCSessionDescriptionInit.type is required");
|
|
24
|
+
}
|
|
25
|
+
this.type = init.type;
|
|
26
|
+
this.sdp = init.sdp ?? "";
|
|
27
|
+
}
|
|
28
|
+
toJSON() {
|
|
29
|
+
return {
|
|
30
|
+
type: this.type,
|
|
31
|
+
sdp: this.sdp,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.PolyfillRTCSessionDescription = PolyfillRTCSessionDescription;
|
|
36
|
+
//# sourceMappingURL=rtcSessionDescription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtcSessionDescription.js","sourceRoot":"","sources":["../../../../src/polyfill/rtcSessionDescription.ts"],"names":[],"mappings":";;;AAOA;;;GAGG;AACH,MAAa,6BAA6B;IAIxC,YACE,OAAkC,EAA+B;QAJ1D;;;;;WAAsB;QACtB;;;;;WAAY;QAKnB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC;IACJ,CAAC;CACF;AApBD,sEAoBC","sourcesContent":["export type PolyfillSdpType = \"offer\" | \"answer\" | \"pranswer\" | \"rollback\";\n\nexport interface RTCSessionDescriptionInit {\n type: PolyfillSdpType;\n sdp?: string;\n}\n\n/**\n * Browser-compatible `RTCSessionDescription` constructor.\n * Core `werift` still exports `(sdp, type)` for backward compatibility.\n */\nexport class PolyfillRTCSessionDescription {\n readonly type: PolyfillSdpType;\n readonly sdp: string;\n\n constructor(\n init: RTCSessionDescriptionInit = {} as RTCSessionDescriptionInit,\n ) {\n if (!init?.type) {\n throw new TypeError(\"RTCSessionDescriptionInit.type is required\");\n }\n this.type = init.type;\n this.sdp = init.sdp ?? \"\";\n }\n\n toJSON() {\n return {\n type: this.type,\n sdp: this.sdp,\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RTCRtpCodecParameters } from "../media/parameters";
|
|
2
|
+
import type { SupportedSourceCodec } from "../nonstandard/userMedia/packetizer";
|
|
3
|
+
import type { MediaKind } from "./mediaRegister";
|
|
4
|
+
export type RtpCodecFromMimeTypeOptions = {
|
|
5
|
+
mimeType: string;
|
|
6
|
+
clockRate?: number;
|
|
7
|
+
channels?: number;
|
|
8
|
+
payloadType?: number;
|
|
9
|
+
parameters?: string;
|
|
10
|
+
rtcpFeedback?: RTCRtpCodecParameters["rtcpFeedback"];
|
|
11
|
+
};
|
|
12
|
+
export declare function kindFromMimeType(mimeType: string): MediaKind;
|
|
13
|
+
/** WebRTC RTP clockRate when the register omits `clockRate` (RFC 3551 / 7587 / video 90 kHz). */
|
|
14
|
+
export declare function defaultClockRateForMimeType(mimeType: string): number;
|
|
15
|
+
export declare function rtpCodecFromMimeType(options: RtpCodecFromMimeTypeOptions): RTCRtpCodecParameters;
|
|
16
|
+
export declare function sourceCodecFromMimeType(mimeType: string): SupportedSourceCodec;
|
|
17
|
+
export declare function codecFromMimeType(options: RtpCodecFromMimeTypeOptions): RTCRtpCodecParameters;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.kindFromMimeType = kindFromMimeType;
|
|
4
|
+
exports.defaultClockRateForMimeType = defaultClockRateForMimeType;
|
|
5
|
+
exports.rtpCodecFromMimeType = rtpCodecFromMimeType;
|
|
6
|
+
exports.sourceCodecFromMimeType = sourceCodecFromMimeType;
|
|
7
|
+
exports.codecFromMimeType = codecFromMimeType;
|
|
8
|
+
const codec_1 = require("../media/codec");
|
|
9
|
+
const parameters_1 = require("../media/parameters");
|
|
10
|
+
function kindFromMimeType(mimeType) {
|
|
11
|
+
return mimeType.toLowerCase().startsWith("audio/") ? "audio" : "video";
|
|
12
|
+
}
|
|
13
|
+
/** WebRTC RTP clockRate when the register omits `clockRate` (RFC 3551 / 7587 / video 90 kHz). */
|
|
14
|
+
function defaultClockRateForMimeType(mimeType) {
|
|
15
|
+
const normalized = mimeType.toLowerCase();
|
|
16
|
+
if (normalized.includes("opus")) {
|
|
17
|
+
return 48000;
|
|
18
|
+
}
|
|
19
|
+
if (normalized.startsWith("audio/")) {
|
|
20
|
+
return 8000;
|
|
21
|
+
}
|
|
22
|
+
return 90000;
|
|
23
|
+
}
|
|
24
|
+
function rtpCodecFromMimeType(options) {
|
|
25
|
+
const extra = extraCodecFields(options);
|
|
26
|
+
const clockRate = extra.clockRate ?? defaultClockRateForMimeType(options.mimeType);
|
|
27
|
+
const withClockRate = { ...extra, clockRate };
|
|
28
|
+
const normalized = options.mimeType.toLowerCase();
|
|
29
|
+
if (normalized.includes("pcmu")) {
|
|
30
|
+
return (0, codec_1.usePCMU)(withClockRate);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
return codecFromMimeType({ ...options, clockRate });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return new parameters_1.RTCRtpCodecParameters({
|
|
37
|
+
mimeType: options.mimeType,
|
|
38
|
+
...withClockRate,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function sourceCodecFromMimeType(mimeType) {
|
|
43
|
+
const normalized = mimeType.toLowerCase();
|
|
44
|
+
if (normalized.includes("h264") || normalized.includes("avc")) {
|
|
45
|
+
return "avc";
|
|
46
|
+
}
|
|
47
|
+
if (normalized.includes("vp8")) {
|
|
48
|
+
return "vp8";
|
|
49
|
+
}
|
|
50
|
+
if (normalized.includes("vp9")) {
|
|
51
|
+
return "vp9";
|
|
52
|
+
}
|
|
53
|
+
if (normalized.includes("av1")) {
|
|
54
|
+
return "av1";
|
|
55
|
+
}
|
|
56
|
+
if (normalized.includes("opus")) {
|
|
57
|
+
return "opus";
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Unsupported encoded binary mimeType: ${mimeType}`);
|
|
60
|
+
}
|
|
61
|
+
function codecFromMimeType(options) {
|
|
62
|
+
const sourceCodec = sourceCodecFromMimeType(options.mimeType);
|
|
63
|
+
const extra = extraCodecFields(options);
|
|
64
|
+
extra.clockRate ?? (extra.clockRate = defaultClockRateForMimeType(options.mimeType));
|
|
65
|
+
switch (sourceCodec) {
|
|
66
|
+
case "avc":
|
|
67
|
+
return (0, codec_1.useH264)(extra);
|
|
68
|
+
case "vp8":
|
|
69
|
+
return (0, codec_1.useVP8)(extra);
|
|
70
|
+
case "vp9":
|
|
71
|
+
return (0, codec_1.useVP9)(extra);
|
|
72
|
+
case "av1":
|
|
73
|
+
return (0, codec_1.useAV1X)(extra);
|
|
74
|
+
case "opus":
|
|
75
|
+
return (0, codec_1.useOPUS)(extra);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function extraCodecFields(options) {
|
|
79
|
+
return {
|
|
80
|
+
...(options.clockRate != undefined ? { clockRate: options.clockRate } : {}),
|
|
81
|
+
...(options.channels != undefined ? { channels: options.channels } : {}),
|
|
82
|
+
...(options.payloadType != undefined
|
|
83
|
+
? { payloadType: options.payloadType }
|
|
84
|
+
: {}),
|
|
85
|
+
...(options.parameters != undefined
|
|
86
|
+
? { parameters: options.parameters }
|
|
87
|
+
: {}),
|
|
88
|
+
...(options.rtcpFeedback != undefined
|
|
89
|
+
? { rtcpFeedback: options.rtcpFeedback }
|
|
90
|
+
: {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=rtpCodec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtpCodec.js","sourceRoot":"","sources":["../../../../src/polyfill/rtpCodec.ts"],"names":[],"mappings":";;AAqBA,4CAEC;AAGD,kEASC;AAED,oDAmBC;AAED,0DAoBC;AAED,8CAkBC;AAlGD,0CAOwB;AACxB,oDAA4D;AAa5D,SAAgB,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACzE,CAAC;AAED,iGAAiG;AACjG,SAAgB,2BAA2B,CAAC,QAAgB;IAC1D,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,KAAM,CAAC;IAChB,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,OAAO,IAAK,CAAC;IACf,CAAC;IACD,OAAO,KAAM,CAAC;AAChB,CAAC;AAED,SAAgB,oBAAoB,CAClC,OAAoC;IAEpC,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,IAAI,2BAA2B,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAClD,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,IAAA,eAAO,EAAC,aAAa,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,CAAC;QACH,OAAO,iBAAiB,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,kCAAqB,CAAC;YAC/B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,GAAG,aAAa;SACjB,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAgB,uBAAuB,CACrC,QAAgB;IAEhB,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wCAAwC,QAAQ,EAAE,CAAC,CAAC;AACtE,CAAC;AAED,SAAgB,iBAAiB,CAC/B,OAAoC;IAEpC,MAAM,WAAW,GAAG,uBAAuB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxC,KAAK,CAAC,SAAS,KAAf,KAAK,CAAC,SAAS,GAAK,2BAA2B,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC;IAClE,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,KAAK;YACR,OAAO,IAAA,eAAO,EAAC,KAAK,CAAC,CAAC;QACxB,KAAK,KAAK;YACR,OAAO,IAAA,cAAM,EAAC,KAAK,CAAC,CAAC;QACvB,KAAK,KAAK;YACR,OAAO,IAAA,cAAM,EAAC,KAAK,CAAC,CAAC;QACvB,KAAK,KAAK;YACR,OAAO,IAAA,eAAO,EAAC,KAAK,CAAC,CAAC;QACxB,KAAK,MAAM;YACT,OAAO,IAAA,eAAO,EAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CACvB,OAAoC;IAEpC,OAAO;QACL,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,SAAS;YAClC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;YACtC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,SAAS;YACjC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;YACpC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,SAAS;YACnC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC","sourcesContent":["import {\n useAV1X,\n useH264,\n useOPUS,\n usePCMU,\n useVP8,\n useVP9,\n} from \"../media/codec\";\nimport { RTCRtpCodecParameters } from \"../media/parameters\";\nimport type { SupportedSourceCodec } from \"../nonstandard/userMedia/packetizer\";\nimport type { MediaKind } from \"./mediaRegister\";\n\nexport type RtpCodecFromMimeTypeOptions = {\n mimeType: string;\n clockRate?: number;\n channels?: number;\n payloadType?: number;\n parameters?: string;\n rtcpFeedback?: RTCRtpCodecParameters[\"rtcpFeedback\"];\n};\n\nexport function kindFromMimeType(mimeType: string): MediaKind {\n return mimeType.toLowerCase().startsWith(\"audio/\") ? \"audio\" : \"video\";\n}\n\n/** WebRTC RTP clockRate when the register omits `clockRate` (RFC 3551 / 7587 / video 90 kHz). */\nexport function defaultClockRateForMimeType(mimeType: string): number {\n const normalized = mimeType.toLowerCase();\n if (normalized.includes(\"opus\")) {\n return 48_000;\n }\n if (normalized.startsWith(\"audio/\")) {\n return 8_000;\n }\n return 90_000;\n}\n\nexport function rtpCodecFromMimeType(\n options: RtpCodecFromMimeTypeOptions,\n): RTCRtpCodecParameters {\n const extra = extraCodecFields(options);\n const clockRate =\n extra.clockRate ?? defaultClockRateForMimeType(options.mimeType);\n const withClockRate = { ...extra, clockRate };\n const normalized = options.mimeType.toLowerCase();\n if (normalized.includes(\"pcmu\")) {\n return usePCMU(withClockRate);\n }\n try {\n return codecFromMimeType({ ...options, clockRate });\n } catch {\n return new RTCRtpCodecParameters({\n mimeType: options.mimeType,\n ...withClockRate,\n });\n }\n}\n\nexport function sourceCodecFromMimeType(\n mimeType: string,\n): SupportedSourceCodec {\n const normalized = mimeType.toLowerCase();\n if (normalized.includes(\"h264\") || normalized.includes(\"avc\")) {\n return \"avc\";\n }\n if (normalized.includes(\"vp8\")) {\n return \"vp8\";\n }\n if (normalized.includes(\"vp9\")) {\n return \"vp9\";\n }\n if (normalized.includes(\"av1\")) {\n return \"av1\";\n }\n if (normalized.includes(\"opus\")) {\n return \"opus\";\n }\n throw new Error(`Unsupported encoded binary mimeType: ${mimeType}`);\n}\n\nexport function codecFromMimeType(\n options: RtpCodecFromMimeTypeOptions,\n): RTCRtpCodecParameters {\n const sourceCodec = sourceCodecFromMimeType(options.mimeType);\n const extra = extraCodecFields(options);\n extra.clockRate ??= defaultClockRateForMimeType(options.mimeType);\n switch (sourceCodec) {\n case \"avc\":\n return useH264(extra);\n case \"vp8\":\n return useVP8(extra);\n case \"vp9\":\n return useVP9(extra);\n case \"av1\":\n return useAV1X(extra);\n case \"opus\":\n return useOPUS(extra);\n }\n}\n\nfunction extraCodecFields(\n options: RtpCodecFromMimeTypeOptions,\n): Partial<RTCRtpCodecParameters> {\n return {\n ...(options.clockRate != undefined ? { clockRate: options.clockRate } : {}),\n ...(options.channels != undefined ? { channels: options.channels } : {}),\n ...(options.payloadType != undefined\n ? { payloadType: options.payloadType }\n : {}),\n ...(options.parameters != undefined\n ? { parameters: options.parameters }\n : {}),\n ...(options.rtcpFeedback != undefined\n ? { rtcpFeedback: options.rtcpFeedback }\n : {}),\n };\n}\n"]}
|