webrtc-adapter
Advanced tools
Comparing version 3.2.0 to 3.3.0
@@ -84,2 +84,3 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
edgeShim.shimPeerConnection(); | ||
edgeShim.shimReplaceTrack(); | ||
break; | ||
@@ -95,2 +96,3 @@ case 'safari': | ||
safariShim.shimOnAddStream(); | ||
safariShim.shimGetUserMedia(); | ||
@@ -271,2 +273,31 @@ break; | ||
} | ||
} else { | ||
// migrate from non-spec RTCIceServer.url to RTCIceServer.urls | ||
var OrigPeerConnection = RTCPeerConnection; | ||
window.RTCPeerConnection = function(pcConfig, pcConstraints) { | ||
if (pcConfig && pcConfig.iceServers) { | ||
var newIceServers = []; | ||
for (var i = 0; i < pcConfig.iceServers.length; i++) { | ||
var server = pcConfig.iceServers[i]; | ||
if (!server.hasOwnProperty('urls') && | ||
server.hasOwnProperty('url')) { | ||
console.warn('RTCIceServer.url is deprecated! Use urls instead.'); | ||
server = JSON.parse(JSON.stringify(server)); | ||
server.urls = server.url; | ||
newIceServers.push(server); | ||
} else { | ||
newIceServers.push(pcConfig.iceServers[i]); | ||
} | ||
} | ||
pcConfig.iceServers = newIceServers; | ||
} | ||
return new OrigPeerConnection(pcConfig, pcConstraints); | ||
}; | ||
window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; | ||
// wrap static methods. Currently just generateCertificate. | ||
Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { | ||
get: function() { | ||
return OrigPeerConnection.generateCertificate; | ||
} | ||
}); | ||
} | ||
@@ -493,6 +524,6 @@ | ||
if (constraints && typeof constraints.video === 'object') { | ||
// Shim facingMode for mobile, where it defaults to "user". | ||
// Shim facingMode for mobile & surface pro. | ||
var face = constraints.video.facingMode; | ||
face = face && ((typeof face === 'object') ? face : {ideal: face}); | ||
var getSupportedFacingModeLies = browserDetails.version < 59; | ||
var getSupportedFacingModeLies = browserDetails.version < 61; | ||
@@ -505,4 +536,10 @@ if ((face && (face.exact === 'user' || face.exact === 'environment' || | ||
delete constraints.video.facingMode; | ||
var match; | ||
if (face.exact === 'environment' || face.ideal === 'environment') { | ||
// Look for "back" in label, or use last cam (typically back cam). | ||
match = 'back'; | ||
} else if (face.exact === 'user' || face.ideal === 'user') { | ||
match = 'front'; | ||
} | ||
if (match) { | ||
// Look for match in label. | ||
return navigator.mediaDevices.enumerateDevices() | ||
@@ -513,8 +550,8 @@ .then(function(devices) { | ||
}); | ||
var back = devices.find(function(d) { | ||
return d.label.toLowerCase().indexOf('back') !== -1; | ||
}) || (devices.length && devices[devices.length - 1]); | ||
if (back) { | ||
constraints.video.deviceId = face.exact ? {exact: back.deviceId} : | ||
{ideal: back.deviceId}; | ||
var dev = devices.find(function(d) { | ||
return d.label.toLowerCase().indexOf(match) !== -1; | ||
}); | ||
if (dev) { | ||
constraints.video.deviceId = face.exact ? {exact: dev.deviceId} : | ||
{ideal: dev.deviceId}; | ||
} | ||
@@ -844,2 +881,3 @@ constraints.video = constraintsToChrome_(constraints.video); | ||
name: { | ||
NotSupportedError: 'TypeError', | ||
SecurityError: 'NotAllowedError', | ||
@@ -1000,3 +1038,2 @@ PermissionDeniedError: 'NotAllowedError' | ||
// TODO: DrAlex, should be here, double check against LayoutTests | ||
// shimOnTrack: function() { }, | ||
@@ -1007,2 +1044,33 @@ // TODO: once the back-end for the mac port is done, add. | ||
shimOnAddStream: function() { | ||
if (typeof window === 'object' && window.RTCPeerConnection && | ||
!('onaddstream' in window.RTCPeerConnection.prototype)) { | ||
Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', { | ||
get: function() { | ||
return this._onaddstream; | ||
}, | ||
set: function(f) { | ||
if (this._onaddstream) { | ||
this.removeEventListener('addstream', this._onaddstream); | ||
this.removeEventListener('track', this._onaddstreampoly); | ||
} | ||
this.addEventListener('addstream', this._onaddstream = f); | ||
this.addEventListener('track', this._onaddstreampoly = function(e) { | ||
var stream = e.streams[0]; | ||
if (!this._streams) { | ||
this._streams = []; | ||
} | ||
if (this._streams.indexOf(stream) >= 0) { | ||
return; | ||
} | ||
this._streams.push(stream); | ||
var event = new Event('addstream'); | ||
event.stream = e.streams[0]; | ||
this.dispatchEvent(event); | ||
}.bind(this)); | ||
} | ||
}); | ||
} | ||
}, | ||
shimGetUserMedia: function() { | ||
@@ -1025,5 +1093,5 @@ if (!navigator.getUserMedia) { | ||
module.exports = { | ||
shimOnAddStream: safariShim.shimOnAddStream, | ||
shimGetUserMedia: safariShim.shimGetUserMedia | ||
// TODO | ||
// shimOnTrack: safariShim.shimOnTrack, | ||
// shimPeerConnection: safariShim.shimPeerConnection | ||
@@ -1030,0 +1098,0 @@ }; |
@@ -84,2 +84,3 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.adapter = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
edgeShim.shimPeerConnection(); | ||
edgeShim.shimReplaceTrack(); | ||
break; | ||
@@ -95,2 +96,3 @@ case 'safari': | ||
safariShim.shimOnAddStream(); | ||
safariShim.shimGetUserMedia(); | ||
@@ -271,2 +273,31 @@ break; | ||
} | ||
} else { | ||
// migrate from non-spec RTCIceServer.url to RTCIceServer.urls | ||
var OrigPeerConnection = RTCPeerConnection; | ||
window.RTCPeerConnection = function(pcConfig, pcConstraints) { | ||
if (pcConfig && pcConfig.iceServers) { | ||
var newIceServers = []; | ||
for (var i = 0; i < pcConfig.iceServers.length; i++) { | ||
var server = pcConfig.iceServers[i]; | ||
if (!server.hasOwnProperty('urls') && | ||
server.hasOwnProperty('url')) { | ||
console.warn('RTCIceServer.url is deprecated! Use urls instead.'); | ||
server = JSON.parse(JSON.stringify(server)); | ||
server.urls = server.url; | ||
newIceServers.push(server); | ||
} else { | ||
newIceServers.push(pcConfig.iceServers[i]); | ||
} | ||
} | ||
pcConfig.iceServers = newIceServers; | ||
} | ||
return new OrigPeerConnection(pcConfig, pcConstraints); | ||
}; | ||
window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; | ||
// wrap static methods. Currently just generateCertificate. | ||
Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { | ||
get: function() { | ||
return OrigPeerConnection.generateCertificate; | ||
} | ||
}); | ||
} | ||
@@ -493,6 +524,6 @@ | ||
if (constraints && typeof constraints.video === 'object') { | ||
// Shim facingMode for mobile, where it defaults to "user". | ||
// Shim facingMode for mobile & surface pro. | ||
var face = constraints.video.facingMode; | ||
face = face && ((typeof face === 'object') ? face : {ideal: face}); | ||
var getSupportedFacingModeLies = browserDetails.version < 59; | ||
var getSupportedFacingModeLies = browserDetails.version < 61; | ||
@@ -505,4 +536,10 @@ if ((face && (face.exact === 'user' || face.exact === 'environment' || | ||
delete constraints.video.facingMode; | ||
var match; | ||
if (face.exact === 'environment' || face.ideal === 'environment') { | ||
// Look for "back" in label, or use last cam (typically back cam). | ||
match = 'back'; | ||
} else if (face.exact === 'user' || face.ideal === 'user') { | ||
match = 'front'; | ||
} | ||
if (match) { | ||
// Look for match in label. | ||
return navigator.mediaDevices.enumerateDevices() | ||
@@ -513,8 +550,8 @@ .then(function(devices) { | ||
}); | ||
var back = devices.find(function(d) { | ||
return d.label.toLowerCase().indexOf('back') !== -1; | ||
}) || (devices.length && devices[devices.length - 1]); | ||
if (back) { | ||
constraints.video.deviceId = face.exact ? {exact: back.deviceId} : | ||
{ideal: back.deviceId}; | ||
var dev = devices.find(function(d) { | ||
return d.label.toLowerCase().indexOf(match) !== -1; | ||
}); | ||
if (dev) { | ||
constraints.video.deviceId = face.exact ? {exact: dev.deviceId} : | ||
{ideal: dev.deviceId}; | ||
} | ||
@@ -844,2 +881,3 @@ constraints.video = constraintsToChrome_(constraints.video); | ||
name: { | ||
NotSupportedError: 'TypeError', | ||
SecurityError: 'NotAllowedError', | ||
@@ -1000,3 +1038,2 @@ PermissionDeniedError: 'NotAllowedError' | ||
// TODO: DrAlex, should be here, double check against LayoutTests | ||
// shimOnTrack: function() { }, | ||
@@ -1007,2 +1044,33 @@ // TODO: once the back-end for the mac port is done, add. | ||
shimOnAddStream: function() { | ||
if (typeof window === 'object' && window.RTCPeerConnection && | ||
!('onaddstream' in window.RTCPeerConnection.prototype)) { | ||
Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', { | ||
get: function() { | ||
return this._onaddstream; | ||
}, | ||
set: function(f) { | ||
if (this._onaddstream) { | ||
this.removeEventListener('addstream', this._onaddstream); | ||
this.removeEventListener('track', this._onaddstreampoly); | ||
} | ||
this.addEventListener('addstream', this._onaddstream = f); | ||
this.addEventListener('track', this._onaddstreampoly = function(e) { | ||
var stream = e.streams[0]; | ||
if (!this._streams) { | ||
this._streams = []; | ||
} | ||
if (this._streams.indexOf(stream) >= 0) { | ||
return; | ||
} | ||
this._streams.push(stream); | ||
var event = new Event('addstream'); | ||
event.stream = e.streams[0]; | ||
this.dispatchEvent(event); | ||
}.bind(this)); | ||
} | ||
}); | ||
} | ||
}, | ||
shimGetUserMedia: function() { | ||
@@ -1025,5 +1093,5 @@ if (!navigator.getUserMedia) { | ||
module.exports = { | ||
shimOnAddStream: safariShim.shimOnAddStream, | ||
shimGetUserMedia: safariShim.shimGetUserMedia | ||
// TODO | ||
// shimOnTrack: safariShim.shimOnTrack, | ||
// shimPeerConnection: safariShim.shimPeerConnection | ||
@@ -1030,0 +1098,0 @@ }; |
{ | ||
"name": "webrtc-adapter", | ||
"version": "3.2.0", | ||
"version": "3.3.0", | ||
"description": "A shim to insulate apps from WebRTC spec changes and browser prefix differences", | ||
@@ -22,3 +22,3 @@ "license": "BSD-3-Clause", | ||
"dependencies": { | ||
"sdp": "^1.3.0" | ||
"sdp": "^1.4.0" | ||
}, | ||
@@ -25,0 +25,0 @@ "engines": { |
@@ -81,2 +81,3 @@ /* | ||
edgeShim.shimPeerConnection(); | ||
edgeShim.shimReplaceTrack(); | ||
break; | ||
@@ -92,2 +93,3 @@ case 'safari': | ||
safariShim.shimOnAddStream(); | ||
safariShim.shimGetUserMedia(); | ||
@@ -94,0 +96,0 @@ break; |
@@ -168,2 +168,31 @@ | ||
} | ||
} else { | ||
// migrate from non-spec RTCIceServer.url to RTCIceServer.urls | ||
var OrigPeerConnection = RTCPeerConnection; | ||
window.RTCPeerConnection = function(pcConfig, pcConstraints) { | ||
if (pcConfig && pcConfig.iceServers) { | ||
var newIceServers = []; | ||
for (var i = 0; i < pcConfig.iceServers.length; i++) { | ||
var server = pcConfig.iceServers[i]; | ||
if (!server.hasOwnProperty('urls') && | ||
server.hasOwnProperty('url')) { | ||
console.warn('RTCIceServer.url is deprecated! Use urls instead.'); | ||
server = JSON.parse(JSON.stringify(server)); | ||
server.urls = server.url; | ||
newIceServers.push(server); | ||
} else { | ||
newIceServers.push(pcConfig.iceServers[i]); | ||
} | ||
} | ||
pcConfig.iceServers = newIceServers; | ||
} | ||
return new OrigPeerConnection(pcConfig, pcConstraints); | ||
}; | ||
window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; | ||
// wrap static methods. Currently just generateCertificate. | ||
Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { | ||
get: function() { | ||
return OrigPeerConnection.generateCertificate; | ||
} | ||
}); | ||
} | ||
@@ -170,0 +199,0 @@ |
@@ -72,6 +72,6 @@ /* | ||
if (constraints && typeof constraints.video === 'object') { | ||
// Shim facingMode for mobile, where it defaults to "user". | ||
// Shim facingMode for mobile & surface pro. | ||
var face = constraints.video.facingMode; | ||
face = face && ((typeof face === 'object') ? face : {ideal: face}); | ||
var getSupportedFacingModeLies = browserDetails.version < 59; | ||
var getSupportedFacingModeLies = browserDetails.version < 61; | ||
@@ -84,4 +84,10 @@ if ((face && (face.exact === 'user' || face.exact === 'environment' || | ||
delete constraints.video.facingMode; | ||
var match; | ||
if (face.exact === 'environment' || face.ideal === 'environment') { | ||
// Look for "back" in label, or use last cam (typically back cam). | ||
match = 'back'; | ||
} else if (face.exact === 'user' || face.ideal === 'user') { | ||
match = 'front'; | ||
} | ||
if (match) { | ||
// Look for match in label. | ||
return navigator.mediaDevices.enumerateDevices() | ||
@@ -92,8 +98,8 @@ .then(function(devices) { | ||
}); | ||
var back = devices.find(function(d) { | ||
return d.label.toLowerCase().indexOf('back') !== -1; | ||
}) || (devices.length && devices[devices.length - 1]); | ||
if (back) { | ||
constraints.video.deviceId = face.exact ? {exact: back.deviceId} : | ||
{ideal: back.deviceId}; | ||
var dev = devices.find(function(d) { | ||
return d.label.toLowerCase().indexOf(match) !== -1; | ||
}); | ||
if (dev) { | ||
constraints.video.deviceId = face.exact ? {exact: dev.deviceId} : | ||
{ideal: dev.deviceId}; | ||
} | ||
@@ -100,0 +106,0 @@ constraints.video = constraintsToChrome_(constraints.video); |
@@ -46,2 +46,5 @@ /* | ||
var urls = server.urls || server.url; | ||
if (server.url && !server.urls) { | ||
console.warn('RTCIceServer.url is deprecated! Use urls instead.'); | ||
} | ||
var isString = typeof urls === 'string'; | ||
@@ -126,2 +129,3 @@ if (isString) { | ||
this.ondatachannel = null; | ||
this.canTrickleIceCandidates = null; | ||
@@ -169,3 +173,3 @@ this.localStreams = []; | ||
} | ||
this._config = config; | ||
this._config = config || {}; | ||
@@ -454,2 +458,25 @@ // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ... | ||
// Destroy ICE gatherer, ICE transport and DTLS transport. | ||
// Without triggering the callbacks. | ||
window.RTCPeerConnection.prototype._disposeIceAndDtlsTransports = | ||
function(sdpMLineIndex) { | ||
var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer; | ||
if (iceGatherer) { | ||
delete iceGatherer.onlocalcandidate; | ||
delete this.transceivers[sdpMLineIndex].iceGatherer; | ||
} | ||
var iceTransport = this.transceivers[sdpMLineIndex].iceTransport; | ||
if (iceTransport) { | ||
delete iceTransport.onicestatechange; | ||
delete this.transceivers[sdpMLineIndex].iceTransport; | ||
} | ||
var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport; | ||
if (dtlsTransport) { | ||
delete dtlsTransport.ondtlssttatechange; | ||
delete dtlsTransport.onerror; | ||
delete this.transceivers[sdpMLineIndex].dtlsTransport; | ||
} | ||
}; | ||
// Start the RTP Sender and Receiver for a transceiver. | ||
@@ -463,3 +490,4 @@ window.RTCPeerConnection.prototype._transceive = function(transceiver, | ||
params.rtcp = { | ||
cname: SDPUtils.localCName | ||
cname: SDPUtils.localCName, | ||
compound: transceiver.rtcpParameters.compound | ||
}; | ||
@@ -482,3 +510,4 @@ if (transceiver.recvEncodingParameters.length) { | ||
params.rtcp = { | ||
cname: transceiver.cname | ||
cname: transceiver.rtcpParameters.cname, | ||
compound: transceiver.rtcpParameters.compound | ||
}; | ||
@@ -606,3 +635,3 @@ if (transceiver.sendEncodingParameters.length) { | ||
var self = this; | ||
var stream = new MediaStream(); | ||
var streams = {}; | ||
var receiverList = []; | ||
@@ -613,4 +642,13 @@ var sections = SDPUtils.splitSections(description.sdp); | ||
'a=ice-lite').length > 0; | ||
this.usingBundle = SDPUtils.matchPrefix(sessionpart, | ||
var usingBundle = SDPUtils.matchPrefix(sessionpart, | ||
'a=group:BUNDLE ').length > 0; | ||
var iceOptions = SDPUtils.matchPrefix(sessionpart, | ||
'a=ice-options:')[0]; | ||
if (iceOptions) { | ||
this.canTrickleIceCandidates = iceOptions.substr(14).split(' ') | ||
.indexOf('trickle') >= 0; | ||
} else { | ||
this.canTrickleIceCandidates = false; | ||
} | ||
sections.forEach(function(mediaSection, sdpMLineIndex) { | ||
@@ -622,2 +660,3 @@ var lines = SDPUtils.splitLines(mediaSection); | ||
var direction = SDPUtils.getDirection(mediaSection, sessionpart); | ||
var remoteMsid = SDPUtils.parseMsid(mediaSection); | ||
@@ -665,15 +704,3 @@ var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:'); | ||
var cname; | ||
// Gets the first SSRC. Note that with RTX there might be multiple | ||
// SSRCs. | ||
var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') | ||
.map(function(line) { | ||
return SDPUtils.parseSsrcMedia(line); | ||
}) | ||
.filter(function(obj) { | ||
return obj.attribute === 'cname'; | ||
})[0]; | ||
if (remoteSsrc) { | ||
cname = remoteSsrc.value; | ||
} | ||
var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection); | ||
@@ -690,3 +717,3 @@ var isComplete = SDPUtils.matchPrefix(mediaSection, | ||
if (description.type === 'offer' && !rejected) { | ||
var transports = self.usingBundle && sdpMLineIndex > 0 ? { | ||
var transports = usingBundle && sdpMLineIndex > 0 ? { | ||
iceGatherer: self.transceivers[0].iceGatherer, | ||
@@ -697,3 +724,3 @@ iceTransport: self.transceivers[0].iceTransport, | ||
if (isComplete && (!self.usingBundle || sdpMLineIndex === 0)) { | ||
if (isComplete && (!usingBundle || sdpMLineIndex === 0)) { | ||
transports.iceTransport.setRemoteCandidates(cands); | ||
@@ -722,6 +749,27 @@ } | ||
track = rtpReceiver.track; | ||
receiverList.push([track, rtpReceiver]); | ||
// FIXME: not correct when there are multiple streams but that | ||
// is not currently supported in this shim. | ||
stream.addTrack(track); | ||
// FIXME: does not work with Plan B. | ||
if (remoteMsid) { | ||
if (!streams[remoteMsid.stream]) { | ||
streams[remoteMsid.stream] = new MediaStream(); | ||
Object.defineProperty(streams[remoteMsid.stream], 'id', { | ||
get: function() { | ||
return remoteMsid.stream; | ||
} | ||
}); | ||
} | ||
Object.defineProperty(track, 'id', { | ||
get: function() { | ||
return remoteMsid.track; | ||
} | ||
}); | ||
streams[remoteMsid.stream].addTrack(track); | ||
receiverList.push([track, rtpReceiver, | ||
streams[remoteMsid.stream]]); | ||
} else { | ||
if (!streams.default) { | ||
streams.default = new MediaStream(); | ||
} | ||
streams.default.addTrack(track); | ||
receiverList.push([track, rtpReceiver, streams.default]); | ||
} | ||
} | ||
@@ -760,3 +808,3 @@ | ||
mid: mid, | ||
cname: cname, | ||
rtcpParameters: rtcpParameters, | ||
sendEncodingParameters: sendEncodingParameters, | ||
@@ -771,2 +819,11 @@ recvEncodingParameters: recvEncodingParameters | ||
} else if (description.type === 'answer' && !rejected) { | ||
if (usingBundle && sdpMLineIndex > 0) { | ||
self._disposeIceAndDtlsTransports(sdpMLineIndex); | ||
self.transceivers[sdpMLineIndex].iceGatherer = | ||
self.transceivers[0].iceGatherer; | ||
self.transceivers[sdpMLineIndex].iceTransport = | ||
self.transceivers[0].iceTransport; | ||
self.transceivers[sdpMLineIndex].dtlsTransport = | ||
self.transceivers[0].dtlsTransport; | ||
} | ||
transceiver = self.transceivers[sdpMLineIndex]; | ||
@@ -785,3 +842,3 @@ iceGatherer = transceiver.iceGatherer; | ||
remoteCapabilities; | ||
self.transceivers[sdpMLineIndex].cname = cname; | ||
self.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters; | ||
@@ -791,3 +848,3 @@ if ((isIceLite || isComplete) && cands.length) { | ||
} | ||
if (!self.usingBundle || sdpMLineIndex === 0) { | ||
if (!usingBundle || sdpMLineIndex === 0) { | ||
iceTransport.start(iceGatherer, remoteIceParameters, | ||
@@ -806,3 +863,13 @@ 'controlling'); | ||
receiverList.push([track, rtpReceiver]); | ||
stream.addTrack(track); | ||
if (remoteMsid) { | ||
if (!streams[remoteMsid.stream]) { | ||
streams[remoteMsid.stream] = new MediaStream(); | ||
} | ||
streams[remoteMsid.stream].addTrack(track); | ||
} else { | ||
if (!streams.default) { | ||
streams.default = new MediaStream(); | ||
} | ||
streams.default.addTrack(track); | ||
} | ||
} else { | ||
@@ -814,2 +881,3 @@ // FIXME: actually the receiver should be created later. | ||
}); | ||
this.usingBundle = usingBundle; | ||
@@ -831,5 +899,6 @@ this.remoteDescription = { | ||
} | ||
if (stream.getTracks().length) { | ||
self.remoteStreams.push(stream); | ||
window.setTimeout(function() { | ||
Object.keys(streams).forEach(function(sid) { | ||
var stream = streams[sid]; | ||
if (stream.getTracks().length) { | ||
self.remoteStreams.push(stream); | ||
var event = new Event('addstream'); | ||
@@ -847,2 +916,5 @@ event.stream = stream; | ||
var receiver = item[1]; | ||
if (stream.id !== item[2].id) { | ||
return; | ||
} | ||
var trackEvent = new Event('track'); | ||
@@ -859,4 +931,4 @@ trackEvent.track = track; | ||
}); | ||
}, 0); | ||
} | ||
} | ||
}); | ||
if (arguments.length > 1 && typeof arguments[1] === 'function') { | ||
@@ -974,4 +1046,8 @@ window.setTimeout(arguments[1], 0); | ||
if (this.localStreams.length) { | ||
numAudioTracks = this.localStreams[0].getAudioTracks().length; | ||
numVideoTracks = this.localStreams[0].getVideoTracks().length; | ||
numAudioTracks = this.localStreams.reduce(function(numTracks, stream) { | ||
return numTracks + stream.getAudioTracks().length; | ||
}, 0); | ||
numVideoTracks = this.localStreams.reduce(function(numTracks, stream) { | ||
return numTracks + stream.getVideoTracks().length; | ||
}, 0); | ||
} | ||
@@ -992,8 +1068,10 @@ // Determine number of audio and video tracks we need to send/recv. | ||
} | ||
if (this.localStreams.length) { | ||
// Push local streams. | ||
this.localStreams[0].getTracks().forEach(function(track) { | ||
// Push local streams. | ||
this.localStreams.forEach(function(localStream) { | ||
localStream.getTracks().forEach(function(track) { | ||
tracks.push({ | ||
kind: track.kind, | ||
track: track, | ||
stream: localStream, | ||
wantReceive: track.kind === 'audio' ? | ||
@@ -1008,3 +1086,4 @@ numAudioTracks > 0 : numVideoTracks > 0 | ||
}); | ||
} | ||
}); | ||
// Create M-lines for recvonly streams. | ||
@@ -1098,3 +1177,5 @@ while (numAudioTracks > 0 || numVideoTracks > 0) { | ||
}); | ||
if (this.usingBundle) { | ||
// always offer BUNDLE and dispose on return if not supported. | ||
if (this._config.bundlePolicy !== 'max-compat') { | ||
sdp += 'a=group:BUNDLE ' + transceivers.map(function(t) { | ||
@@ -1104,6 +1185,9 @@ return t.mid; | ||
} | ||
sdp += 'a=ice-options:trickle\r\n'; | ||
tracks.forEach(function(mline, sdpMLineIndex) { | ||
var transceiver = transceivers[sdpMLineIndex]; | ||
sdp += SDPUtils.writeMediaSection(transceiver, | ||
transceiver.localCapabilities, 'offer', self.localStreams[0]); | ||
transceiver.localCapabilities, 'offer', mline.stream); | ||
sdp += 'a=rtcp-rsize\r\n'; | ||
}); | ||
@@ -1143,4 +1227,15 @@ | ||
var hasRtx = commonCapabilities.codecs.filter(function(c) { | ||
return c.name.toLowerCase() === 'rtx'; | ||
}).length; | ||
if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) { | ||
delete transceiver.sendEncodingParameters[0].rtx; | ||
} | ||
sdp += SDPUtils.writeMediaSection(transceiver, commonCapabilities, | ||
'answer', self.localStreams[0]); | ||
if (transceiver.rtcpParameters && | ||
transceiver.rtcpParameters.reducedSize) { | ||
sdp += 'a=rtcp-rsize\r\n'; | ||
} | ||
}); | ||
@@ -1241,2 +1336,8 @@ | ||
}; | ||
}, | ||
shimReplaceTrack: function() { | ||
// ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614 | ||
if (window.RTCRtpSender && !('replaceTrack' in RTCRtpSender.prototype)) { | ||
RTCRtpSender.prototype.replaceTrack = RTCRtpSender.prototype.setTrack; | ||
} | ||
} | ||
@@ -1248,3 +1349,4 @@ }; | ||
shimPeerConnection: edgeShim.shimPeerConnection, | ||
shimGetUserMedia: require('./getusermedia') | ||
shimGetUserMedia: require('./getusermedia'), | ||
shimReplaceTrack: edgeShim.shimReplaceTrack | ||
}; |
@@ -19,2 +19,3 @@ /* | ||
name: { | ||
NotSupportedError: 'TypeError', | ||
SecurityError: 'NotAllowedError', | ||
@@ -21,0 +22,0 @@ PermissionDeniedError: 'NotAllowedError' |
@@ -11,3 +11,2 @@ /* | ||
// TODO: DrAlex, should be here, double check against LayoutTests | ||
// shimOnTrack: function() { }, | ||
@@ -18,2 +17,33 @@ // TODO: once the back-end for the mac port is done, add. | ||
shimOnAddStream: function() { | ||
if (typeof window === 'object' && window.RTCPeerConnection && | ||
!('onaddstream' in window.RTCPeerConnection.prototype)) { | ||
Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', { | ||
get: function() { | ||
return this._onaddstream; | ||
}, | ||
set: function(f) { | ||
if (this._onaddstream) { | ||
this.removeEventListener('addstream', this._onaddstream); | ||
this.removeEventListener('track', this._onaddstreampoly); | ||
} | ||
this.addEventListener('addstream', this._onaddstream = f); | ||
this.addEventListener('track', this._onaddstreampoly = function(e) { | ||
var stream = e.streams[0]; | ||
if (!this._streams) { | ||
this._streams = []; | ||
} | ||
if (this._streams.indexOf(stream) >= 0) { | ||
return; | ||
} | ||
this._streams.push(stream); | ||
var event = new Event('addstream'); | ||
event.stream = e.streams[0]; | ||
this.dispatchEvent(event); | ||
}.bind(this)); | ||
} | ||
}); | ||
} | ||
}, | ||
shimGetUserMedia: function() { | ||
@@ -36,6 +66,6 @@ if (!navigator.getUserMedia) { | ||
module.exports = { | ||
shimOnAddStream: safariShim.shimOnAddStream, | ||
shimGetUserMedia: safariShim.shimGetUserMedia | ||
// TODO | ||
// shimOnTrack: safariShim.shimOnTrack, | ||
// shimPeerConnection: safariShim.shimPeerConnection | ||
}; |
@@ -26,10 +26,3 @@ /* | ||
}); | ||
it('does not override window.RTCPeerConnection if it exists', () => { | ||
const pc = function() {}; | ||
global.window.RTCPeerConnection = pc; | ||
shim.shimPeerConnection(); | ||
expect(window.RTCPeerConnection).to.equal(pc); | ||
}); | ||
}); | ||
}); |
@@ -398,3 +398,3 @@ /* | ||
describe.skip('when called with an offer containing multiple streams ' + | ||
describe('when called with an offer containing multiple streams ' + | ||
'/ tracks', () => { | ||
@@ -453,2 +453,27 @@ const sdp = 'v=0\r\no=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + | ||
// probably easiest done using a sinon.stub | ||
// | ||
describe('sets the canTrickleIceCandidates property', () => { | ||
it('to true when called with an offer that contains ' + | ||
'a=ice-options:trickle', (done) => { | ||
const sdp = 'v=0\r\no=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + | ||
's=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n' + | ||
'a=ice-options:trickle\r\n'; | ||
pc.setRemoteDescription({type: 'offer', sdp: sdp}) | ||
.then(() => { | ||
expect(pc.canTrickleIceCandidates).to.equal(true); | ||
done(); | ||
}); | ||
}); | ||
it('to false when called with an offer that does not contain ' + | ||
'a=ice-options:trickle', (done) => { | ||
const sdp = 'v=0\r\no=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + | ||
's=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n'; | ||
pc.setRemoteDescription({type: 'offer', sdp: sdp}) | ||
.then(() => { | ||
expect(pc.canTrickleIceCandidates).to.equal(false); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -646,3 +671,3 @@ | ||
describe.skip('with an audio track and two video tracks', () => { | ||
describe('with an audio track and two video tracks', () => { | ||
it('the generated SDP should contain an audio and ' + | ||
@@ -893,3 +918,96 @@ 'video m-line', (done) => { | ||
}); | ||
describe('after a video offer without RTX', () => { | ||
const sdp = 'v=0\r\no=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + | ||
's=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n' + | ||
'm=video 9 UDP/TLS/RTP/SAVPF 102\r\n' + | ||
'c=IN IP4 0.0.0.0\r\n' + | ||
'a=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:foo\r\na=ice-pwd:bar\r\n' + | ||
'a=fingerprint:sha-256 so:me:co:lo:ns\r\n' + | ||
'a=setup:actpass\r\n' + | ||
'a=mid:video1\r\n' + | ||
'a=sendrecv\r\na=rtcp-mux\r\n' + | ||
'a=rtcp-rsize\r\n' + | ||
'a=rtpmap:102 vp8/90000\r\n' + | ||
'a=ssrc:1001 msid:stream1 track1\r\n' + | ||
'a=ssrc:1001 cname:some\r\n'; | ||
it('there is no ssrc-group in the answer', (done) => { | ||
const videoTrack = new MediaStreamTrack(); | ||
videoTrack.kind = 'video'; | ||
const stream = new MediaStream([videoTrack]); | ||
pc.addStream(stream); | ||
pc.setRemoteDescription({type: 'offer', sdp: sdp}) | ||
.then(() => { | ||
return pc.createAnswer(); | ||
}) | ||
.then((answer) => { | ||
expect(answer.sdp).not.to.contain('a=ssrc-group:FID '); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('rtcp-rsize is', () => { | ||
const sdp = 'v=0\r\no=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + | ||
's=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n' + | ||
'm=audio 9 UDP/TLS/RTP/SAVPF 98\r\n' + | ||
'c=IN IP4 0.0.0.0\r\n' + | ||
'a=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:foo\r\na=ice-pwd:bar\r\n' + | ||
'a=fingerprint:sha-256 so:me:co:lo:ns\r\n' + | ||
'a=setup:actpass\r\n' + | ||
'a=mid:audio1\r\n' + | ||
'a=sendrecv\r\na=rtcp-mux\r\n' + | ||
'a=rtcp-rsize\r\n' + | ||
'a=rtpmap:98 opus/48000\r\n' + | ||
'a=ssrc:1001 msid:stream1 track1\r\n' + | ||
'a=ssrc:1001 cname:some\r\n'; | ||
it('set if the offer contained rtcp-rsize', (done) => { | ||
pc.setRemoteDescription({type: 'offer', sdp: sdp}) | ||
.then(() => { | ||
return pc.createAnswer(); | ||
}) | ||
.then((answer) => { | ||
expect(answer.sdp).to.contain('a=rtcp-rsize\r\n'); | ||
done(); | ||
}); | ||
}); | ||
it('not set if the offer did not contain rtcp-rsize', (done) => { | ||
pc.setRemoteDescription({type: 'offer', | ||
sdp: sdp.replace('a=rtcp-rsize\r\n', '')}) | ||
.then(() => { | ||
return pc.createAnswer(); | ||
}) | ||
.then((answer) => { | ||
expect(answer.sdp).not.to.contain('a=rtcp-rsize\r\n'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('bundlePolicy', () => { | ||
it('creates an offer with a=group:BUNDLE by default', (done) => { | ||
const pc = new RTCPeerConnection(); | ||
pc.createOffer({offerToReceiveAudio: 1}) | ||
.then((offer) => { | ||
expect(offer.sdp).to.contain('a=group:BUNDLE'); | ||
done(); | ||
}); | ||
}); | ||
it('max-compat creates an offer without a=group:BUNDLE', (done) => { | ||
const pc = new RTCPeerConnection({bundlePolicy: 'max-compat'}); | ||
pc.createOffer({offerToReceiveAudio: 1}) | ||
.then((offer) => { | ||
expect(offer.sdp).not.to.contain('a=group:BUNDLE'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
551227
37
14278
Updatedsdp@^1.4.0