@gjsify/webrtc 0.3.15 → 0.3.17

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.
Files changed (37) hide show
  1. package/lib/esm/get-user-media.js +1 -108
  2. package/lib/esm/gst-enum-maps.js +1 -84
  3. package/lib/esm/gst-init.js +6 -28
  4. package/lib/esm/gst-stats-parser.js +1 -106
  5. package/lib/esm/gst-utils.js +1 -27
  6. package/lib/esm/index.js +1 -23
  7. package/lib/esm/media-device-info.js +1 -24
  8. package/lib/esm/media-devices.js +1 -158
  9. package/lib/esm/media-stream-track.js +1 -139
  10. package/lib/esm/media-stream.js +1 -79
  11. package/lib/esm/register/data-channel.js +1 -12
  12. package/lib/esm/register/error.js +1 -12
  13. package/lib/esm/register/media-devices.js +1 -11
  14. package/lib/esm/register/media.js +1 -16
  15. package/lib/esm/register/peer-connection.js +1 -20
  16. package/lib/esm/register.js +1 -5
  17. package/lib/esm/rtc-certificate.js +1 -66
  18. package/lib/esm/rtc-data-channel.js +1 -250
  19. package/lib/esm/rtc-dtls-transport.js +1 -42
  20. package/lib/esm/rtc-dtmf-sender.js +1 -101
  21. package/lib/esm/rtc-error.js +1 -26
  22. package/lib/esm/rtc-events.js +1 -35
  23. package/lib/esm/rtc-ice-candidate.js +1 -74
  24. package/lib/esm/rtc-ice-transport.js +1 -97
  25. package/lib/esm/rtc-peer-connection.js +1 -812
  26. package/lib/esm/rtc-rtp-receiver.js +1 -93
  27. package/lib/esm/rtc-rtp-sender.js +1 -290
  28. package/lib/esm/rtc-rtp-transceiver.js +1 -96
  29. package/lib/esm/rtc-sctp-transport.js +1 -40
  30. package/lib/esm/rtc-session-description.js +1 -53
  31. package/lib/esm/rtc-stats-report.js +1 -40
  32. package/lib/esm/rtc-track-event.js +1 -31
  33. package/lib/esm/rtp-capabilities.js +1 -87
  34. package/lib/esm/tee-multiplexer.js +1 -60
  35. package/lib/esm/wpt-helpers.js +1 -138
  36. package/package.json +14 -14
  37. package/tsconfig.tsbuildinfo +1 -1
@@ -1,93 +1 @@
1
- import { MediaStreamTrack } from "./media-stream-track.js";
2
- import { getRtpCapabilities } from "./rtp-capabilities.js";
3
- import { ReceiverBridge } from "@gjsify/webrtc-native";
4
-
5
- //#region src/rtc-rtp-receiver.ts
6
- const MAX_JITTER_BUFFER_TARGET = 4e3;
7
- var RTCRtpReceiver = class {
8
- _gstReceiver;
9
- _track;
10
- _jitterBufferTarget = null;
11
- _pipeline = null;
12
- _receiverBridge = null;
13
- /** @internal — stats callback set by RTCPeerConnection */
14
- _getStatsForTrack = null;
15
- constructor(kind, gstReceiver, pipeline) {
16
- this._gstReceiver = gstReceiver;
17
- this._pipeline = pipeline ?? null;
18
- this._track = new MediaStreamTrack({
19
- kind,
20
- muted: true
21
- });
22
- }
23
- /** @internal — called from RTCPeerConnection._handlePadAdded */
24
- _connectToPad(pad) {
25
- if (!this._pipeline || this._receiverBridge) return;
26
- this._receiverBridge = new ReceiverBridge({
27
- pipeline: this._pipeline,
28
- kind: this._track.kind
29
- });
30
- this._receiverBridge.connect_to_pad(pad);
31
- this._receiverBridge.connect("media-flowing", () => {
32
- this._track._setMuted(false);
33
- });
34
- }
35
- /** @internal — called from RTCPeerConnection.close() */
36
- _dispose() {
37
- try {
38
- this._receiverBridge?.dispose_bridge();
39
- } catch {}
40
- this._receiverBridge = null;
41
- }
42
- /** @internal — set by RTCPeerConnection */
43
- _transport = null;
44
- get track() {
45
- return this._track;
46
- }
47
- get transport() {
48
- return this._transport;
49
- }
50
- get jitterBufferTarget() {
51
- return this._jitterBufferTarget;
52
- }
53
- set jitterBufferTarget(v) {
54
- if (v === null) {
55
- this._jitterBufferTarget = null;
56
- return;
57
- }
58
- const n = Number(v);
59
- if (!Number.isFinite(n) || n < 0) {
60
- throw new RangeError(`Failed to set jitterBufferTarget: ${v} is negative or not finite`);
61
- }
62
- if (n > MAX_JITTER_BUFFER_TARGET) {
63
- throw new RangeError(`Failed to set jitterBufferTarget: ${v} exceeds maximum of ${MAX_JITTER_BUFFER_TARGET}`);
64
- }
65
- this._jitterBufferTarget = n;
66
- }
67
- getParameters() {
68
- return {
69
- codecs: [],
70
- headerExtensions: [],
71
- rtcp: {}
72
- };
73
- }
74
- getContributingSources() {
75
- return [];
76
- }
77
- getSynchronizationSources() {
78
- return [];
79
- }
80
- async getStats() {
81
- if (this._getStatsForTrack && this._track) {
82
- return this._getStatsForTrack(this._track);
83
- }
84
- const { RTCStatsReport: Report } = await import("./rtc-stats-report.js");
85
- return new Report();
86
- }
87
- static getCapabilities(kind) {
88
- return getRtpCapabilities(kind);
89
- }
90
- };
91
-
92
- //#endregion
93
- export { RTCRtpReceiver };
1
+ import{MediaStreamTrack as e}from"./media-stream-track.js";import{getRtpCapabilities as t}from"./rtp-capabilities.js";import{ReceiverBridge as n}from"@gjsify/webrtc-native";const r=4e3;var i=class{_gstReceiver;_track;_jitterBufferTarget=null;_pipeline=null;_receiverBridge=null;_getStatsForTrack=null;constructor(t,n,r){this._gstReceiver=n,this._pipeline=r??null,this._track=new e({kind:t,muted:!0})}_connectToPad(e){!this._pipeline||this._receiverBridge||(this._receiverBridge=new n({pipeline:this._pipeline,kind:this._track.kind}),this._receiverBridge.connect_to_pad(e),this._receiverBridge.connect(`media-flowing`,()=>{this._track._setMuted(!1)}))}_dispose(){try{this._receiverBridge?.dispose_bridge()}catch{}this._receiverBridge=null}_transport=null;get track(){return this._track}get transport(){return this._transport}get jitterBufferTarget(){return this._jitterBufferTarget}set jitterBufferTarget(e){if(e===null){this._jitterBufferTarget=null;return}let t=Number(e);if(!Number.isFinite(t)||t<0)throw RangeError(`Failed to set jitterBufferTarget: ${e} is negative or not finite`);if(t>r)throw RangeError(`Failed to set jitterBufferTarget: ${e} exceeds maximum of ${r}`);this._jitterBufferTarget=t}getParameters(){return{codecs:[],headerExtensions:[],rtcp:{}}}getContributingSources(){return[]}getSynchronizationSources(){return[]}async getStats(){if(this._getStatsForTrack&&this._track)return this._getStatsForTrack(this._track);let{RTCStatsReport:e}=await import(`./rtc-stats-report.js`);return new e}static getCapabilities(e){return t(e)}};export{i as RTCRtpReceiver};
@@ -1,290 +1 @@
1
- import { Gst } from "./gst-init.js";
2
- import { getRtpCapabilities } from "./rtp-capabilities.js";
3
- import { RTCDTMFSender } from "./rtc-dtmf-sender.js";
4
- import { TeeMultiplexer } from "./tee-multiplexer.js";
5
-
6
- //#region src/rtc-rtp-sender.ts
7
- const OPUS_PAYLOAD_TYPE = 111;
8
- const VP8_PAYLOAD_TYPE = 96;
9
- let _txCounter = 0;
10
- var RTCRtpSender = class {
11
- _gstSender;
12
- _track = null;
13
- _lastParams = null;
14
- /** @internal GStreamer pipeline references (set by RTCPeerConnection) */
15
- _pipeline = null;
16
- _webrtcbin = null;
17
- _mlineIndex = -1;
18
- _elements = [];
19
- _valve = null;
20
- _linked = false;
21
- /** @internal — tee src pad if this sender uses a shared source */
22
- _teeSrcPad = null;
23
- /** @internal — stats callback set by RTCPeerConnection */
24
- _getStatsForTrack = null;
25
- /** @internal — set by RTCPeerConnection */
26
- _transport = null;
27
- /** @internal — DTMF sender, created lazily for audio senders */
28
- _dtmf = null;
29
- /** @internal — the kind of media this sender handles */
30
- _kind = null;
31
- /** @internal — back-reference for DTMF stopped/direction checks */
32
- _transceiver = null;
33
- /** @internal — callback to notify RTCPeerConnection when pipeline changes (cross-pipeline fix) */
34
- _onPipelineChanged = null;
35
- constructor(gstSender, pipeline, webrtcbin) {
36
- this._gstSender = gstSender;
37
- this._pipeline = pipeline ?? null;
38
- this._webrtcbin = webrtcbin ?? null;
39
- }
40
- get track() {
41
- return this._track;
42
- }
43
- /** Returns the DTMF sender for audio senders, null for video. */
44
- get dtmf() {
45
- const kind = this._track?.kind ?? this._kind;
46
- if (kind !== "audio") return null;
47
- if (!this._dtmf) {
48
- const dtmf = new RTCDTMFSender();
49
- dtmf._isStopped = () => this._transceiver?.stopped ?? false;
50
- dtmf._getCurrentDirection = () => this._transceiver?.currentDirection ?? null;
51
- this._dtmf = dtmf;
52
- }
53
- return this._dtmf;
54
- }
55
- get transport() {
56
- return this._transport;
57
- }
58
- /** @internal */
59
- _setTrack(track) {
60
- if (track === null && this._linked) {
61
- this._teardownPipeline();
62
- }
63
- this._track = track;
64
- }
65
- /** @internal — called by RTCPeerConnection._createTransceiverWrapper */
66
- _setMlineIndex(index) {
67
- this._mlineIndex = index;
68
- }
69
- /** @internal — build the outgoing encoder chain and link to webrtcbin */
70
- _wirePipeline(track) {
71
- if (this._linked || !this._pipeline || !this._webrtcbin) return;
72
- const source = track._gstSource;
73
- if (!source) return;
74
- const trackAny = track;
75
- let sourceForChain;
76
- if (trackAny._gstTee && trackAny._gstPipeline && trackAny._gstPipeline !== this._pipeline) {
77
- const sourcePipeline = trackAny._gstPipeline;
78
- const tee = trackAny._gstTee;
79
- if (this._webrtcbin.get_parent() === this._pipeline) {
80
- this._pipeline.set_state(Gst.State.NULL);
81
- this._pipeline.remove(this._webrtcbin);
82
- }
83
- sourcePipeline.add(this._webrtcbin);
84
- this._webrtcbin.sync_state_with_parent();
85
- this._pipeline = sourcePipeline;
86
- this._onPipelineChanged?.(sourcePipeline);
87
- const teeSrcPad = tee.request_pad_simple ? tee.request_pad_simple("src_%u") : tee.get_request_pad("src_%u");
88
- this._teeSrcPad = teeSrcPad;
89
- sourceForChain = null;
90
- } else if (trackAny._teeMultiplexer) {
91
- const tee = trackAny._teeMultiplexer;
92
- const teeSrcPad = tee.requestSrcPad();
93
- this._teeSrcPad = teeSrcPad;
94
- sourceForChain = null;
95
- } else if (trackAny._gstPipeline && trackAny._gstPipeline !== this._pipeline) {
96
- const oldPipeline = trackAny._gstPipeline;
97
- const sourceSrcPad = source.get_static_pad("src");
98
- const oldPeer = sourceSrcPad?.get_peer?.();
99
- if (oldPeer) sourceSrcPad.unlink(oldPeer);
100
- source.set_state(Gst.State.NULL);
101
- oldPipeline.remove(source);
102
- this._pipeline.add(source);
103
- trackAny._gstPipeline = this._pipeline;
104
- const tee = new TeeMultiplexer(this._pipeline, source);
105
- trackAny._teeMultiplexer = tee;
106
- if (oldPeer) {
107
- const firstBranch = tee.requestSrcPad();
108
- if (firstBranch) firstBranch.link(oldPeer);
109
- }
110
- const teeSrcPad = tee.requestSrcPad();
111
- this._teeSrcPad = teeSrcPad;
112
- sourceForChain = null;
113
- } else {
114
- const oldPipeline = trackAny._gstPipeline;
115
- if (oldPipeline && oldPipeline !== this._pipeline) {
116
- source.set_state(Gst.State.NULL);
117
- oldPipeline.remove(source);
118
- trackAny._gstPipeline = this._pipeline;
119
- }
120
- if (source.get_parent() !== this._pipeline) {
121
- this._pipeline.add(source);
122
- }
123
- sourceForChain = source;
124
- }
125
- const valve = Gst.ElementFactory.make("valve", null);
126
- valve.drop = !track.enabled;
127
- this._valve = valve;
128
- this._pipeline.add(valve);
129
- const elements = [valve];
130
- let lastElement;
131
- if (track.kind === "audio") {
132
- const convert = Gst.ElementFactory.make("audioconvert", null);
133
- const resample = Gst.ElementFactory.make("audioresample", null);
134
- const encoder = Gst.ElementFactory.make("opusenc", null);
135
- const payloader = Gst.ElementFactory.make("rtpopuspay", null);
136
- payloader.pt = OPUS_PAYLOAD_TYPE;
137
- const capsfilter = Gst.ElementFactory.make("capsfilter", null);
138
- capsfilter.caps = Gst.Caps.from_string(`application/x-rtp,media=audio,encoding-name=OPUS,clock-rate=48000,payload=${OPUS_PAYLOAD_TYPE}`);
139
- elements.push(convert, resample, encoder, payloader, capsfilter);
140
- for (const el of elements) this._pipeline.add(el);
141
- if (this._teeSrcPad) {
142
- const valveSinkPad = valve.get_static_pad("sink");
143
- this._teeSrcPad.link(valveSinkPad);
144
- } else if (sourceForChain) {
145
- sourceForChain.link(valve);
146
- }
147
- valve.link(convert);
148
- convert.link(resample);
149
- resample.link(encoder);
150
- encoder.link(payloader);
151
- payloader.link(capsfilter);
152
- lastElement = capsfilter;
153
- } else {
154
- const convert = Gst.ElementFactory.make("videoconvert", null);
155
- const scale = Gst.ElementFactory.make("videoscale", null);
156
- const encoder = Gst.ElementFactory.make("vp8enc", null);
157
- encoder.deadline = 1;
158
- encoder.keyframe_max_dist = 60;
159
- const payloader = Gst.ElementFactory.make("rtpvp8pay", null);
160
- payloader.pt = VP8_PAYLOAD_TYPE;
161
- const capsfilter = Gst.ElementFactory.make("capsfilter", null);
162
- capsfilter.caps = Gst.Caps.from_string(`application/x-rtp,media=video,encoding-name=VP8,clock-rate=90000,payload=${VP8_PAYLOAD_TYPE}`);
163
- elements.push(convert, scale, encoder, payloader, capsfilter);
164
- for (const el of elements) this._pipeline.add(el);
165
- if (this._teeSrcPad) {
166
- const valveSinkPad = valve.get_static_pad("sink");
167
- this._teeSrcPad.link(valveSinkPad);
168
- } else if (sourceForChain) {
169
- sourceForChain.link(valve);
170
- }
171
- valve.link(convert);
172
- convert.link(scale);
173
- scale.link(encoder);
174
- encoder.link(payloader);
175
- payloader.link(capsfilter);
176
- lastElement = capsfilter;
177
- }
178
- const padName = this._mlineIndex >= 0 ? `sink_${this._mlineIndex}` : "sink_%u";
179
- const sinkPad = this._webrtcbin.request_pad_simple ? this._webrtcbin.request_pad_simple(padName) : this._webrtcbin.get_request_pad(padName);
180
- if (sinkPad) {
181
- const srcPad = lastElement.get_static_pad("src");
182
- srcPad.link(sinkPad);
183
- }
184
- const ownedElements = this._teeSrcPad ? elements : [source, ...elements];
185
- for (const el of ownedElements) {
186
- el.sync_state_with_parent();
187
- }
188
- this._elements = ownedElements;
189
- this._linked = true;
190
- track._setEnableCallback((enabled) => {
191
- if (this._valve) this._valve.drop = !enabled;
192
- });
193
- }
194
- /** @internal — tear down the encoder chain on close/removeTrack */
195
- _teardownPipeline() {
196
- if (!this._linked) return;
197
- if (this._track) {
198
- this._track._setEnableCallback(null);
199
- }
200
- if (this._teeSrcPad && this._track?._teeMultiplexer) {
201
- try {
202
- this._track._teeMultiplexer.releaseSrcPad(this._teeSrcPad);
203
- } catch {}
204
- this._teeSrcPad = null;
205
- }
206
- for (const el of [...this._elements].reverse()) {
207
- try {
208
- el.set_state(Gst.State.NULL);
209
- this._pipeline?.remove(el);
210
- } catch {}
211
- }
212
- this._elements = [];
213
- this._valve = null;
214
- this._linked = false;
215
- }
216
- getParameters() {
217
- if (!this._lastParams) {
218
- this._lastParams = {
219
- transactionId: String(++_txCounter),
220
- encodings: [],
221
- codecs: [],
222
- headerExtensions: [],
223
- rtcp: {}
224
- };
225
- }
226
- return {
227
- ...this._lastParams,
228
- encodings: [...this._lastParams.encodings]
229
- };
230
- }
231
- async setParameters(params) {
232
- if (!this._lastParams) {
233
- throw new DOMException("getParameters must be called before setParameters", "InvalidStateError");
234
- }
235
- if (params.transactionId !== this._lastParams.transactionId) {
236
- throw new DOMException("transactionId mismatch", "InvalidModificationError");
237
- }
238
- this._lastParams = null;
239
- }
240
- async replaceTrack(track) {
241
- if (track === null) {
242
- this._teardownPipeline();
243
- this._track = null;
244
- return;
245
- }
246
- if (this._track !== null && track.kind !== this._track.kind) {
247
- throw new TypeError("Cannot replace track with different kind");
248
- }
249
- if (this._linked && track._gstSource) {
250
- const oldSource = this._elements[0];
251
- const newSource = track._gstSource;
252
- const oldPipeline = track._gstPipeline;
253
- if (oldPipeline && oldPipeline !== this._pipeline) {
254
- newSource.set_state(Gst.State.NULL);
255
- oldPipeline.remove(newSource);
256
- track._gstPipeline = this._pipeline;
257
- }
258
- oldSource.set_state(Gst.State.NULL);
259
- oldSource.unlink(this._valve);
260
- this._pipeline.remove(oldSource);
261
- this._pipeline.add(newSource);
262
- newSource.link(this._valve);
263
- newSource.sync_state_with_parent();
264
- this._elements[0] = newSource;
265
- } else if (track._gstSource) {
266
- this._wirePipeline(track);
267
- }
268
- if (this._track) this._track._setEnableCallback(null);
269
- this._track = track;
270
- if (this._linked) {
271
- track._setEnableCallback((enabled) => {
272
- if (this._valve) this._valve.drop = !enabled;
273
- });
274
- }
275
- }
276
- async getStats() {
277
- if (this._getStatsForTrack && this._track) {
278
- return this._getStatsForTrack(this._track);
279
- }
280
- const { RTCStatsReport: Report } = await import("./rtc-stats-report.js");
281
- return new Report();
282
- }
283
- setStreams(..._streams) {}
284
- static getCapabilities(kind) {
285
- return getRtpCapabilities(kind);
286
- }
287
- };
288
-
289
- //#endregion
290
- export { RTCRtpSender };
1
+ import{Gst as e}from"./gst-init.js";import{getRtpCapabilities as t}from"./rtp-capabilities.js";import{RTCDTMFSender as n}from"./rtc-dtmf-sender.js";import{TeeMultiplexer as r}from"./tee-multiplexer.js";let i=0;var a=class{_gstSender;_track=null;_lastParams=null;_pipeline=null;_webrtcbin=null;_mlineIndex=-1;_elements=[];_valve=null;_linked=!1;_teeSrcPad=null;_getStatsForTrack=null;_transport=null;_dtmf=null;_kind=null;_transceiver=null;_onPipelineChanged=null;constructor(e,t,n){this._gstSender=e,this._pipeline=t??null,this._webrtcbin=n??null}get track(){return this._track}get dtmf(){if((this._track?.kind??this._kind)!==`audio`)return null;if(!this._dtmf){let e=new n;e._isStopped=()=>this._transceiver?.stopped??!1,e._getCurrentDirection=()=>this._transceiver?.currentDirection??null,this._dtmf=e}return this._dtmf}get transport(){return this._transport}_setTrack(e){e===null&&this._linked&&this._teardownPipeline(),this._track=e}_setMlineIndex(e){this._mlineIndex=e}_wirePipeline(t){if(this._linked||!this._pipeline||!this._webrtcbin)return;let n=t._gstSource;if(!n)return;let i=t,a;if(i._gstTee&&i._gstPipeline&&i._gstPipeline!==this._pipeline){let t=i._gstPipeline,n=i._gstTee;this._webrtcbin.get_parent()===this._pipeline&&(this._pipeline.set_state(e.State.NULL),this._pipeline.remove(this._webrtcbin)),t.add(this._webrtcbin),this._webrtcbin.sync_state_with_parent(),this._pipeline=t,this._onPipelineChanged?.(t);let r=n.request_pad_simple?n.request_pad_simple(`src_%u`):n.get_request_pad(`src_%u`);this._teeSrcPad=r,a=null}else if(i._teeMultiplexer){let e=i._teeMultiplexer.requestSrcPad();this._teeSrcPad=e,a=null}else if(i._gstPipeline&&i._gstPipeline!==this._pipeline){let t=i._gstPipeline,o=n.get_static_pad(`src`),s=o?.get_peer?.();s&&o.unlink(s),n.set_state(e.State.NULL),t.remove(n),this._pipeline.add(n),i._gstPipeline=this._pipeline;let c=new r(this._pipeline,n);if(i._teeMultiplexer=c,s){let e=c.requestSrcPad();e&&e.link(s)}let l=c.requestSrcPad();this._teeSrcPad=l,a=null}else{let t=i._gstPipeline;t&&t!==this._pipeline&&(n.set_state(e.State.NULL),t.remove(n),i._gstPipeline=this._pipeline),n.get_parent()!==this._pipeline&&this._pipeline.add(n),a=n}let o=e.ElementFactory.make(`valve`,null);o.drop=!t.enabled,this._valve=o,this._pipeline.add(o);let s=[o],c;if(t.kind===`audio`){let t=e.ElementFactory.make(`audioconvert`,null),n=e.ElementFactory.make(`audioresample`,null),r=e.ElementFactory.make(`opusenc`,null),i=e.ElementFactory.make(`rtpopuspay`,null);i.pt=111;let l=e.ElementFactory.make(`capsfilter`,null);l.caps=e.Caps.from_string(`application/x-rtp,media=audio,encoding-name=OPUS,clock-rate=48000,payload=111`),s.push(t,n,r,i,l);for(let e of s)this._pipeline.add(e);if(this._teeSrcPad){let e=o.get_static_pad(`sink`);this._teeSrcPad.link(e)}else a&&a.link(o);o.link(t),t.link(n),n.link(r),r.link(i),i.link(l),c=l}else{let t=e.ElementFactory.make(`videoconvert`,null),n=e.ElementFactory.make(`videoscale`,null),r=e.ElementFactory.make(`vp8enc`,null);r.deadline=1,r.keyframe_max_dist=60;let i=e.ElementFactory.make(`rtpvp8pay`,null);i.pt=96;let l=e.ElementFactory.make(`capsfilter`,null);l.caps=e.Caps.from_string(`application/x-rtp,media=video,encoding-name=VP8,clock-rate=90000,payload=96`),s.push(t,n,r,i,l);for(let e of s)this._pipeline.add(e);if(this._teeSrcPad){let e=o.get_static_pad(`sink`);this._teeSrcPad.link(e)}else a&&a.link(o);o.link(t),t.link(n),n.link(r),r.link(i),i.link(l),c=l}let l=this._mlineIndex>=0?`sink_${this._mlineIndex}`:`sink_%u`,u=this._webrtcbin.request_pad_simple?this._webrtcbin.request_pad_simple(l):this._webrtcbin.get_request_pad(l);u&&c.get_static_pad(`src`).link(u);let d=this._teeSrcPad?s:[n,...s];for(let e of d)e.sync_state_with_parent();this._elements=d,this._linked=!0,t._setEnableCallback(e=>{this._valve&&(this._valve.drop=!e)})}_teardownPipeline(){if(this._linked){if(this._track&&this._track._setEnableCallback(null),this._teeSrcPad&&this._track?._teeMultiplexer){try{this._track._teeMultiplexer.releaseSrcPad(this._teeSrcPad)}catch{}this._teeSrcPad=null}for(let t of[...this._elements].reverse())try{t.set_state(e.State.NULL),this._pipeline?.remove(t)}catch{}this._elements=[],this._valve=null,this._linked=!1}}getParameters(){return this._lastParams||={transactionId:String(++i),encodings:[],codecs:[],headerExtensions:[],rtcp:{}},{...this._lastParams,encodings:[...this._lastParams.encodings]}}async setParameters(e){if(!this._lastParams)throw new DOMException(`getParameters must be called before setParameters`,`InvalidStateError`);if(e.transactionId!==this._lastParams.transactionId)throw new DOMException(`transactionId mismatch`,`InvalidModificationError`);this._lastParams=null}async replaceTrack(t){if(t===null){this._teardownPipeline(),this._track=null;return}if(this._track!==null&&t.kind!==this._track.kind)throw TypeError(`Cannot replace track with different kind`);if(this._linked&&t._gstSource){let n=this._elements[0],r=t._gstSource,i=t._gstPipeline;i&&i!==this._pipeline&&(r.set_state(e.State.NULL),i.remove(r),t._gstPipeline=this._pipeline),n.set_state(e.State.NULL),n.unlink(this._valve),this._pipeline.remove(n),this._pipeline.add(r),r.link(this._valve),r.sync_state_with_parent(),this._elements[0]=r}else t._gstSource&&this._wirePipeline(t);this._track&&this._track._setEnableCallback(null),this._track=t,this._linked&&t._setEnableCallback(e=>{this._valve&&(this._valve.drop=!e)})}async getStats(){if(this._getStatsForTrack&&this._track)return this._getStatsForTrack(this._track);let{RTCStatsReport:e}=await import(`./rtc-stats-report.js`);return new e}setStreams(...e){}static getCapabilities(e){return t(e)}};export{a as RTCRtpSender};
@@ -1,96 +1 @@
1
- import { gstDirectionToW3C, w3cDirectionToGst } from "./gst-enum-maps.js";
2
- import { RTCRtpSender } from "./rtc-rtp-sender.js";
3
- import { RTCRtpReceiver } from "./rtc-rtp-receiver.js";
4
-
5
- //#region src/rtc-rtp-transceiver.ts
6
- var RTCRtpTransceiver = class {
7
- _gstTrans;
8
- sender;
9
- receiver;
10
- _stopped = false;
11
- _codecPreferences = [];
12
- constructor(gstTrans, sender, receiver) {
13
- this._gstTrans = gstTrans;
14
- this.sender = sender;
15
- this.receiver = receiver;
16
- }
17
- get mid() {
18
- if (this._stopped) return null;
19
- const m = this._gstTrans.mid;
20
- return m === "" || m == null ? null : String(m);
21
- }
22
- get direction() {
23
- if (this._stopped) return "stopped";
24
- return gstDirectionToW3C(this._gstTrans.direction);
25
- }
26
- set direction(d) {
27
- if (this._stopped) {
28
- throw new DOMException("Cannot set direction on a stopped transceiver", "InvalidStateError");
29
- }
30
- if (d === "stopped") {
31
- throw new TypeError("The provided value 'stopped' is not a valid enum value of type RTCRtpTransceiverDirection.");
32
- }
33
- const valid = [
34
- "sendrecv",
35
- "sendonly",
36
- "recvonly",
37
- "inactive"
38
- ];
39
- if (!valid.includes(d)) {
40
- throw new TypeError(`The provided value '${d}' is not a valid enum value of type RTCRtpTransceiverDirection.`);
41
- }
42
- this._gstTrans.direction = w3cDirectionToGst(d);
43
- }
44
- get currentDirection() {
45
- if (this._stopped) return null;
46
- const cd = this._gstTrans.current_direction ?? this._gstTrans.currentDirection;
47
- if (cd == null) return null;
48
- const w3c = gstDirectionToW3C(cd);
49
- return w3c === "inactive" ? null : w3c;
50
- }
51
- get stopped() {
52
- return this._stopped;
53
- }
54
- stop() {
55
- if (this._stopped) return;
56
- this._stopped = true;
57
- }
58
- setCodecPreferences(codecs) {
59
- if (!Array.isArray(codecs)) {
60
- throw new TypeError("codecs must be an array");
61
- }
62
- if (codecs.length === 0) {
63
- this._codecPreferences = [];
64
- return;
65
- }
66
- const kind = this.receiver.track.kind;
67
- const recvCaps = RTCRtpReceiver.getCapabilities(kind);
68
- const sendCaps = RTCRtpSender.getCapabilities(kind);
69
- if (!recvCaps || !sendCaps) {
70
- throw new DOMException("No capabilities available", "InvalidModificationError");
71
- }
72
- const allCaps = [...recvCaps.codecs, ...sendCaps.codecs];
73
- for (const codec of codecs) {
74
- if (!codec || typeof codec !== "object") {
75
- throw new TypeError("Each codec must be an object");
76
- }
77
- if (typeof codec.mimeType !== "string" || typeof codec.clockRate !== "number") {
78
- throw new TypeError("codec must have mimeType (string) and clockRate (number)");
79
- }
80
- const isResiliency = /\/(rtx|red|ulpfec)$/i.test(codec.mimeType);
81
- if (isResiliency) continue;
82
- const match = allCaps.find((c) => c.mimeType.toLowerCase() === codec.mimeType.toLowerCase() && c.clockRate === codec.clockRate && (codec.channels === undefined || c.channels === codec.channels) && (codec.sdpFmtpLine === undefined || c.sdpFmtpLine === codec.sdpFmtpLine));
83
- if (!match) {
84
- throw new DOMException(`Codec ${codec.mimeType} ${codec.clockRate} is not in capabilities`, "InvalidModificationError");
85
- }
86
- }
87
- this._codecPreferences = [...codecs];
88
- }
89
- /** @internal */
90
- get _nativeTransceiver() {
91
- return this._gstTrans;
92
- }
93
- };
94
-
95
- //#endregion
96
- export { RTCRtpTransceiver };
1
+ import{gstDirectionToW3C as e,w3cDirectionToGst as t}from"./gst-enum-maps.js";import{RTCRtpSender as n}from"./rtc-rtp-sender.js";import{RTCRtpReceiver as r}from"./rtc-rtp-receiver.js";var i=class{_gstTrans;sender;receiver;_stopped=!1;_codecPreferences=[];constructor(e,t,n){this._gstTrans=e,this.sender=t,this.receiver=n}get mid(){if(this._stopped)return null;let e=this._gstTrans.mid;return e===``||e==null?null:String(e)}get direction(){return this._stopped?`stopped`:e(this._gstTrans.direction)}set direction(e){if(this._stopped)throw new DOMException(`Cannot set direction on a stopped transceiver`,`InvalidStateError`);if(e===`stopped`)throw TypeError(`The provided value 'stopped' is not a valid enum value of type RTCRtpTransceiverDirection.`);if(![`sendrecv`,`sendonly`,`recvonly`,`inactive`].includes(e))throw TypeError(`The provided value '${e}' is not a valid enum value of type RTCRtpTransceiverDirection.`);this._gstTrans.direction=t(e)}get currentDirection(){if(this._stopped)return null;let t=this._gstTrans.current_direction??this._gstTrans.currentDirection;if(t==null)return null;let n=e(t);return n===`inactive`?null:n}get stopped(){return this._stopped}stop(){this._stopped||=!0}setCodecPreferences(e){if(!Array.isArray(e))throw TypeError(`codecs must be an array`);if(e.length===0){this._codecPreferences=[];return}let t=this.receiver.track.kind,i=r.getCapabilities(t),a=n.getCapabilities(t);if(!i||!a)throw new DOMException(`No capabilities available`,`InvalidModificationError`);let o=[...i.codecs,...a.codecs];for(let t of e){if(!t||typeof t!=`object`)throw TypeError(`Each codec must be an object`);if(typeof t.mimeType!=`string`||typeof t.clockRate!=`number`)throw TypeError(`codec must have mimeType (string) and clockRate (number)`);if(!/\/(rtx|red|ulpfec)$/i.test(t.mimeType)&&!o.find(e=>e.mimeType.toLowerCase()===t.mimeType.toLowerCase()&&e.clockRate===t.clockRate&&(t.channels===void 0||e.channels===t.channels)&&(t.sdpFmtpLine===void 0||e.sdpFmtpLine===t.sdpFmtpLine)))throw new DOMException(`Codec ${t.mimeType} ${t.clockRate} is not in capabilities`,`InvalidModificationError`)}this._codecPreferences=[...e]}get _nativeTransceiver(){return this._gstTrans}};export{i as RTCRtpTransceiver};
@@ -1,40 +1 @@
1
- import "@gjsify/dom-events/register/event-target";
2
-
3
- //#region src/rtc-sctp-transport.ts
4
- var RTCSctpTransport = class extends EventTarget {
5
- transport;
6
- _state = "connecting";
7
- _maxMessageSize = 262144;
8
- _maxChannels = 65535;
9
- _onstatechange = null;
10
- constructor(dtlsTransport) {
11
- super();
12
- this.transport = dtlsTransport;
13
- }
14
- get state() {
15
- return this._state;
16
- }
17
- get maxMessageSize() {
18
- return this._maxMessageSize;
19
- }
20
- get maxChannels() {
21
- return this._maxChannels;
22
- }
23
- get onstatechange() {
24
- return this._onstatechange;
25
- }
26
- set onstatechange(v) {
27
- this._onstatechange = v;
28
- }
29
- /** @internal */
30
- _setState(state) {
31
- if (this._state === state) return;
32
- this._state = state;
33
- const ev = new Event("statechange");
34
- this._onstatechange?.call(this, ev);
35
- this.dispatchEvent(ev);
36
- }
37
- };
38
-
39
- //#endregion
40
- export { RTCSctpTransport };
1
+ import"@gjsify/dom-events/register/event-target";var e=class extends EventTarget{transport;_state=`connecting`;_maxMessageSize=262144;_maxChannels=65535;_onstatechange=null;constructor(e){super(),this.transport=e}get state(){return this._state}get maxMessageSize(){return this._maxMessageSize}get maxChannels(){return this._maxChannels}get onstatechange(){return this._onstatechange}set onstatechange(e){this._onstatechange=e}_setState(e){if(this._state===e)return;this._state=e;let t=new Event(`statechange`);this._onstatechange?.call(this,t),this.dispatchEvent(t)}};export{e as RTCSctpTransport};
@@ -1,53 +1 @@
1
- import GstWebRTC from "gi://GstWebRTC?version=1.0";
2
- import GstSdp from "gi://GstSdp?version=1.0";
3
-
4
- //#region src/rtc-session-description.ts
5
- function sdpTypeToGst(type) {
6
- switch (type) {
7
- case "offer": return GstWebRTC.WebRTCSDPType.OFFER;
8
- case "pranswer": return GstWebRTC.WebRTCSDPType.PRANSWER;
9
- case "answer": return GstWebRTC.WebRTCSDPType.ANSWER;
10
- case "rollback": return GstWebRTC.WebRTCSDPType.ROLLBACK;
11
- }
12
- }
13
- function sdpTypeFromGst(type) {
14
- switch (type) {
15
- case GstWebRTC.WebRTCSDPType.OFFER: return "offer";
16
- case GstWebRTC.WebRTCSDPType.PRANSWER: return "pranswer";
17
- case GstWebRTC.WebRTCSDPType.ANSWER: return "answer";
18
- case GstWebRTC.WebRTCSDPType.ROLLBACK: return "rollback";
19
- default: return "offer";
20
- }
21
- }
22
- var RTCSessionDescription = class RTCSessionDescription {
23
- type;
24
- sdp;
25
- constructor(init) {
26
- this.type = init?.type ?? "offer";
27
- this.sdp = init?.sdp ?? "";
28
- }
29
- toJSON() {
30
- return {
31
- type: this.type,
32
- sdp: this.sdp
33
- };
34
- }
35
- /** Build a GstWebRTC.WebRTCSessionDescription for use with webrtcbin signals. */
36
- toGstDesc() {
37
- const [ret, sdp] = GstSdp.SDPMessage.new_from_text(this.sdp);
38
- if (ret !== GstSdp.SDPResult.OK) {
39
- throw new Error(`Failed to parse SDP text (GstSDPResult=${ret})`);
40
- }
41
- return GstWebRTC.WebRTCSessionDescription.new(sdpTypeToGst(this.type), sdp);
42
- }
43
- static fromGstDesc(desc) {
44
- const sdpText = desc.sdp?.as_text?.() ?? "";
45
- return new RTCSessionDescription({
46
- type: sdpTypeFromGst(desc.type),
47
- sdp: sdpText
48
- });
49
- }
50
- };
51
-
52
- //#endregion
53
- export { RTCSessionDescription };
1
+ import e from"gi://GstWebRTC?version=1.0";import t from"gi://GstSdp?version=1.0";function n(t){switch(t){case`offer`:return e.WebRTCSDPType.OFFER;case`pranswer`:return e.WebRTCSDPType.PRANSWER;case`answer`:return e.WebRTCSDPType.ANSWER;case`rollback`:return e.WebRTCSDPType.ROLLBACK}}function r(t){switch(t){case e.WebRTCSDPType.OFFER:return`offer`;case e.WebRTCSDPType.PRANSWER:return`pranswer`;case e.WebRTCSDPType.ANSWER:return`answer`;case e.WebRTCSDPType.ROLLBACK:return`rollback`;default:return`offer`}}var i=class i{type;sdp;constructor(e){this.type=e?.type??`offer`,this.sdp=e?.sdp??``}toJSON(){return{type:this.type,sdp:this.sdp}}toGstDesc(){let[r,i]=t.SDPMessage.new_from_text(this.sdp);if(r!==t.SDPResult.OK)throw Error(`Failed to parse SDP text (GstSDPResult=${r})`);return e.WebRTCSessionDescription.new(n(this.type),i)}static fromGstDesc(e){let t=e.sdp?.as_text?.()??``;return new i({type:r(e.type),sdp:t})}};export{i as RTCSessionDescription};
@@ -1,40 +1 @@
1
- //#region src/rtc-stats-report.ts
2
- /**
3
- * Read-only Map-like collection of stats entries keyed by id.
4
- * W3C requires iteration support but not mutation.
5
- */
6
- var RTCStatsReport = class {
7
- _map;
8
- constructor(entries) {
9
- this._map = new Map(entries);
10
- }
11
- get size() {
12
- return this._map.size;
13
- }
14
- get(key) {
15
- return this._map.get(key);
16
- }
17
- has(key) {
18
- return this._map.has(key);
19
- }
20
- forEach(callbackfn, thisArg) {
21
- this._map.forEach((value, key) => {
22
- callbackfn.call(thisArg, value, key, this);
23
- });
24
- }
25
- entries() {
26
- return this._map.entries();
27
- }
28
- keys() {
29
- return this._map.keys();
30
- }
31
- values() {
32
- return this._map.values();
33
- }
34
- [Symbol.iterator]() {
35
- return this._map.entries();
36
- }
37
- };
38
-
39
- //#endregion
40
- export { RTCStatsReport };
1
+ var e=class{_map;constructor(e){this._map=new Map(e)}get size(){return this._map.size}get(e){return this._map.get(e)}has(e){return this._map.has(e)}forEach(e,t){this._map.forEach((n,r)=>{e.call(t,n,r,this)})}entries(){return this._map.entries()}keys(){return this._map.keys()}values(){return this._map.values()}[Symbol.iterator](){return this._map.entries()}};export{e as RTCStatsReport};
@@ -1,31 +1 @@
1
- import "@gjsify/dom-events/register/event-target";
2
-
3
- //#region src/rtc-track-event.ts
4
- var RTCTrackEvent = class extends Event {
5
- receiver;
6
- track;
7
- streams;
8
- transceiver;
9
- constructor(type, init) {
10
- super(type, init);
11
- if (!init || typeof init !== "object") {
12
- throw new TypeError("RTCTrackEventInit is required");
13
- }
14
- if (!("receiver" in init)) {
15
- throw new TypeError("Failed to construct 'RTCTrackEvent': required member receiver is not provided.");
16
- }
17
- if (!("track" in init)) {
18
- throw new TypeError("Failed to construct 'RTCTrackEvent': required member track is not provided.");
19
- }
20
- if (!("transceiver" in init)) {
21
- throw new TypeError("Failed to construct 'RTCTrackEvent': required member transceiver is not provided.");
22
- }
23
- this.receiver = init.receiver;
24
- this.track = init.track;
25
- this.streams = Object.freeze(init.streams ? [...init.streams] : []);
26
- this.transceiver = init.transceiver;
27
- }
28
- };
29
-
30
- //#endregion
31
- export { RTCTrackEvent };
1
+ import"@gjsify/dom-events/register/event-target";var e=class extends Event{receiver;track;streams;transceiver;constructor(e,t){if(super(e,t),!t||typeof t!=`object`)throw TypeError(`RTCTrackEventInit is required`);if(!(`receiver`in t))throw TypeError(`Failed to construct 'RTCTrackEvent': required member receiver is not provided.`);if(!(`track`in t))throw TypeError(`Failed to construct 'RTCTrackEvent': required member track is not provided.`);if(!(`transceiver`in t))throw TypeError(`Failed to construct 'RTCTrackEvent': required member transceiver is not provided.`);this.receiver=t.receiver,this.track=t.track,this.streams=Object.freeze(t.streams?[...t.streams]:[]),this.transceiver=t.transceiver}};export{e as RTCTrackEvent};