@gjsify/webrtc 0.46.0 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/get-user-media.js +1 -1
- package/lib/esm/gst-utils.js +1 -1
- package/lib/esm/media-stream-track.js +1 -1
- package/lib/esm/rtc-peer-connection/data-channel.js +1 -1
- package/lib/esm/rtc-peer-connection/sdp-negotiation.js +1 -1
- package/lib/esm/rtc-peer-connection/stats-and-config.js +1 -1
- package/lib/esm/rtc-peer-connection/tracks.js +1 -1
- package/lib/esm/rtc-peer-connection/transceivers.js +1 -1
- package/lib/esm/rtc-peer-connection.js +1 -1
- package/lib/esm/rtc-rtp-sender.js +1 -1
- package/lib/esm/rtc-sctp-transport.js +1 -1
- package/lib/esm/rtc-session-description.js +1 -1
- package/lib/esm/rtp-capabilities.js +1 -1
- package/lib/esm/sdp-params.js +3 -0
- package/lib/types/gst-utils.d.ts +11 -0
- package/lib/types/media-stream-track.d.ts +8 -0
- package/lib/types/rtc-peer-connection.d.ts +33 -0
- package/lib/types/rtc-rtp-sender.d.ts +11 -1
- package/lib/types/rtc-sctp-transport.d.ts +8 -0
- package/lib/types/rtp-capabilities.d.ts +11 -0
- package/lib/types/sdp-params.d.ts +49 -0
- package/package.json +8 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{Gst as e,ensureGstInit as t}from"./gst-init.js";import{MediaStreamTrack as n}from"./media-stream-track.js";import{MediaStream as r}from"./media-stream.js";async function getUserMedia(i){if(t(),!i.audio&&!i.video)throw TypeError(`Failed to execute 'getUserMedia': At least one of audio or video must be requested`);let a=[];if(i.audio){let t=typeof i.audio==`object`?i.audio:{},r=_createAudioSource(),o=new e.Pipeline;o.add(r);let s=_buildAudioCaps(t);if(s){let t=e.ElementFactory.make(`capsfilter`,null);t.caps=e.Caps.from_string(s),o.add(t),r.link(t)}a.push(new n({kind:`audio`,label:r.name??`audio`,_gst:{source:r,pipeline:o}}))}if(i.video){let t=typeof i.video==`object`?i.video:{},r=_createVideoSource(),o=new e.Pipeline;o.add(r);let s=_buildVideoCaps(t);if(s){let t=e.ElementFactory.make(`capsfilter`,null);t.caps=e.Caps.from_string(s),o.add(t),r.link(t)}a.push(new n({kind:`video`,label:r.name??`video`,_gst:{source:r,pipeline:o}}))}return new r(a)}function _buildAudioCaps(e){let t=[];return e.sampleRate!=null&&t.push(`rate=${Math.trunc(e.sampleRate)}`),e.channelCount!=null&&t.push(`channels=${Math.trunc(e.channelCount)}`),t.length===0?null:`audio/x-raw,${t.join(`,`)}`}function _buildVideoCaps(e){let t=[];return e.width!=null&&t.push(`width=${Math.trunc(e.width)}`),e.height!=null&&t.push(`height=${Math.trunc(e.height)}`),e.frameRate!=null&&t.push(`framerate=${Math.trunc(e.frameRate)}/1`),t.length===0?null:`video/x-raw,${t.join(`,`)}`}function
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Gst as e,ensureGstInit as t}from"./gst-init.js";import{MediaStreamTrack as n}from"./media-stream-track.js";import{MediaStream as r}from"./media-stream.js";async function getUserMedia(i){if(t(),!i.audio&&!i.video)throw TypeError(`Failed to execute 'getUserMedia': At least one of audio or video must be requested`);let a=[];if(i.audio){let t=typeof i.audio==`object`?i.audio:{},r=_createAudioSource(),o=new e.Pipeline;o.add(r);let s=_buildAudioCaps(t);if(s){let t=e.ElementFactory.make(`capsfilter`,null);t.caps=e.Caps.from_string(s),o.add(t),r.link(t)}a.push(new n({kind:`audio`,label:r.name??`audio`,_gst:{source:r,pipeline:o}}))}if(i.video){let t=typeof i.video==`object`?i.video:{},r=_createVideoSource(),o=new e.Pipeline;o.add(r);let s=_buildVideoCaps(t);if(s){let t=e.ElementFactory.make(`capsfilter`,null);t.caps=e.Caps.from_string(s),o.add(t),r.link(t)}a.push(new n({kind:`video`,label:r.name??`video`,_gst:{source:r,pipeline:o}}))}return new r(a)}function _buildAudioCaps(e){let t=[];return e.sampleRate!=null&&t.push(`rate=${Math.trunc(e.sampleRate)}`),e.channelCount!=null&&t.push(`channels=${Math.trunc(e.channelCount)}`),t.length===0?null:`audio/x-raw,${t.join(`,`)}`}function _buildVideoCaps(e){let t=[];return e.width!=null&&t.push(`width=${Math.trunc(e.width)}`),e.height!=null&&t.push(`height=${Math.trunc(e.height)}`),e.frameRate!=null&&t.push(`framerate=${Math.trunc(e.frameRate)}/1`),t.length===0?null:`video/x-raw,${t.join(`,`)}`}function _probeSource(t,n){let r=e.ElementFactory.make(t,null);if(!r)return null;let i=e.ElementFactory.make(n,null),a=e.ElementFactory.make(`fakesink`,null);if(!i||!a)return r;let o=new e.Pipeline;o.add(r),o.add(i),o.add(a),r.link(i),i.link(a);let s=o.set_state(e.State.PLAYING);return s!==e.StateChangeReturn.FAILURE&&(s=o.get_state(500*Number(e.MSECOND))[0]),o.set_state(e.State.NULL),r.unlink(i),o.remove(r),s===e.StateChangeReturn.FAILURE?null:r}const i=new Map;function _chooseSource(t,n,r,a){let o=i.get(t);if(o)return e.ElementFactory.make(o,null);for(let e of n){let n=_probeSource(e,r);if(n)return i.set(t,e),n}return i.set(t,a),e.ElementFactory.make(a,null)}function _createAudioSource(){let e=_chooseSource(`audio`,[`pipewiresrc`,`pulsesrc`,`autoaudiosrc`],`audioconvert`,`audiotestsrc`);try{e.is_live=!0}catch{}return i.get(`audio`)===`audiotestsrc`&&(e.wave=0),e}function _createVideoSource(){let e=_chooseSource(`video`,[`pipewiresrc`,`v4l2src`,`autovideosrc`],`videoconvert`,`videotestsrc`);return i.get(`video`)===`videotestsrc`&&(e.is_live=!0,e.pattern=0),e}export{getUserMedia};
|
package/lib/esm/gst-utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{PromiseBridge as e}from"@gjsify/webrtc-native";function withGstPromise(t){return new Promise((n,r)=>{let i=new e;i.connect(`replied`,(e,t)=>{n(t)}),i.connect(`rejected`,(e,t)=>{r(Error(t))}),t(i.promise)})}export{withGstPromise};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{PromiseBridge as e}from"@gjsify/webrtc-native";function withGstPromise(t){return new Promise((n,r)=>{let i=new e;i.connect(`replied`,(e,t)=>{n(t)}),i.connect(`rejected`,(e,t)=>{r(Error(t))}),t(i.promise)})}function getRtcpCname(e){try{return e.get_by_name(`rtpbin`)?.sdes?.get_string(`cname`)??void 0}catch{return}}export{getRtcpCname,withGstPromise};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{Gst as e}from"./gst-init.js";import"@gjsify/dom-events/register/event-target";import t from"gi://GLib?version=2.0";var n=class MediaStreamTrack extends EventTarget{id;kind;label;_enabled=!0;_muted;_ended=!1;_contentHint=``;_onended=null;_onmute=null;_onunmute=null;_gstSource=null;_gstPipeline=null;_gstTee=null;_teeMultiplexer=null;_enableCallback=null;constructor(e){super(),this.id=e.id??t.uuid_string_random(),this.kind=e.kind,this.label=e.label??``,this._muted=e.muted??!1,e._gst&&(this._gstSource=e._gst.source,this._gstPipeline=e._gst.pipeline)}get enabled(){return this._enabled}set enabled(e){let t=!!e;this._enabled!==t&&(this._enabled=t,this._enableCallback?.(t))}get muted(){return this._muted}get readyState(){return this._ended?`ended`:`live`}get contentHint(){return this._contentHint}set contentHint(e){if(this.kind===`audio`){if(e!==``&&e!==`speech`&&e!==`speech-recognition`&&e!==`music`)return}else if(e!==``&&e!==`motion`&&e!==`detail`&&e!==`text`)return;this._contentHint=e}get onended(){return this._onended}set onended(e){this._onended=e}get onmute(){return this._onmute}set onmute(e){this._onmute=e}get onunmute(){return this._onunmute}set onunmute(e){this._onunmute=e}clone(){let e=new MediaStreamTrack({kind:this.kind,label:this.label,muted:this._muted});return e._enabled=this._enabled,e}stop(){if(this._ended)return;if(this._ended=!0,this._gstSource||this._gstPipeline){try{this._gstPipeline?.set_state(e.State.NULL)}catch{}try{this._gstSource?.set_state(e.State.NULL)}catch{}this._gstSource=null,this._gstPipeline=null}let t=new Event(`ended`);this._onended?.call(this,t),this.dispatchEvent(t)}getCapabilities(){return{}}getConstraints(){return{}}getSettings(){return{}}applyConstraints(e){return Promise.reject(new DOMException(`applyConstraints is not supported`,`NotSupportedError`))}_setMuted(e){if(this._muted===e)return;this._muted=e;let t=new Event(e?`mute`:`unmute`);e?this._onmute?.call(this,t):this._onunmute?.call(this,t),this.dispatchEvent(t)}_setEnableCallback(e){this._enableCallback=e}};export{n as MediaStreamTrack};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Gst as e}from"./gst-init.js";import"@gjsify/dom-events/register/event-target";import t from"gi://GLib?version=2.0";var n=class MediaStreamTrack extends EventTarget{id;kind;label;_enabled=!0;_muted;_ended=!1;_contentHint=``;_onended=null;_onmute=null;_onunmute=null;_gstSource=null;_gstPipeline=null;_gstTee=null;_teeMultiplexer=null;_senderConsumers=0;_enableCallback=null;constructor(e){super(),this.id=e.id??t.uuid_string_random(),this.kind=e.kind,this.label=e.label??``,this._muted=e.muted??!1,e._gst&&(this._gstSource=e._gst.source,this._gstPipeline=e._gst.pipeline)}get enabled(){return this._enabled}set enabled(e){let t=!!e;this._enabled!==t&&(this._enabled=t,this._enableCallback?.(t))}get muted(){return this._muted}get readyState(){return this._ended?`ended`:`live`}get contentHint(){return this._contentHint}set contentHint(e){if(this.kind===`audio`){if(e!==``&&e!==`speech`&&e!==`speech-recognition`&&e!==`music`)return}else if(e!==``&&e!==`motion`&&e!==`detail`&&e!==`text`)return;this._contentHint=e}get onended(){return this._onended}set onended(e){this._onended=e}get onmute(){return this._onmute}set onmute(e){this._onmute=e}get onunmute(){return this._onunmute}set onunmute(e){this._onunmute=e}clone(){let e=new MediaStreamTrack({kind:this.kind,label:this.label,muted:this._muted});return e._enabled=this._enabled,e}stop(){if(this._ended)return;if(this._ended=!0,this._gstSource||this._gstPipeline){try{this._gstPipeline?.set_state(e.State.NULL)}catch{}try{this._gstSource?.set_state(e.State.NULL)}catch{}this._gstSource=null,this._gstPipeline=null}let t=new Event(`ended`);this._onended?.call(this,t),this.dispatchEvent(t)}getCapabilities(){return{}}getConstraints(){return{}}getSettings(){return{}}applyConstraints(e){return Promise.reject(new DOMException(`applyConstraints is not supported`,`NotSupportedError`))}_setMuted(e){if(this._muted===e)return;this._muted=e;let t=new Event(e?`mute`:`unmute`);e?this._onmute?.call(this,t):this._onunmute?.call(this,t),this.dispatchEvent(t)}_setEnableCallback(e){this._enableCallback=e}};export{n as MediaStreamTrack};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{RTCDataChannel as t}from"../rtc-data-channel.js";import{DOMException as n}from"@gjsify/dom-exception";function coerceUnsignedShort(e,t){let n=Number(t);if(!Number.isFinite(n))throw TypeError(`createDataChannel: ${e} must be a finite number, got ${String(t)}`);let r=Math.trunc(n);if(r<0||r>65535)throw TypeError(`createDataChannel: ${e}=${r} is outside the [0, 65535] range`);return r}const r={createDataChannel(r,i={}){if(this._closed)throw new n(`Cannot create a data channel on a closed RTCPeerConnection`,`InvalidStateError`);if(typeof r!=`string`)throw TypeError(`createDataChannel: label must be a string`);if(new TextEncoder().encode(r).byteLength>65535)throw TypeError(`createDataChannel: label too long (> 65535 bytes)`);let a=i.maxPacketLifeTime==null?void 0:coerceUnsignedShort(`maxPacketLifeTime`,i.maxPacketLifeTime),o=i.maxRetransmits==null?void 0:coerceUnsignedShort(`maxRetransmits`,i.maxRetransmits),s=i.id==null?void 0:coerceUnsignedShort(`id`,i.id);if(a!==void 0&&o!==void 0)throw TypeError(`createDataChannel: maxPacketLifeTime and maxRetransmits are mutually exclusive`);if(i.negotiated===!0&&s===void 0)throw TypeError(`createDataChannel: negotiated=true requires an id`);if(s===65535)throw TypeError(`createDataChannel: id 65535 is reserved`);let c=e.Structure.new_empty(`data-channel-opts`);this._setStructureField(c,`ordered`,`boolean`,i.ordered),this._setStructureField(c,`max-packet-lifetime`,`int`,a),this._setStructureField(c,`max-retransmits`,`int`,o),this._setStructureField(c,`protocol`,`string`,i.protocol),this._setStructureField(c,`negotiated`,`boolean`,i.negotiated),this._setStructureField(c,`id`,`int`,s);let l=null;try{l=this._webrtcbin.emit(`create-data-channel`,r,c)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`create-data-channel failed: ${t}`)}if(!l)throw Error(`webrtcbin returned null data channel (check id/label/options)`);this._ensureSctpTransport();let u=new t(l,this.sctp??void 0);return this._dataChannels.set(l,u),u.addEventListener(`close`,()=>{this._dataChannels.delete(l)}),u}};function installDataChannelMethods(e){Object.assign(e,r)}export{installDataChannelMethods};
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{RTCDataChannel as t}from"../rtc-data-channel.js";import{DOMException as n}from"@gjsify/dom-exception";function coerceUnsignedShort(e,t){let n=Number(t);if(!Number.isFinite(n))throw TypeError(`createDataChannel: ${e} must be a finite number, got ${String(t)}`);let r=Math.trunc(n);if(r<0||r>65535)throw TypeError(`createDataChannel: ${e}=${r} is outside the [0, 65535] range`);return r}const r={createDataChannel(r,i={}){if(this._closed)throw new n(`Cannot create a data channel on a closed RTCPeerConnection`,`InvalidStateError`);if(typeof r!=`string`)throw TypeError(`createDataChannel: label must be a string`);if(new TextEncoder().encode(r).byteLength>65535)throw TypeError(`createDataChannel: label too long (> 65535 bytes)`);let a=i.maxPacketLifeTime==null?void 0:coerceUnsignedShort(`maxPacketLifeTime`,i.maxPacketLifeTime),o=i.maxRetransmits==null?void 0:coerceUnsignedShort(`maxRetransmits`,i.maxRetransmits),s=i.id==null?void 0:coerceUnsignedShort(`id`,i.id);if(a!==void 0&&o!==void 0)throw TypeError(`createDataChannel: maxPacketLifeTime and maxRetransmits are mutually exclusive`);if(i.negotiated===!0&&s===void 0)throw TypeError(`createDataChannel: negotiated=true requires an id`);if(s===65535)throw TypeError(`createDataChannel: id 65535 is reserved`);let c=e.Structure.new_empty(`data-channel-opts`);this._setStructureField(c,`ordered`,`boolean`,i.ordered),this._setStructureField(c,`max-packet-lifetime`,`int`,a),this._setStructureField(c,`max-retransmits`,`int`,o),this._setStructureField(c,`protocol`,`string`,i.protocol),this._setStructureField(c,`negotiated`,`boolean`,i.negotiated),this._setStructureField(c,`id`,`int`,s);let l=null;try{l=this._webrtcbin.emit(`create-data-channel`,r,c)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`create-data-channel failed: ${t}`)}if(!l)throw Error(`webrtcbin returned null data channel (check id/label/options)`);this._ensureSctpTransport();let u=new t(l,this.sctp??void 0);return this._dataChannels.set(l,u),u.addEventListener(`close`,()=>{this._dataChannels.delete(l)}),this._updateNegotiationNeeded(),u}};function installDataChannelMethods(e){Object.assign(e,r)}export{installDataChannelMethods};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{withGstPromise as t}from"../gst-utils.js";import{RTCSessionDescription as n}from"../rtc-session-description.js";import{
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{withGstPromise as t}from"../gst-utils.js";import{RTCSessionDescription as n}from"../rtc-session-description.js";import{rewriteIceCredentials as r}from"../sdp-params.js";import{DOMException as i}from"@gjsify/dom-exception";const a={async createOffer(i){this._rejectIfClosed(`createOffer`);let a=e.Structure.new_empty(`offer-options`),o=this._iceRestartNeeded;o&&(this._setStructureField(a,`ice-restart`,`boolean`,!0),this._iceRestartNeeded=!1);let s=(await t(e=>{this._webrtcbin.emit(`create-offer`,a,e)})).get_value(`offer`),c=n.fromGstDesc(s).toJSON();return o&&(c.sdp=r(c.sdp)),c},async createAnswer(r){this._rejectIfClosed(`createAnswer`);let i=e.Structure.new_empty(`answer-options`),a=(await t(e=>{this._webrtcbin.emit(`create-answer`,i,e)})).get_value(`answer`);return n.fromGstDesc(a).toJSON()},async setLocalDescription(r){if(this._rejectIfClosed(`setLocalDescription`),!r||!r.type){let e=this.signalingState;if(e===`stable`||e===`have-local-offer`)r=await this.createOffer();else if(e===`have-remote-offer`||e===`have-remote-pranswer`)r=await this.createAnswer();else throw new i(`setLocalDescription: cannot auto-create SDP in signalingState '${e}'`,`InvalidStateError`)}if(r.type===`rollback`){let e=this.signalingState;if(e!==`have-local-offer`)throw new i(`setLocalDescription: cannot rollback in signalingState '${e}'`,`InvalidStateError`);let a=this.currentLocalDescription!==null,o=new n(r).toGstDesc();await t(e=>{this._webrtcbin.emit(`set-local-description`,o,e)}),a||this._clearTransports();return}this._pipeline.set_state(e.State.PLAYING);let a=new n(r).toGstDesc();await t(e=>{this._webrtcbin.emit(`set-local-description`,a,e)}),this._assignTransports()},async setRemoteDescription(r){if(this._rejectIfClosed(`setRemoteDescription`),!r||!r.sdp||!r.type)throw TypeError(`setRemoteDescription requires an RTCSessionDescriptionInit with sdp and type`);this._pipeline.set_state(e.State.PLAYING);let i=new n(r).toGstDesc();await t(e=>{this._webrtcbin.emit(`set-remote-description`,i,e)}),this.signalingState===`stable`&&(this._hasNegotiated=!0)},async addIceCandidate(e){if(this._rejectIfClosed(`addIceCandidate`),!e)return;let{candidate:t,sdpMLineIndex:n}=e;typeof t!=`string`||typeof n!=`number`||this._webrtcbin.emit(`add-ice-candidate`,n,t)}};function installSdpNegotiationMethods(e){Object.assign(e,a)}export{installSdpNegotiationMethods};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{MediaStreamTrack as e}from"../media-stream-track.js";import{filterStatsByTrackId as t,parseGstStats as n}from"../gst-stats-parser.js";import{withGstPromise as r}from"../gst-utils.js";import{DOMException as i}from"@gjsify/dom-exception";const a={async getStats(a){if(this._rejectIfClosed(`getStats`),a!=null&&a instanceof e){let e=this._senders.some(e=>e.track===a),t=this._receivers.some(e=>e.track===a);if(!e&&!t)throw new i(`The selector track is not associated with a sender or receiver of this connection`,`InvalidAccessError`)}let o=n(await r(e=>{this._webrtcbin.emit(`get-stats`,null,e)}));return a!=null&&a instanceof e?t(o,a.id):o},restartIce(){this._closed||(this._iceRestartNeeded=!0,this.
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{MediaStreamTrack as e}from"../media-stream-track.js";import{filterStatsByTrackId as t,parseGstStats as n}from"../gst-stats-parser.js";import{withGstPromise as r}from"../gst-utils.js";import{DOMException as i}from"@gjsify/dom-exception";const a={async getStats(a){if(this._rejectIfClosed(`getStats`),a!=null&&a instanceof e){let e=this._senders.some(e=>e.track===a),t=this._receivers.some(e=>e.track===a);if(!e&&!t)throw new i(`The selector track is not associated with a sender or receiver of this connection`,`InvalidAccessError`)}let o=n(await r(e=>{this._webrtcbin.emit(`get-stats`,null,e)}));return a!=null&&a instanceof e?t(o,a.id):o},restartIce(){this._closed||(this._iceRestartNeeded=!0,this._updateNegotiationNeeded())},setConfiguration(e){if(this._rejectIfClosed(`setConfiguration`),e.bundlePolicy&&e.bundlePolicy!==(this._conf.bundlePolicy??`balanced`))throw new i(`setConfiguration: bundlePolicy cannot be changed`,`InvalidModificationError`);if(e.rtcpMuxPolicy&&e.rtcpMuxPolicy!==(this._conf.rtcpMuxPolicy??`require`))throw new i(`setConfiguration: rtcpMuxPolicy cannot be changed`,`InvalidModificationError`);e.iceServers&&this._applyIceServers(e.iceServers),e.iceTransportPolicy&&this._applyIceTransportPolicy(e.iceTransportPolicy),this._conf={...this._conf,...e}},getConfiguration(){return{...this._conf}}};function installStatsAndConfigMethods(e){Object.assign(e,a)}export{installStatsAndConfigMethods};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{MediaStreamTrack as e}from"../media-stream-track.js";import{DOMException as t}from"@gjsify/dom-exception";const n={addTrack(n,...r){if(this._rejectIfClosed(`addTrack`),!(n instanceof e))throw TypeError(`Failed to execute 'addTrack' on 'RTCPeerConnection': parameter 1 is not a MediaStreamTrack`);if(this._senders.find(e=>e.track===n))throw new t(`Track already exists in a sender of this connection`,`InvalidAccessError`);let i;for(let e of this._transceivers.values())if(e.sender.track===null&&!e.stopped&&e.direction!==`stopped`&&e.receiver.track.kind===n.kind){let t=e.direction;if(t===`recvonly`||t===`inactive`){i=e;break}}if(i){let e=i.direction;return i.direction=e===`recvonly`?`sendrecv`:`sendonly`,i.sender._setTrack(n),i.sender}return this.addTransceiver(n,{direction:`sendrecv`}).sender},removeTrack(e){if(this._rejectIfClosed(`removeTrack`),!this._senders.includes(e))throw new t(`sender was not created by this connection`,`InvalidAccessError`);e._setTrack(null)},getSenders(){return[...this._senders]},getReceivers(){return[...this._receivers]},getTransceivers(){return[...this._transceivers.values()]}};function installTrackMethods(e){Object.assign(e,n)}export{installTrackMethods};
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{MediaStreamTrack as e}from"../media-stream-track.js";import{DOMException as t}from"@gjsify/dom-exception";const n={addTrack(n,...r){if(this._rejectIfClosed(`addTrack`),!(n instanceof e))throw TypeError(`Failed to execute 'addTrack' on 'RTCPeerConnection': parameter 1 is not a MediaStreamTrack`);if(this._senders.find(e=>e.track===n))throw new t(`Track already exists in a sender of this connection`,`InvalidAccessError`);let i;for(let e of this._transceivers.values())if(e.sender.track===null&&!e.stopped&&e.direction!==`stopped`&&e.receiver.track.kind===n.kind){let t=e.direction;if(t===`recvonly`||t===`inactive`){i=e;break}}if(i){let e=i.direction;return i.direction=e===`recvonly`?`sendrecv`:`sendonly`,i.sender._setTrack(n),this._updateNegotiationNeeded(),i.sender}return this.addTransceiver(n,{direction:`sendrecv`}).sender},removeTrack(e){if(this._rejectIfClosed(`removeTrack`),!this._senders.includes(e))throw new t(`sender was not created by this connection`,`InvalidAccessError`);e._setTrack(null)},getSenders(){return[...this._senders]},getReceivers(){return[...this._receivers]},getTransceivers(){return[...this._transceivers.values()]}};function installTrackMethods(e){Object.assign(e,n)}export{installTrackMethods};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{MediaStreamTrack as t}from"../media-stream-track.js";import{w3cDirectionToGst as n}from"../gst-enum-maps.js";import{
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{Gst as e}from"../gst-init.js";import{MediaStreamTrack as t}from"../media-stream-track.js";import{w3cDirectionToGst as n}from"../gst-enum-maps.js";import{defaultRtpCapsString as r}from"../rtp-capabilities.js";import{RTCRtpSender as i}from"../rtc-rtp-sender.js";import{RTCRtpReceiver as a}from"../rtc-rtp-receiver.js";import{RTCRtpTransceiver as o}from"../rtc-rtp-transceiver.js";const s={addTransceiver(s,c){this._rejectIfClosed(`addTransceiver`);let l;if(typeof s==`string`){if(s!==`audio`&&s!==`video`)throw TypeError(`Failed to execute 'addTransceiver' on 'RTCPeerConnection': The provided value '${s}' is not a valid enum value of type MediaStreamTrackKind.`);l=s}else if(s instanceof t)l=s.kind;else throw TypeError(`Failed to execute 'addTransceiver' on 'RTCPeerConnection': parameter 1 is not of type 'MediaStreamTrack' or a valid MediaStreamTrackKind.`);if(c?.sendEncodings){let e=new Set;for(let t of c.sendEncodings){if(t.rid!==void 0){if(typeof t.rid!=`string`||t.rid.length===0||t.rid.length>16||!/^[a-zA-Z0-9]+$/.test(t.rid))throw TypeError(`Invalid RID value: ${t.rid}`);if(e.has(t.rid))throw TypeError(`Duplicate RID: ${t.rid}`);e.add(t.rid)}if(t.scaleResolutionDownBy!==void 0&&t.scaleResolutionDownBy<1)throw RangeError(`scaleResolutionDownBy must be >= 1.0`)}}let u=c?.direction??`sendrecv`;if(![`sendrecv`,`sendonly`,`recvonly`,`inactive`].includes(u))throw TypeError(`Failed to execute 'addTransceiver' on 'RTCPeerConnection': The provided value '${u}' is not a valid enum value of type RTCRtpTransceiverDirection.`);let d=s instanceof t&&s._gstSource,f=u===`sendrecv`||u===`sendonly`,p,m;if(d&&f){let e=s,t=new i(null,this._pipeline,this._webrtcbin);t._kind=l,t._onPipelineChanged=e=>{this._pipeline=e},t._setTrack(e),t._wirePipeline(e);let r=this._findNewGstTransceiver();if(!r)throw Error(`webrtcbin did not create a transceiver for the send pad`);p=r;let c=p.receiver??null,d=new a(l,c,this._pipeline),statsDelegate=e=>this.getStats(e);if(t._getStatsForTrack=statsDelegate,d._getStatsForTrack=statsDelegate,this.localDescription){let e=this._ensureTransports();t._transport=e,d._transport=e}m=new o(p,t,d),t._transceiver=m,this._transceivers.set(p,m),this._senders.push(t),this._receivers.push(d),p.direction=n(u)}else{let i=e.Caps.from_string(r(l)),a=n(u===`inactive`?`sendrecv`:u),o=this._webrtcbin.emit(`add-transceiver`,a,i);if(!o)throw Error(`webrtcbin did not create a transceiver`);p=o,m=this._transceivers.get(p),m||=this._createTransceiverWrapper(p),p.direction=n(u),s instanceof t&&m.sender._setTrack(s)}return this._updateNegotiationNeeded(),m}};function installTransceiverMethods(e){Object.assign(e,s)}export{installTransceiverMethods};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{Gst as e,ensureWebrtcbinAvailable as t}from"./gst-init.js";import{MediaStream as n}from"./media-stream.js";import{gstToConnectionState as r,gstToIceConnectionState as i,gstToIceGatheringState as a,gstToSignalingState as o}from"./gst-enum-maps.js";import{asWebRtcBin as s,asWebRtcSrcPad as c}from"./internal/gst-types.js";import{RTCSessionDescription as l}from"./rtc-session-description.js";import{RTCIceCandidate as u}from"./rtc-ice-candidate.js";import{RTCDataChannelEvent as d,RTCPeerConnectionIceEvent as f}from"./rtc-events.js";import{RTCDataChannel as p}from"./rtc-data-channel.js";import{RTCRtpSender as m}from"./rtc-rtp-sender.js";import{RTCRtpReceiver as h}from"./rtc-rtp-receiver.js";import{RTCRtpTransceiver as g}from"./rtc-rtp-transceiver.js";import{RTCTrackEvent as _}from"./rtc-track-event.js";import{RTCIceTransport as v}from"./rtc-ice-transport.js";import{RTCDtlsTransport as y}from"./rtc-dtls-transport.js";import{RTCSctpTransport as b}from"./rtc-sctp-transport.js";import{RTCCertificate as x,generateCertificate as S}from"./rtc-certificate.js";import{installSdpNegotiationMethods as C}from"./rtc-peer-connection/sdp-negotiation.js";import{installDataChannelMethods as w}from"./rtc-peer-connection/data-channel.js";import{installTransceiverMethods as T}from"./rtc-peer-connection/transceivers.js";import{installTrackMethods as E}from"./rtc-peer-connection/tracks.js";import{installStatsAndConfigMethods as D}from"./rtc-peer-connection/stats-and-config.js";import{DOMException as O}from"@gjsify/dom-exception";import k from"gi://GLib?version=2.0";import A from"gi://GstWebRTC?version=1.0";import{WebrtcbinBridge as j}from"@gjsify/webrtc-native";import M from"gi://GObject?version=2.0";let N=0;var RTCPeerConnection=class extends EventTarget{_pipeline;_webrtcbin;_bridge;_conf;_closed=!1;_iceRestartNeeded=!1;_hasNegotiated=!1;_dataChannels=new Map;_transceivers=new Map;_senders=[];_receivers=[];_iceTransport=null;_dtlsTransport=null;_sctpTransport=null;canTrickleIceCandidates=!0;constructor(n){super(),t();let[r,i]=e.version();if(r<1||r===1&&i<20)throw new O(`@gjsify/webrtc requires GStreamer >= 1.20 (you have ${r}.${i}). webrtcbin is only stable from 1.20 onward.`,`NotSupportedError`);let a=++N;this._pipeline=new e.Pipeline({name:`gjsify-webrtc-pipeline-${a}`});let o=e.ElementFactory.make(`webrtcbin`,`gjsify-webrtcbin-${a}`);if(!o)throw Error(`Failed to create webrtcbin element`);if(this._webrtcbin=o,this._conf={...n},n?.certificates){for(let e of n.certificates)if(e instanceof x&&e.expires<=Date.now())throw new O(`RTCPeerConnection: one of the provided certificates has expired`,`InvalidAccessError`)}this._applyIceServers(n?.iceServers??[]),this._applyIceTransportPolicy(n?.iceTransportPolicy),this._applyBundlePolicy(n?.bundlePolicy),this._pipeline.add(this._webrtcbin),this._bridge=new j({bin:this._webrtcbin}),this._bridge.connect(`negotiation-needed`,()=>this._handleNegotiationNeeded()),this._bridge.connect(`icecandidate`,(e,t,n)=>this._handleIceCandidate(t,n)),this._bridge.connect(`datachannel`,(e,t)=>this._handleDataChannel(t)),this._bridge.connect(`new-transceiver`,(e,t)=>this._handleNewTransceiver(t)),this._bridge.connect(`pad-added`,(e,t)=>this._handlePadAdded(t)),this._bridge.connect(`connection-state-changed`,()=>this._dispatchStateChange(`connectionstatechange`)),this._bridge.connect(`ice-connection-state-changed`,()=>this._dispatchStateChange(`iceconnectionstatechange`)),this._bridge.connect(`ice-gathering-state-changed`,()=>this._dispatchStateChange(`icegatheringstatechange`)),this._bridge.connect(`signaling-state-changed`,()=>this._dispatchStateChange(`signalingstatechange`)),this._pipeline.set_state(e.State.PLAYING)}_applyIceServers(e){let t=!1;for(let n of e){let e=Array.isArray(n.urls)?n.urls:[n.urls];if(e.length===0)throw SyntaxError(`RTCIceServer.urls must not be empty`);for(let r of e){if(typeof r!=`string`||r.length===0)throw TypeError(`RTCIceServer.urls entries must be non-empty strings`);let e=r.indexOf(`:`);if(e<0)throw TypeError(`Invalid ICE server URL "${r}"`);let i=r.slice(0,e+1),a=r.slice(e+1);if(i===`stun:`||i===`stuns:`){if(t)continue;s(this._webrtcbin).stun_server=`${i}//${a}`,t=!0}else if(i===`turn:`||i===`turns:`){if(typeof n.username!=`string`||typeof n.credential!=`string`)throw TypeError(`TURN server credential for ${r} missing`);let e=`${i}//${encodeURIComponent(n.username)}:${encodeURIComponent(n.credential)}@${a}`;try{this._webrtcbin.emit(`add-turn-server`,e)}catch{s(this._webrtcbin).turn_server=e}}else throw TypeError(`Unsupported ICE server protocol "${i}"`)}}}_applyIceTransportPolicy(e){if(!e)return;let t=e===`relay`?A.WebRTCICETransportPolicy.RELAY:A.WebRTCICETransportPolicy.ALL;try{s(this._webrtcbin).ice_transport_policy=t}catch{}}_applyBundlePolicy(e){if(!e)return;let t;switch(e){case`balanced`:t=A.WebRTCBundlePolicy.BALANCED;break;case`max-compat`:t=A.WebRTCBundlePolicy.MAX_COMPAT;break;case`max-bundle`:t=A.WebRTCBundlePolicy.MAX_BUNDLE;break;default:return}try{s(this._webrtcbin).bundle_policy=t}catch{}}get signalingState(){if(this._closed)return`closed`;try{return o(s(this._webrtcbin).signaling_state)}catch{return`stable`}}get connectionState(){if(this._closed)return`closed`;try{return r(s(this._webrtcbin).connection_state)}catch{return`new`}}get iceConnectionState(){if(this._closed)return`closed`;try{return i(s(this._webrtcbin).ice_connection_state)}catch{return`new`}}get iceGatheringState(){try{return a(s(this._webrtcbin).ice_gathering_state)}catch{return`new`}}_descProp(e){try{let t=s(this._webrtcbin)[e];return t?l.fromGstDesc(t):null}catch{return null}}get localDescription(){return this._descProp(`local_description`)}get remoteDescription(){return this._descProp(`remote_description`)}get currentLocalDescription(){return this._descProp(`current_local_description`)}get currentRemoteDescription(){return this._descProp(`current_remote_description`)}get pendingLocalDescription(){return this._descProp(`pending_local_description`)}get pendingRemoteDescription(){return this._descProp(`pending_remote_description`)}get sctp(){return this._sctpTransport}get peerIdentity(){return Promise.reject(TypeError(`peerIdentity assertions are not implemented`))}get idpErrorInfo(){return null}get idpLoginUrl(){return null}_rejectIfClosed(e){if(this._closed)throw new O(`RTCPeerConnection.${e}: connection is closed`,`InvalidStateError`)}_setStructureField(e,t,n,r){if(r==null)return;let i=new M.Value;n===`boolean`?(i.init(M.TYPE_BOOLEAN),i.set_boolean(!!r)):n===`int`?(i.init(M.TYPE_INT),i.set_int(Number(r))):n===`string`&&(i.init(M.TYPE_STRING),i.set_string(String(r))),e.set_value(t,i),i.unset()}close(){this._closed||(this._closed=!0,k.idle_add(k.PRIORITY_DEFAULT,()=>{try{this._pipeline.set_state(e.State.NULL)}catch{}for(let e of this._dataChannels.values())try{e._disconnectSignals()}catch{}this._dataChannels.clear();for(let e of this._senders)try{e._teardownPipeline()}catch{}for(let e of this._receivers)try{e._dispose()}catch{}this._transceivers.clear(),this._senders.length=0,this._receivers.length=0,this._dtlsTransport&&this._dtlsTransport._setState(`closed`),this._iceTransport&&this._iceTransport._setState(`closed`),this._sctpTransport&&this._sctpTransport._setState(`closed`);try{this._bridge.dispose_bridge()}catch{}return k.SOURCE_REMOVE}))}getIdentityAssertion(){return Promise.reject(Error(`getIdentityAssertion is not implemented`))}_findNewGstTransceiver(){for(let e=0;;e++){let t=this._webrtcbin.emit(`get-transceiver`,e);if(!t)return null;if(!this._transceivers.has(t))return t}}_ensureTransports(){return this._dtlsTransport||=(this._iceTransport=new v,new y(this._iceTransport)),this._dtlsTransport}_ensureSctpTransport(){if(this._sctpTransport)return;let e=this._ensureTransports();this._sctpTransport=new b(e)}_createTransceiverWrapper(e){let t=`audio`;try{e.kind===A.WebRTCKind.VIDEO&&(t=`video`)}catch{}let n=e.receiver??null,r=e.sender??null,i=new h(t,n,this._pipeline),a=new m(r,this._pipeline,this._webrtcbin);a._kind=t,a._onPipelineChanged=e=>{this._pipeline=e};let statsDelegate=e=>this.getStats(e);a._getStatsForTrack=statsDelegate,i._getStatsForTrack=statsDelegate;let o=this._ensureTransports();a._transport=o,i._transport=o;try{let t=e.mlineindex;typeof t==`number`&&t>=0&&a._setMlineIndex(t)}catch{}let s=new g(e,a,i);return a._transceiver=s,this._transceivers.set(e,s),this._senders.push(a),this._receivers.push(i),s}_handleNegotiationNeeded(){let e=new Event(`negotiationneeded`);this._onnegotiationneeded?.call(this,e),this.dispatchEvent(e)}_handleIceCandidate(e,t){let n=new f(`icecandidate`,{candidate:new u({candidate:t,sdpMLineIndex:e})});this._onicecandidate?.call(this,n),this.dispatchEvent(n)}_handleNewTransceiver(e){this._closed||this._transceivers.has(e)||this._createTransceiverWrapper(e)}_handlePadAdded(t){if(this._closed||t.direction!==e.PadDirection.SRC)return;let r=c(t).transceiver;if(!r)return;let i=this._transceivers.get(r);i||=this._createTransceiverWrapper(r),i.receiver._connectToPad(t);let a=new n([i.receiver.track]),o=new _(`track`,{receiver:i.receiver,track:i.receiver.track,streams:[a],transceiver:i});this._ontrack?.call(this,o),this.dispatchEvent(o)}_handleDataChannel(e){this._ensureSctpTransport();let t=e.channel,n=this._dataChannels.get(t);n||(n=new p(e,this._sctpTransport??void 0),this._dataChannels.set(t,n),n.addEventListener(`close`,()=>{this._dataChannels.delete(t)}));let r=new d(`datachannel`,{channel:n});this._ondatachannel?.call(this,r),this.dispatchEvent(r)}_dispatchStateChange(e){e===`connectionstatechange`?this._syncDtlsState():e===`iceconnectionstatechange`?this._syncIceState():e===`icegatheringstatechange`&&this._syncIceGatheringState();let t=new Event(e);switch(e){case`connectionstatechange`:this._onconnectionstatechange?.call(this,t);break;case`iceconnectionstatechange`:this._oniceconnectionstatechange?.call(this,t);break;case`icegatheringstatechange`:this._onicegatheringstatechange?.call(this,t);break;case`signalingstatechange`:this._onsignalingstatechange?.call(this,t);break}this.dispatchEvent(t)}_syncDtlsState(){if(!this._dtlsTransport)return;let e=this.connectionState;this._dtlsTransport._setState({new:`new`,connecting:`connecting`,connected:`connected`,disconnected:`connected`,failed:`failed`,closed:`closed`}[e]??`new`),e===`connected`&&this._sctpTransport&&this._sctpTransport._setState(`connected`)}_syncIceState(){if(!this._iceTransport)return;let e=this.iceConnectionState;this._iceTransport._setState(e)}_syncIceGatheringState(){if(!this._iceTransport)return;let e=this.iceGatheringState;this._iceTransport._setGatheringState(e)}_onconnectionstatechange=null;_ondatachannel=null;_onicecandidate=null;_oniceconnectionstatechange=null;_onicegatheringstatechange=null;_onnegotiationneeded=null;_onsignalingstatechange=null;get onconnectionstatechange(){return this._onconnectionstatechange}set onconnectionstatechange(e){this._onconnectionstatechange=e}get ondatachannel(){return this._ondatachannel}set ondatachannel(e){this._ondatachannel=e}get onicecandidate(){return this._onicecandidate}set onicecandidate(e){this._onicecandidate=e}get oniceconnectionstatechange(){return this._oniceconnectionstatechange}set oniceconnectionstatechange(e){this._oniceconnectionstatechange=e}get onicegatheringstatechange(){return this._onicegatheringstatechange}set onicegatheringstatechange(e){this._onicegatheringstatechange=e}get onnegotiationneeded(){return this._onnegotiationneeded}set onnegotiationneeded(e){this._onnegotiationneeded=e}get onsignalingstatechange(){return this._onsignalingstatechange}set onsignalingstatechange(e){this._onsignalingstatechange=e}_ontrack=null;get ontrack(){return this._ontrack}set ontrack(e){this._ontrack=e}get onicecandidateerror(){return null}set onicecandidateerror(e){}static generateCertificate(e){return S(e)}};C(RTCPeerConnection.prototype),w(RTCPeerConnection.prototype),T(RTCPeerConnection.prototype),E(RTCPeerConnection.prototype),D(RTCPeerConnection.prototype);export{RTCPeerConnection};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Gst as e,ensureWebrtcbinAvailable as t}from"./gst-init.js";import{MediaStream as n}from"./media-stream.js";import{gstToConnectionState as r,gstToIceConnectionState as i,gstToIceGatheringState as a,gstToSignalingState as o}from"./gst-enum-maps.js";import{asWebRtcBin as s,asWebRtcSrcPad as c}from"./internal/gst-types.js";import{RTCSessionDescription as l}from"./rtc-session-description.js";import{RTCIceCandidate as u}from"./rtc-ice-candidate.js";import{RTCDataChannelEvent as d,RTCPeerConnectionIceEvent as f}from"./rtc-events.js";import{RTCDataChannel as p}from"./rtc-data-channel.js";import{RTCRtpSender as m}from"./rtc-rtp-sender.js";import{RTCRtpReceiver as h}from"./rtc-rtp-receiver.js";import{RTCRtpTransceiver as g}from"./rtc-rtp-transceiver.js";import{RTCTrackEvent as _}from"./rtc-track-event.js";import{RTCIceTransport as v}from"./rtc-ice-transport.js";import{RTCDtlsTransport as y}from"./rtc-dtls-transport.js";import{RTCSctpTransport as b}from"./rtc-sctp-transport.js";import{RTCCertificate as x,generateCertificate as S}from"./rtc-certificate.js";import{installSdpNegotiationMethods as C}from"./rtc-peer-connection/sdp-negotiation.js";import{installDataChannelMethods as w}from"./rtc-peer-connection/data-channel.js";import{installTransceiverMethods as T}from"./rtc-peer-connection/transceivers.js";import{installTrackMethods as E}from"./rtc-peer-connection/tracks.js";import{installStatsAndConfigMethods as D}from"./rtc-peer-connection/stats-and-config.js";import{DOMException as O}from"@gjsify/dom-exception";import k from"gi://GLib?version=2.0";import A from"gi://GstWebRTC?version=1.0";import{WebrtcbinBridge as j}from"@gjsify/webrtc-native";import M from"gi://GObject?version=2.0";let N=0;var RTCPeerConnection=class extends EventTarget{_pipeline;_webrtcbin;_bridge;_conf;_closed=!1;_iceRestartNeeded=!1;_hasNegotiated=!1;_dataChannels=new Map;_transceivers=new Map;_senders=[];_receivers=[];_iceTransport=null;_dtlsTransport=null;_sctpTransport=null;canTrickleIceCandidates=!0;constructor(n){super(),t();let[r,i]=e.version();if(r<1||r===1&&i<20)throw new O(`@gjsify/webrtc requires GStreamer >= 1.20 (you have ${r}.${i}). webrtcbin is only stable from 1.20 onward.`,`NotSupportedError`);let a=++N;this._pipeline=new e.Pipeline({name:`gjsify-webrtc-pipeline-${a}`});let o=e.ElementFactory.make(`webrtcbin`,`gjsify-webrtcbin-${a}`);if(!o)throw Error(`Failed to create webrtcbin element`);if(this._webrtcbin=o,this._conf={...n},n?.certificates){for(let e of n.certificates)if(e instanceof x&&e.expires<=Date.now())throw new O(`RTCPeerConnection: one of the provided certificates has expired`,`InvalidAccessError`)}this._applyIceServers(n?.iceServers??[]),this._applyIceTransportPolicy(n?.iceTransportPolicy),this._applyBundlePolicy(n?.bundlePolicy),this._pipeline.add(this._webrtcbin),this._bridge=new j({bin:this._webrtcbin}),this._bridge.connect(`negotiation-needed`,()=>this._handleNegotiationNeeded()),this._bridge.connect(`icecandidate`,(e,t,n)=>this._handleIceCandidate(t,n)),this._bridge.connect(`datachannel`,(e,t)=>this._handleDataChannel(t)),this._bridge.connect(`new-transceiver`,(e,t)=>this._handleNewTransceiver(t)),this._bridge.connect(`pad-added`,(e,t)=>this._handlePadAdded(t)),this._bridge.connect(`connection-state-changed`,()=>this._dispatchStateChange(`connectionstatechange`)),this._bridge.connect(`ice-connection-state-changed`,()=>this._dispatchStateChange(`iceconnectionstatechange`)),this._bridge.connect(`ice-gathering-state-changed`,()=>this._dispatchStateChange(`icegatheringstatechange`)),this._bridge.connect(`signaling-state-changed`,()=>this._dispatchStateChange(`signalingstatechange`)),this._pipeline.set_state(e.State.PLAYING)}_applyIceServers(e){let t=!1;for(let n of e){let e=Array.isArray(n.urls)?n.urls:[n.urls];if(e.length===0)throw SyntaxError(`RTCIceServer.urls must not be empty`);for(let r of e){if(typeof r!=`string`||r.length===0)throw TypeError(`RTCIceServer.urls entries must be non-empty strings`);let e=r.indexOf(`:`);if(e<0)throw TypeError(`Invalid ICE server URL "${r}"`);let i=r.slice(0,e+1),a=r.slice(e+1);if(i===`stun:`||i===`stuns:`){if(t)continue;s(this._webrtcbin).stun_server=`${i}//${a}`,t=!0}else if(i===`turn:`||i===`turns:`){if(typeof n.username!=`string`||typeof n.credential!=`string`)throw TypeError(`TURN server credential for ${r} missing`);let e=`${i}//${encodeURIComponent(n.username)}:${encodeURIComponent(n.credential)}@${a}`;try{this._webrtcbin.emit(`add-turn-server`,e)}catch{s(this._webrtcbin).turn_server=e}}else throw TypeError(`Unsupported ICE server protocol "${i}"`)}}}_applyIceTransportPolicy(e){if(!e)return;let t=e===`relay`?A.WebRTCICETransportPolicy.RELAY:A.WebRTCICETransportPolicy.ALL;try{s(this._webrtcbin).ice_transport_policy=t}catch{}}_applyBundlePolicy(e){if(!e)return;let t;switch(e){case`balanced`:t=A.WebRTCBundlePolicy.BALANCED;break;case`max-compat`:t=A.WebRTCBundlePolicy.MAX_COMPAT;break;case`max-bundle`:t=A.WebRTCBundlePolicy.MAX_BUNDLE;break;default:return}try{s(this._webrtcbin).bundle_policy=t}catch{}}get signalingState(){if(this._closed)return`closed`;try{return o(s(this._webrtcbin).signaling_state)}catch{return`stable`}}get connectionState(){if(this._closed)return`closed`;try{return r(s(this._webrtcbin).connection_state)}catch{return`new`}}get iceConnectionState(){if(this._closed)return`closed`;try{return i(s(this._webrtcbin).ice_connection_state)}catch{return`new`}}get iceGatheringState(){try{return a(s(this._webrtcbin).ice_gathering_state)}catch{return`new`}}_descProp(e){try{let t=s(this._webrtcbin)[e];return t?l.fromGstDesc(t):null}catch{return null}}get localDescription(){return this._descProp(`local_description`)}get remoteDescription(){return this._descProp(`remote_description`)}get currentLocalDescription(){return this._descProp(`current_local_description`)}get currentRemoteDescription(){return this._descProp(`current_remote_description`)}get pendingLocalDescription(){return this._descProp(`pending_local_description`)}get pendingRemoteDescription(){return this._descProp(`pending_remote_description`)}get sctp(){return this._sctpTransport}get peerIdentity(){return Promise.reject(TypeError(`peerIdentity assertions are not implemented`))}get idpErrorInfo(){return null}get idpLoginUrl(){return null}_rejectIfClosed(e){if(this._closed)throw new O(`RTCPeerConnection.${e}: connection is closed`,`InvalidStateError`)}_setStructureField(e,t,n,r){if(r==null)return;let i=new M.Value;n===`boolean`?(i.init(M.TYPE_BOOLEAN),i.set_boolean(!!r)):n===`int`?(i.init(M.TYPE_INT),i.set_int(Number(r))):n===`string`&&(i.init(M.TYPE_STRING),i.set_string(String(r))),e.set_value(t,i),i.unset()}close(){this._closed||(this._closed=!0,k.idle_add(k.PRIORITY_DEFAULT,()=>{try{this._pipeline.set_state(e.State.NULL)}catch{}for(let e of this._dataChannels.values())try{e._disconnectSignals()}catch{}this._dataChannels.clear();for(let e of this._senders)try{e._teardownPipeline()}catch{}for(let e of this._receivers)try{e._dispose()}catch{}this._transceivers.clear(),this._senders.length=0,this._receivers.length=0,this._dtlsTransport&&this._dtlsTransport._setState(`closed`),this._iceTransport&&this._iceTransport._setState(`closed`),this._sctpTransport&&this._sctpTransport._setState(`closed`);try{this._bridge.dispose_bridge()}catch{}return k.SOURCE_REMOVE}))}getIdentityAssertion(){return Promise.reject(Error(`getIdentityAssertion is not implemented`))}_findNewGstTransceiver(){for(let e=0;;e++){let t=this._webrtcbin.emit(`get-transceiver`,e);if(!t)return null;if(!this._transceivers.has(t))return t}}_ensureTransports(){return this._dtlsTransport||=(this._iceTransport=new v,new y(this._iceTransport)),this._dtlsTransport}_ensureSctpTransport(){if(this._sctpTransport)return;let e=this._ensureTransports();this._sctpTransport=new b(e)}_assignTransports(){let e=this._ensureTransports();for(let t of this._senders)t._transport=e;for(let t of this._receivers)t._transport=e}_clearTransports(){for(let e of this._senders)e._transport=null;for(let e of this._receivers)e._transport=null}_createTransceiverWrapper(e){let t=`audio`;try{e.kind===A.WebRTCKind.VIDEO&&(t=`video`)}catch{}let n=e.receiver??null,r=e.sender??null,i=new h(t,n,this._pipeline),a=new m(r,this._pipeline,this._webrtcbin);a._kind=t,a._onPipelineChanged=e=>{this._pipeline=e};let statsDelegate=e=>this.getStats(e);if(a._getStatsForTrack=statsDelegate,i._getStatsForTrack=statsDelegate,this.localDescription){let e=this._ensureTransports();a._transport=e,i._transport=e}try{let t=e.mlineindex;typeof t==`number`&&t>=0&&a._setMlineIndex(t)}catch{}let o=new g(e,a,i);return a._transceiver=o,this._transceivers.set(e,o),this._senders.push(a),this._receivers.push(i),o}_handleNegotiationNeeded(){if(this._closed)return;let e=new Event(`negotiationneeded`);this._onnegotiationneeded?.call(this,e),this.dispatchEvent(e)}_negotiationNeededQueued=!1;_updateNegotiationNeeded(){this._closed||this._hasNegotiated&&this.signalingState===`stable`&&(this._negotiationNeededQueued||(this._negotiationNeededQueued=!0,Promise.resolve().then(()=>{this._negotiationNeededQueued=!1,this.signalingState===`stable`&&this._handleNegotiationNeeded()})))}_handleIceCandidate(e,t){let n=new f(`icecandidate`,{candidate:new u({candidate:t,sdpMLineIndex:e})});this._onicecandidate?.call(this,n),this.dispatchEvent(n)}_handleNewTransceiver(e){this._closed||this._transceivers.has(e)||this._createTransceiverWrapper(e)}_handlePadAdded(t){if(this._closed||t.direction!==e.PadDirection.SRC)return;let r=c(t).transceiver;if(!r)return;let i=this._transceivers.get(r);i||=this._createTransceiverWrapper(r),i.receiver._connectToPad(t);let a=new n([i.receiver.track]),o=new _(`track`,{receiver:i.receiver,track:i.receiver.track,streams:[a],transceiver:i});this._ontrack?.call(this,o),this.dispatchEvent(o)}_handleDataChannel(e){this._ensureSctpTransport();let t=e.channel,n=this._dataChannels.get(t);n||(n=new p(e,this._sctpTransport??void 0),this._dataChannels.set(t,n),n.addEventListener(`close`,()=>{this._dataChannels.delete(t)}));let r=new d(`datachannel`,{channel:n});this._ondatachannel?.call(this,r),this.dispatchEvent(r)}_dispatchStateChange(e){e===`connectionstatechange`?this._syncDtlsState():e===`iceconnectionstatechange`?this._syncIceState():e===`icegatheringstatechange`&&this._syncIceGatheringState();let t=new Event(e);switch(e){case`connectionstatechange`:this._onconnectionstatechange?.call(this,t);break;case`iceconnectionstatechange`:this._oniceconnectionstatechange?.call(this,t);break;case`icegatheringstatechange`:this._onicegatheringstatechange?.call(this,t);break;case`signalingstatechange`:this._onsignalingstatechange?.call(this,t);break}this.dispatchEvent(t)}_syncDtlsState(){if(!this._dtlsTransport)return;let e=this.connectionState;this._dtlsTransport._setState({new:`new`,connecting:`connecting`,connected:`connected`,disconnected:`connected`,failed:`failed`,closed:`closed`}[e]??`new`),e===`connected`&&this._sctpTransport&&this._sctpTransport._setState(`connected`)}_syncIceState(){if(!this._iceTransport)return;let e=this.iceConnectionState;this._iceTransport._setState(e)}_syncIceGatheringState(){if(!this._iceTransport)return;let e=this.iceGatheringState;this._iceTransport._setGatheringState(e)}_onconnectionstatechange=null;_ondatachannel=null;_onicecandidate=null;_oniceconnectionstatechange=null;_onicegatheringstatechange=null;_onnegotiationneeded=null;_onsignalingstatechange=null;get onconnectionstatechange(){return this._onconnectionstatechange}set onconnectionstatechange(e){this._onconnectionstatechange=e}get ondatachannel(){return this._ondatachannel}set ondatachannel(e){this._ondatachannel=e}get onicecandidate(){return this._onicecandidate}set onicecandidate(e){this._onicecandidate=e}get oniceconnectionstatechange(){return this._oniceconnectionstatechange}set oniceconnectionstatechange(e){this._oniceconnectionstatechange=e}get onicegatheringstatechange(){return this._onicegatheringstatechange}set onicegatheringstatechange(e){this._onicegatheringstatechange=e}get onnegotiationneeded(){return this._onnegotiationneeded}set onnegotiationneeded(e){this._onnegotiationneeded=e}get onsignalingstatechange(){return this._onsignalingstatechange}set onsignalingstatechange(e){this._onsignalingstatechange=e}_ontrack=null;get ontrack(){return this._ontrack}set ontrack(e){this._ontrack=e}get onicecandidateerror(){return null}set onicecandidateerror(e){}static generateCertificate(e){return S(e)}};C(RTCPeerConnection.prototype),w(RTCPeerConnection.prototype),T(RTCPeerConnection.prototype),E(RTCPeerConnection.prototype),D(RTCPeerConnection.prototype);export{RTCPeerConnection};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{Gst as e}from"./gst-init.js";import{asCapsFilterElement as
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Gst as e}from"./gst-init.js";import{getRtcpCname as t}from"./gst-utils.js";import{asCapsFilterElement as n,asRtpPayloaderElement as r,asValveElement as i,asVp8EncElement as a,asWebRtcBin as o}from"./internal/gst-types.js";import{getRtpCapabilities as s}from"./rtp-capabilities.js";import{parseMediaSectionParams as c}from"./sdp-params.js";import{RTCDTMFSender as l}from"./rtc-dtmf-sender.js";import{TeeMultiplexer as u}from"./tee-multiplexer.js";let d=0;var RTCRtpSender=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 l;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 o=t._gstSource;if(!o)return;let s=t,c;if(s._gstTee&&s._gstPipeline&&s._gstPipeline!==this._pipeline){let t=s._gstPipeline,n=s._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,c=null}else if(s._teeMultiplexer){let e=s._teeMultiplexer.requestSrcPad();this._teeSrcPad=e,c=null}else if(s._gstPipeline&&s._gstPipeline!==this._pipeline&&s._senderConsumers>0){let t=s._gstPipeline,n=o.get_static_pad(`src`),r=n?.get_peer?.();r&&n.unlink(r),o.set_state(e.State.NULL),t.remove(o),this._pipeline.add(o),s._gstPipeline=this._pipeline;let i=new u(this._pipeline,o);if(s._teeMultiplexer=i,r){let e=i.requestSrcPad();e&&e.link(r)}let a=i.requestSrcPad();this._teeSrcPad=a,c=null}else{let t=s._gstPipeline;t&&t!==this._pipeline&&(o.set_state(e.State.NULL),t.remove(o),s._gstPipeline=this._pipeline),o.get_parent()!==this._pipeline&&this._pipeline.add(o),c=o}let l=i(e.ElementFactory.make(`valve`,null));l.drop=!t.enabled,this._valve=l,this._pipeline.add(l);let d=[l],f;if(t.kind===`audio`){let t=e.ElementFactory.make(`audioconvert`,null),i=e.ElementFactory.make(`audioresample`,null),a=e.ElementFactory.make(`opusenc`,null),o=r(e.ElementFactory.make(`rtpopuspay`,null));o.pt=111;let s=n(e.ElementFactory.make(`capsfilter`,null));s.caps=e.Caps.from_string(`application/x-rtp,media=audio,encoding-name=OPUS,clock-rate=48000,payload=111`),d.push(t,i,a,o,s);for(let e of d)this._pipeline.add(e);if(this._teeSrcPad){let e=l.get_static_pad(`sink`);this._teeSrcPad.link(e)}else c&&c.link(l);l.link(t),t.link(i),i.link(a),a.link(o),o.link(s),f=s}else{let t=e.ElementFactory.make(`videoconvert`,null),i=e.ElementFactory.make(`videoscale`,null),o=a(e.ElementFactory.make(`vp8enc`,null));o.deadline=1,o.keyframe_max_dist=60;let s=r(e.ElementFactory.make(`rtpvp8pay`,null));s.pt=96;let u=n(e.ElementFactory.make(`capsfilter`,null));u.caps=e.Caps.from_string(`application/x-rtp,media=video,encoding-name=VP8,clock-rate=90000,payload=96`),d.push(t,i,o,s,u);for(let e of d)this._pipeline.add(e);if(this._teeSrcPad){let e=l.get_static_pad(`sink`);this._teeSrcPad.link(e)}else c&&c.link(l);l.link(t),t.link(i),i.link(o),o.link(s),s.link(u),f=u}let p=this._mlineIndex>=0?`sink_${this._mlineIndex}`:`sink_%u`,m=this._webrtcbin.request_pad_simple?this._webrtcbin.request_pad_simple(p):this._webrtcbin.get_request_pad(p);m&&f.get_static_pad(`src`).link(m);let h=this._teeSrcPad?d:[o,...d];for(let e of h)e.sync_state_with_parent();this._elements=h,this._linked=!0,t._senderConsumers++,t._setEnableCallback(e=>{this._valve&&(this._valve.drop=!e)})}_teardownPipeline(){if(this._linked){if(this._track&&(this._track._setEnableCallback(null),this._track._senderConsumers=Math.max(0,this._track._senderConsumers-1)),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(){let e=this._negotiatedParams();this._lastParams?(this._lastParams.codecs=e.codecs,this._lastParams.headerExtensions=e.headerExtensions,this._lastParams.rtcp=e.rtcp):this._lastParams={transactionId:String(++d),encodings:[],...e};let t=this._lastParams;return{...t,encodings:[...t.encodings],codecs:t.codecs.map(e=>({...e})),headerExtensions:t.headerExtensions.map(e=>({...e})),rtcp:{...t.rtcp}}}_negotiatedParams(){let e={},n={codecs:[],headerExtensions:[],rtcp:e};if(!this._webrtcbin)return n;let r=t(this._webrtcbin);r!==void 0&&(e.cname=r);let i=o(this._webrtcbin),a=(i.current_remote_description??i.current_local_description)?.sdp?.as_text?.()??``;if(!a)return n;let s=this._track?.kind??this._kind,l=c(a,{mid:this._transceiver?.mid??void 0,mlineIndex:this._mlineIndex>=0?this._mlineIndex:void 0,kind:s??void 0});return l?(n.codecs=l.codecs,n.headerExtensions=l.headerExtensions,e.reducedSize=l.reducedSize,n):n}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`);let n=t;if(this._linked&&n._gstSource){let t=this._elements[0],r=n._gstSource,i=n._gstPipeline;i&&i!==this._pipeline&&(r.set_state(e.State.NULL),i.remove(r),n._gstPipeline=this._pipeline),t.set_state(e.State.NULL),this._valve&&t.unlink(this._valve),this._pipeline?.remove(t),this._pipeline?.add(r),this._valve&&r.link(this._valve),r.sync_state_with_parent(),this._elements[0]=r}else n._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 s(e)}};export{RTCRtpSender};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import"@gjsify/dom-events/register/event-target";var RTCSctpTransport=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{RTCSctpTransport};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import"@gjsify/dom-events/register/event-target";var RTCSctpTransport=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}_setMaxMessageSize(e){if(typeof e!=`number`||!Number.isFinite(e)||e<0)throw TypeError(`RTCSctpTransport: invalid max-message-size ${String(e)}`);this._maxMessageSize=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{RTCSctpTransport};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import e from"gi://GstWebRTC?version=1.0";import t from"gi://GstSdp?version=1.0";function sdpTypeToGst(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 sdpTypeFromGst(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 n=class RTCSessionDescription{type;sdp;constructor(e){this.type=e?.type??`offer`,this.sdp=e?.sdp??``}toJSON(){return{type:this.type,sdp:this.sdp}}toGstDesc(){let[n,r]=t.SDPMessage.new_from_text(this.sdp);if(n!==t.SDPResult.OK)throw Error(`Failed to parse SDP text (GstSDPResult=${n})`);return e.WebRTCSessionDescription.new(sdpTypeToGst(this.type),r)}static fromGstDesc(e){let t=e.sdp?.as_text?.()??``;return new RTCSessionDescription({type:sdpTypeFromGst(e.type),sdp:t})}};export{n as RTCSessionDescription};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import e from"gi://GstWebRTC?version=1.0";import t from"gi://GstSdp?version=1.0";function sdpTypeToGst(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 sdpTypeFromGst(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 n=class RTCSessionDescription{type;sdp;constructor(e){this.type=e?.type??`offer`,this.sdp=e?.sdp??``}toJSON(){return{type:this.type,sdp:this.sdp}}toGstDesc(){if(this.type===`rollback`){let[n,r]=t.SDPMessage.new();if(n!==t.SDPResult.OK)throw Error(`Failed to create empty SDP message (GstSDPResult=${n})`);return e.WebRTCSessionDescription.new(e.WebRTCSDPType.ROLLBACK,r)}let[n,r]=t.SDPMessage.new_from_text(this.sdp);if(n!==t.SDPResult.OK)throw Error(`Failed to parse SDP text (GstSDPResult=${n})`);return e.WebRTCSessionDescription.new(sdpTypeToGst(this.type),r)}static fromGstDesc(e){let t=e.sdp?.as_text?.()??``;return new RTCSessionDescription({type:sdpTypeFromGst(e.type),sdp:t})}};export{n as RTCSessionDescription};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";const e={codecs:[{mimeType:`audio/opus`,clockRate:48e3,channels:2,sdpFmtpLine:`minptime=10;useinbandfec=1`},{mimeType:`audio/G722`,clockRate:8e3,channels:1},{mimeType:`audio/PCMU`,clockRate:8e3,channels:1},{mimeType:`audio/PCMA`,clockRate:8e3,channels:1},{mimeType:`audio/telephone-event`,clockRate:8e3,channels:1},{mimeType:`audio/red`,clockRate:48e3,channels:2}],headerExtensions:[{uri:`urn:ietf:params:rtp-hdrext:ssrc-audio-level`},{uri:`http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time`},{uri:`urn:ietf:params:rtp-hdrext:sdes:mid`}]},t={codecs:[{mimeType:`video/VP8`,clockRate:9e4},{mimeType:`video/rtx`,clockRate:9e4},{mimeType:`video/H264`,clockRate:9e4,sdpFmtpLine:`level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f`},{mimeType:`video/VP9`,clockRate:9e4},{mimeType:`video/red`,clockRate:9e4},{mimeType:`video/ulpfec`,clockRate:9e4}],headerExtensions:[{uri:`urn:ietf:params:rtp-hdrext:toffset`},{uri:`http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time`},{uri:`urn:3gpp:video-orientation`},{uri:`urn:ietf:params:rtp-hdrext:sdes:mid`},{uri:`urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id`},{uri:`urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id`}]};function getRtpCapabilities(n){return n===`audio`?e:n===`video`?t:null}export{getRtpCapabilities};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";const e={codecs:[{mimeType:`audio/opus`,clockRate:48e3,channels:2,sdpFmtpLine:`minptime=10;useinbandfec=1`},{mimeType:`audio/G722`,clockRate:8e3,channels:1},{mimeType:`audio/PCMU`,clockRate:8e3,channels:1},{mimeType:`audio/PCMA`,clockRate:8e3,channels:1},{mimeType:`audio/telephone-event`,clockRate:8e3,channels:1},{mimeType:`audio/red`,clockRate:48e3,channels:2}],headerExtensions:[{uri:`urn:ietf:params:rtp-hdrext:ssrc-audio-level`},{uri:`http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time`},{uri:`urn:ietf:params:rtp-hdrext:sdes:mid`}]},t={codecs:[{mimeType:`video/VP8`,clockRate:9e4},{mimeType:`video/rtx`,clockRate:9e4},{mimeType:`video/H264`,clockRate:9e4,sdpFmtpLine:`level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f`},{mimeType:`video/VP9`,clockRate:9e4},{mimeType:`video/red`,clockRate:9e4},{mimeType:`video/ulpfec`,clockRate:9e4}],headerExtensions:[{uri:`urn:ietf:params:rtp-hdrext:toffset`},{uri:`http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time`},{uri:`urn:3gpp:video-orientation`},{uri:`urn:ietf:params:rtp-hdrext:sdes:mid`},{uri:`urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id`},{uri:`urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id`}]};function getRtpCapabilities(n){return n===`audio`?e:n===`video`?t:null}const n=111,r=96;function defaultRtpCapsString(e){return e===`audio`?`application/x-rtp,media=audio,encoding-name=OPUS,clock-rate=48000,payload=111`:`application/x-rtp,media=video,encoding-name=VP8,clock-rate=90000,payload=96`}export{n as OPUS_PAYLOAD_TYPE,r as VP8_PAYLOAD_TYPE,defaultRtpCapsString,getRtpCapabilities};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{fillRandomBytes as e}from"@gjsify/webcrypto/random";function parseMediaSectionParams(e,t){let n=[],r=null;for(let t of e.split(/\r\n|\r|\n/)){let e=t.trimEnd();e.startsWith(`m=`)?(r=[e],n.push(r)):r&&e.length>0&&r.push(e)}let i;if(t.mid!==void 0&&(i=n.find(e=>e.includes(`a=mid:${t.mid}`))),!i&&t.mlineIndex!==void 0&&t.mlineIndex>=0&&(i=n[t.mlineIndex]),!i&&t.kind!==void 0&&(i=n.find(e=>e[0].startsWith(`m=${t.kind} `))),!i)return null;let a=i[0].split(` `),o=a[0].slice(2),s=a.slice(3).map(Number).filter(Number.isInteger),c=new Map,l=new Map,u=[],d=!1;for(let e of i){let t=/^a=rtpmap:(\d+) ([^/]+)\/(\d+)(?:\/(\d+))?/.exec(e);if(t){let e={encoding:t[2],clockRate:Number(t[3])};t[4]!==void 0&&(e.channels=Number(t[4])),c.set(Number(t[1]),e);continue}if(t=/^a=fmtp:(\d+) (.+)/.exec(e),t){l.set(Number(t[1]),t[2]);continue}if(t=/^a=extmap:(\d+)(?:\/\S+)? (\S+)/.exec(e),t){u.push({id:Number(t[1]),uri:t[2]});continue}e===`a=rtcp-rsize`&&(d=!0)}let f=[];for(let e of s){let t=c.get(e);if(!t)continue;let n={payloadType:e,mimeType:`${o}/${t.encoding}`,clockRate:t.clockRate};t.channels!==void 0&&(n.channels=t.channels);let r=l.get(e);r!==void 0&&(n.sdpFmtpLine=r),f.push(n)}return{codecs:f,headerExtensions:u,reducedSize:d}}function randomIceString(t){let n=new Uint8Array(t);e(n);let r=``;for(let e of n)r+=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`[e&63];return r}function rewriteIceCredentials(e){let t=new Map,n=new Map;return e.split(`\r
|
|
2
|
+
`).map(e=>{if(e.startsWith(`a=ice-ufrag:`)){let n=e.slice(12);return t.has(n)||t.set(n,randomIceString(8)),`a=ice-ufrag:${t.get(n)}`}if(e.startsWith(`a=ice-pwd:`)){let t=e.slice(10);return n.has(t)||n.set(t,randomIceString(24)),`a=ice-pwd:${n.get(t)}`}return e}).join(`\r
|
|
3
|
+
`)}export{parseMediaSectionParams,rewriteIceCredentials};
|
package/lib/types/gst-utils.d.ts
CHANGED
|
@@ -9,3 +9,14 @@ import type Gst from 'gi://Gst?version=1.0';
|
|
|
9
9
|
* });
|
|
10
10
|
*/
|
|
11
11
|
export declare function withGstPromise(emit: (promise: Gst.Promise) => void): Promise<Gst.Structure | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Read the RTP CNAME of a webrtcbin — "the CNAME of the associated
|
|
14
|
+
* RTCPeerConnection" that W3C § 5.2 getParameters exposes as `rtcp.cname`.
|
|
15
|
+
*
|
|
16
|
+
* webrtcbin's internal rtpbin generates one canonical name per connection
|
|
17
|
+
* (used in its RTCP SDES packets) and exposes it through rtpbin's `sdes`
|
|
18
|
+
* GstStructure (`application/x-rtp-source-sdes, cname=(string)…`). The
|
|
19
|
+
* rtpbin child is class-installed by GstWebRTCBin under the fixed name
|
|
20
|
+
* "rtpbin".
|
|
21
|
+
*/
|
|
22
|
+
export declare function getRtcpCname(webrtcbin: Gst.Element): string | undefined;
|
|
@@ -33,6 +33,14 @@ export declare class MediaStreamTrack extends EventTarget {
|
|
|
33
33
|
_gstTee: GstNs.Element | null;
|
|
34
34
|
/** @internal TeeMultiplexer for multi-PC fan-out (created on second addTrack) */
|
|
35
35
|
_teeMultiplexer: TeeMultiplexer | null;
|
|
36
|
+
/**
|
|
37
|
+
* @internal Number of RTCRtpSenders currently consuming `_gstSource`.
|
|
38
|
+
* The FIRST consumer moves the source out of its holding pipeline (the
|
|
39
|
+
* one getUserMedia parked it in) into the PC pipeline; only a SECOND
|
|
40
|
+
* concurrent consumer inserts the TeeMultiplexer fan-out. Maintained by
|
|
41
|
+
* RTCRtpSender._wirePipeline / _teardownPipeline.
|
|
42
|
+
*/
|
|
43
|
+
_senderConsumers: number;
|
|
36
44
|
/** @internal Callback set by RTCRtpSender to control valve drop property */
|
|
37
45
|
private _enableCallback;
|
|
38
46
|
constructor(init: MediaStreamTrackInit);
|
|
@@ -105,8 +105,41 @@ export declare class RTCPeerConnection extends EventTarget {
|
|
|
105
105
|
_ensureTransports(): RTCDtlsTransport;
|
|
106
106
|
/** Create the SCTP transport when a data channel is first negotiated. */
|
|
107
107
|
_ensureSctpTransport(): void;
|
|
108
|
+
/**
|
|
109
|
+
* @internal — attach the shared DTLS transport to every sender/receiver.
|
|
110
|
+
* Called when a LOCAL description is applied: per W3C § 4.4.1.5 (set
|
|
111
|
+
* session description → "create the DTLS transports") and the WPT
|
|
112
|
+
* canonical refs/wpt/webrtc/RTCRtpSender.https.html, `sender.transport` /
|
|
113
|
+
* `receiver.transport` is null until setLocalDescription ("null transport
|
|
114
|
+
* initially", "a transport after sLD(offer)") and stays null on the peer
|
|
115
|
+
* that only applied a REMOTE offer ("null transport after sRD(offer)").
|
|
116
|
+
*/
|
|
117
|
+
_assignTransports(): void;
|
|
118
|
+
/**
|
|
119
|
+
* @internal — detach the transports again when the initial offer is
|
|
120
|
+
* rolled back (WPT RTCRtpSender.https.html: "null transport after
|
|
121
|
+
* rollback of sLD(offer)"). The caller only invokes this while no
|
|
122
|
+
* negotiation has completed — after a completed offer/answer the
|
|
123
|
+
* transports survive a renegotiation rollback.
|
|
124
|
+
*/
|
|
125
|
+
_clearTransports(): void;
|
|
108
126
|
_createTransceiverWrapper(gstTrans: GstWebRTC.WebRTCRTPTransceiver): RTCRtpTransceiver;
|
|
109
127
|
_handleNegotiationNeeded(): void;
|
|
128
|
+
/** @internal — one queued negotiationneeded task per mutation burst. */
|
|
129
|
+
_negotiationNeededQueued: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* @internal — the JS half of W3C § 4.7.3 "update the negotiation-needed
|
|
132
|
+
* flag", called by the mutating entry points (addTransceiver, addTrack,
|
|
133
|
+
* createDataChannel, restartIce). webrtcbin emits on-negotiation-needed
|
|
134
|
+
* for the INITIAL need but — measured on GStreamer 1.28 — does NOT
|
|
135
|
+
* re-emit when a transceiver or data channel is added after a completed
|
|
136
|
+
* offer/answer, so once `_hasNegotiated` is set the renegotiation event
|
|
137
|
+
* is queued here instead. The `_negotiationNeededQueued` dedupe mirrors
|
|
138
|
+
* the spec's [[NegotiationNeeded]] flag chain (one queued task per
|
|
139
|
+
* burst); the stable-state re-check on dispatch mirrors § 4.7.3 step
|
|
140
|
+
* "if connection's signaling state is not 'stable', abort".
|
|
141
|
+
*/
|
|
142
|
+
_updateNegotiationNeeded(): void;
|
|
110
143
|
private _handleIceCandidate;
|
|
111
144
|
private _handleNewTransceiver;
|
|
112
145
|
private _handlePadAdded;
|
|
@@ -70,10 +70,11 @@ export declare class RTCRtpSender {
|
|
|
70
70
|
private _dtmf;
|
|
71
71
|
/** @internal — the kind of media this sender handles */
|
|
72
72
|
_kind: 'audio' | 'video' | null;
|
|
73
|
-
/** @internal — back-reference for DTMF stopped/direction checks */
|
|
73
|
+
/** @internal — back-reference for DTMF stopped/direction checks + m-section (mid) lookup */
|
|
74
74
|
_transceiver: {
|
|
75
75
|
stopped: boolean;
|
|
76
76
|
currentDirection: string | null;
|
|
77
|
+
mid: string | null;
|
|
77
78
|
} | null;
|
|
78
79
|
/** @internal — callback to notify RTCPeerConnection when pipeline changes (cross-pipeline fix) */
|
|
79
80
|
_onPipelineChanged: ((newPipeline: GstNs.Pipeline) => void) | null;
|
|
@@ -91,6 +92,15 @@ export declare class RTCRtpSender {
|
|
|
91
92
|
/** @internal — tear down the encoder chain on close/removeTrack */
|
|
92
93
|
_teardownPipeline(): void;
|
|
93
94
|
getParameters(): RTCRtpSendParameters;
|
|
95
|
+
/**
|
|
96
|
+
* Negotiated codecs/extensions/rtcp for this sender's m-section.
|
|
97
|
+
* W3C § 5.2 getParameters: "The codecs sequence is populated based on
|
|
98
|
+
* the codecs that have been negotiated for sending … in the priority
|
|
99
|
+
* order indicated by the remote description"; "rtcp.cname is set to the
|
|
100
|
+
* CNAME of the associated RTCPeerConnection". Before any negotiation
|
|
101
|
+
* completed the codec list is empty (there is no negotiated set yet).
|
|
102
|
+
*/
|
|
103
|
+
private _negotiatedParams;
|
|
94
104
|
setParameters(params: RTCRtpSendParameters): Promise<void>;
|
|
95
105
|
replaceTrack(track: MediaStreamTrack | null): Promise<void>;
|
|
96
106
|
getStats(): Promise<RTCStatsReport>;
|
|
@@ -14,6 +14,14 @@ export declare class RTCSctpTransport extends EventTarget {
|
|
|
14
14
|
get maxChannels(): number | null;
|
|
15
15
|
get onstatechange(): EventHandler;
|
|
16
16
|
set onstatechange(v: EventHandler);
|
|
17
|
+
/**
|
|
18
|
+
* @internal — update the `maxMessageSize` ceiling, e.g. from a parsed SDP
|
|
19
|
+
* `a=max-message-size:N` attribute (RFC 8841 § 6.1). A value of `0` means
|
|
20
|
+
* the peer can handle messages of any size — `RTCDataChannel.send`'s
|
|
21
|
+
* enforcement skips the check entirely. Negative or non-finite values are
|
|
22
|
+
* rejected.
|
|
23
|
+
*/
|
|
24
|
+
_setMaxMessageSize(v: number): void;
|
|
17
25
|
/** @internal */
|
|
18
26
|
_setState(state: RTCSctpTransportState): void;
|
|
19
27
|
}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
import type { RTCRtpCapabilities } from './rtc-rtp-sender.js';
|
|
2
2
|
/** Shared implementation for RTCRtpSender.getCapabilities / RTCRtpReceiver.getCapabilities. */
|
|
3
3
|
export declare function getRtpCapabilities(kind: string): RTCRtpCapabilities | null;
|
|
4
|
+
export declare const OPUS_PAYLOAD_TYPE = 111;
|
|
5
|
+
export declare const VP8_PAYLOAD_TYPE = 96;
|
|
6
|
+
/**
|
|
7
|
+
* Full RTP caps for a kind-only (Path-B) `add-transceiver`. webrtcbin needs
|
|
8
|
+
* `encoding-name`/`clock-rate`/`payload` to build an m-section for the
|
|
9
|
+
* transceiver — `application/x-rtp,media=audio` alone yields an offer with
|
|
10
|
+
* NO m-line at all (measured on GStreamer 1.28: create-offer returned only
|
|
11
|
+
* the session-level `v=/o=/s=/t=` + `a=ice-options:trickle`). Mirrors the
|
|
12
|
+
* caps the Path-A encoder chain advertises via its capsfilter.
|
|
13
|
+
*/
|
|
14
|
+
export declare function defaultRtpCapsString(kind: 'audio' | 'video'): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface SdpCodecParams {
|
|
2
|
+
payloadType: number;
|
|
3
|
+
mimeType: string;
|
|
4
|
+
clockRate: number;
|
|
5
|
+
channels?: number;
|
|
6
|
+
sdpFmtpLine?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SdpHeaderExtensionParams {
|
|
9
|
+
uri: string;
|
|
10
|
+
id: number;
|
|
11
|
+
}
|
|
12
|
+
export interface SdpMediaSectionParams {
|
|
13
|
+
codecs: SdpCodecParams[];
|
|
14
|
+
headerExtensions: SdpHeaderExtensionParams[];
|
|
15
|
+
/** `a=rtcp-rsize` present (RFC 5506 reduced-size RTCP). */
|
|
16
|
+
reducedSize: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface SdpMediaSectionSelector {
|
|
19
|
+
/** Match by `a=mid:<mid>` (RFC 5888) — the most precise selector. */
|
|
20
|
+
mid?: string;
|
|
21
|
+
/** Fall back to the m-section at this index (JSEP m-line order). */
|
|
22
|
+
mlineIndex?: number;
|
|
23
|
+
/** Last resort: the first m-section of this media kind. */
|
|
24
|
+
kind?: 'audio' | 'video';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Extract the negotiated codec/extension/rtcp parameters for ONE m-section
|
|
28
|
+
* of an SDP document. Returns `null` when no section matches the selector
|
|
29
|
+
* (e.g. before any negotiation completed).
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseMediaSectionParams(sdp: string, selector: SdpMediaSectionSelector): SdpMediaSectionParams | null;
|
|
32
|
+
/**
|
|
33
|
+
* Rewrite every `a=ice-ufrag:` / `a=ice-pwd:` line of an SDP with freshly
|
|
34
|
+
* generated credentials — the JSEP ICE-restart primitive (RFC 9429 § 3.5.1:
|
|
35
|
+
* "an ICE restart is indicated by generating new ICE ufrag and pwd in the
|
|
36
|
+
* offer"; W3C WebRTC § 4.4.3.2 restartIce). Distinct old values map to
|
|
37
|
+
* distinct new values, and a value repeated across m-sections
|
|
38
|
+
* (BUNDLE-shared credentials) keeps sharing ONE new value, preserving the
|
|
39
|
+
* offer's credential topology.
|
|
40
|
+
*
|
|
41
|
+
* Why rewriting instead of an engine option: GStreamer webrtcbin (≤ 1.28)
|
|
42
|
+
* ignores the `ice-restart` field of the create-offer options structure
|
|
43
|
+
* (measured: identical ufrag with and without it), but it DOES push the
|
|
44
|
+
* local credentials of a set-local-description SDP into its ICE agent —
|
|
45
|
+
* measured end-to-end: two webrtcbins complete ICE connectivity with a
|
|
46
|
+
* munged ufrag/pwd offer. The SDP is therefore the supported carrier for
|
|
47
|
+
* fresh local credentials.
|
|
48
|
+
*/
|
|
49
|
+
export declare function rewriteIceCredentials(sdp: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/webrtc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"description": "W3C WebRTC API for GJS using GStreamer webrtcbin as the peer-connection backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -61,10 +61,11 @@
|
|
|
61
61
|
"peer-connection"
|
|
62
62
|
],
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@gjsify/buffer": "^0.
|
|
65
|
-
"@gjsify/dom-events": "^0.
|
|
66
|
-
"@gjsify/dom-exception": "^0.
|
|
67
|
-
"@gjsify/
|
|
64
|
+
"@gjsify/buffer": "^0.47.0",
|
|
65
|
+
"@gjsify/dom-events": "^0.47.0",
|
|
66
|
+
"@gjsify/dom-exception": "^0.47.0",
|
|
67
|
+
"@gjsify/webcrypto": "^0.47.0",
|
|
68
|
+
"@gjsify/webrtc-native": "^0.47.0"
|
|
68
69
|
},
|
|
69
70
|
"devDependencies": {
|
|
70
71
|
"@girs/gjs": "4.6.0",
|
|
@@ -73,8 +74,8 @@
|
|
|
73
74
|
"@girs/gst-1.0": "4.6.0",
|
|
74
75
|
"@girs/gstsdp-1.0": "4.6.0",
|
|
75
76
|
"@girs/gstwebrtc-1.0": "4.6.0",
|
|
76
|
-
"@gjsify/cli": "^0.
|
|
77
|
-
"@gjsify/unit": "^0.
|
|
77
|
+
"@gjsify/cli": "^0.47.0",
|
|
78
|
+
"@gjsify/unit": "^0.47.0",
|
|
78
79
|
"@types/node": "^25.9.2",
|
|
79
80
|
"typescript": "^6.0.3"
|
|
80
81
|
},
|