You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I want to send modified sdp to chrome. However it is not receiving that modified sdp which is changed in sdp_pattern.txt
v=0
o=mozilla...THIS_IS_SDPARTA-65.0 2266787997050267451 0 IN IP4 0.0.0.0
s=-
t=0 0
a=sendrecv
a=fingerprint:sha-256 79:3F:28:AD:AE:2A:B7:05:60:8D:53:CF:88:3B:88:32:9A:04:71:04:A3:B9:F3:08:D2:41:0C:38:95:41:21:F5
a=group:BUNDLE 0 1 2 // Specify the mids to bundle
a=ice-options:trickle
a=msid-semantic:WMS *
m=audio 63259 UDP/TLS/RTP/SAVPF 109 9 0 8 101 // For 1st audio track
c=IN IP4 192.168.0.12
a=candidate:0 1 UDP 2122252543 192.168.0.12 63259 typ host
... some candidates
a=candidate:1 2 TCP 2105524478 192.168.0.12 9 typ host tcptype active
a=sendrecv
a=end-of-candidates
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
... some extmap
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
a=fmtp:101 0-15
a=ice-pwd:foo
a=ice-ufrag:bar
a=mid:0 // Identifier of m-line. Thus each m-line has one mid.
a=msid:{aaaaa} {bbbbb} // Media Stream ID. There is msid in each m-line.
a=rtcp-mux
a=rtpmap:109 opus/48000/2
... some rtpmap
a=setup:actpass
a=ssrc:45563795 cname:{ccccc} // Except simulcast case, there is one ssrc in each m-line
m=audio 63259 UDP/TLS/RTP/SAVPF 109 9 0 8 101 // For 2nd audio track
c=IN IP4 192.168.0.12
a=sendrecv
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
... some extmap
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
a=fmtp:101 0-15
a=ice-pwd:foo
a=ice-ufrag:bar
a=mid:1 // Identifier of m-line. Thus each m-line has one mid.
a=msid:{ddddd} {eeeee} // Media Stream ID. There is msid in each m-line.
a=rtcp-mux
a=rtpmap:109 opus/48000/2
... some rtpmap
a=setup:actpass
a=ssrc:12345678 cname:{fffff} // Except simulcast case, there is one ssrc in each m-line
m=video 63259 UDP/TLS/RTP/SAVPF 120 121 126 97 // For video track
c=IN IP4 192.168.0.12
a=sendrecv
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
... some extmap
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
... some fmtp
a=ice-pwd:foo
a=ice-ufrag:bar
a=mid:2
a=msid:{ggggg} {hhhhh}
a=rtcp-fb:120 nack
... some rtcp-fb
a=rtcp-mux
a=rtpmap:120 VP8/90000
... some rtpmap
a=setup:actpass
a=ssrc:1242852923 cname:{iiiii}
webrtcpeer.js
var freeice = require('freeice');
var inherits = require('inherits');
var UAParser = require('ua-parser-js');
var uuid = require('uuid');
var hark = require('hark');
var EventEmitter = require('events').EventEmitter;
var recursive = require('merge').recursive.bind(undefined, true);
var sdpTranslator = require('sdp-translator');
try {
require('kurento-browser-extensions');
} catch (error) {
if (typeof getScreenConstraints === 'undefined') {
console.warn('screen sharing is not available');
getScreenConstraints = function getScreenConstraints(sendSource, callback) {
callback(new Error('This library is not enabled for screen sharing'));
};
}
}
var MEDIA_CONSTRAINTS = {
audio: true,
video: {
width: 640,
framerate: 15
}
};
var ua = window && window.navigator ? window.navigator.userAgent : '';
var parser = new UAParser(ua);
var browser = parser.getBrowser();
var usePlanB = false;
if (browser.name === 'Chrome' || browser.name === 'Chromium') {
console.log(browser.name + ': using SDP PlanB');
usePlanB = true;
}
function noop(error) {
if (error)
console.error(error);
}
function trackStop(track) {
track.stop && track.stop();
}
function streamStop(stream) {
stream.getTracks().forEach(trackStop);
}
var dumpSDP = function (description) {
if (typeof description === 'undefined' || description === null) {
return '';
}
return 'type: ' + description.type + '\r\n' + description.sdp;
};
function bufferizeCandidates(pc, onerror) {
var candidatesQueue = [];
pc.addEventListener('signalingstatechange', function () {
if (this.signalingState === 'stable') {
while (candidatesQueue.length) {
var entry = candidatesQueue.shift();
this.addIceCandidate(entry.candidate, entry.callback, entry.callback);
}
}
});
return function (candidate, callback) {
callback = callback || onerror;
switch (pc.signalingState) {
case 'closed':
callback(new Error('PeerConnection object is closed'));
break;
case 'stable':
if (pc.remoteDescription) {
pc.addIceCandidate(candidate, callback, callback);
break;
}
default:
candidatesQueue.push({
candidate: candidate,
callback: callback
});
}
};
}
function removeFIDFromOffer(sdp) {
var n = sdp.indexOf('a=ssrc-group:FID');
if (n > 0) {
return sdp.slice(0, n);
} else {
return sdp;
}
}
function getSimulcastInfo(videoStream) {
var videoTracks = videoStream.getVideoTracks();
if (!videoTracks.length) {
console.warn('No video tracks available in the video stream');
return '';
}
var lines = [
'a=x-google-flag:conference',
'a=ssrc-group:SIM 1 2 3',
'a=ssrc:1 cname:localVideo',
'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id,
'a=ssrc:1 mslabel:' + videoStream.id,
'a=ssrc:1 label:' + videoTracks[0].id,
'a=ssrc:2 cname:localVideo',
'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id,
'a=ssrc:2 mslabel:' + videoStream.id,
'a=ssrc:2 label:' + videoTracks[0].id,
'a=ssrc:3 cname:localVideo',
'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id,
'a=ssrc:3 mslabel:' + videoStream.id,
'a=ssrc:3 label:' + videoTracks[0].id
];
lines.push('');
return lines.join('\n');
}
function WebRtcPeer(mode, options, callback) {
if (!(this instanceof WebRtcPeer)) {
return new WebRtcPeer(mode, options, callback);
}
WebRtcPeer.super_.call(this);
if (options instanceof Function) {
callback = options;
options = undefined;
}
options = options || {};
callback = (callback || noop).bind(this);
var self = this;
var localVideo = options.localVideo;
var remoteVideo = options.remoteVideo;
var videoStream = options.videoStream;
var audioStream = options.audioStream;
var mediaConstraints = options.mediaConstraints;
var connectionConstraints = options.connectionConstraints;
var pc = options.peerConnection;
var sendSource = options.sendSource || 'webcam';
var dataChannelConfig = options.dataChannelConfig;
var useDataChannels = options.dataChannels || false;
var dataChannel;
var guid = uuid.v4();
var configuration = recursive({ iceServers: freeice() }, options.configuration);
var onicecandidate = options.onicecandidate;
if (onicecandidate)
this.on('icecandidate', onicecandidate);
var oncandidategatheringdone = options.oncandidategatheringdone;
if (oncandidategatheringdone) {
this.on('candidategatheringdone', oncandidategatheringdone);
}
var simulcast = options.simulcast;
var multistream = options.multistream;
var interop = new sdpTranslator.Interop();
var candidatesQueueOut = [];
var candidategatheringdone = false;
Object.defineProperties(this, {
'peerConnection': {
get: function () {
return pc;
}
},
'id': {
value: options.id || guid,
writable: false
},
'remoteVideo': {
get: function () {
return remoteVideo;
}
},
'localVideo': {
get: function () {
return localVideo;
}
},
'dataChannel': {
get: function () {
return dataChannel;
}
},
'currentFrame': {
get: function () {
if (!remoteVideo)
return;
if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA)
throw new Error('No video stream data available');
var canvas = document.createElement('canvas');
canvas.width = remoteVideo.videoWidth;
canvas.height = remoteVideo.videoHeight;
canvas.getContext('2d').drawImage(remoteVideo, 0, 0);
return canvas;
}
}
});
if (!pc) {
pc = new RTCPeerConnection ({ sdpSemantics : "unified-plan" });
if (useDataChannels && !dataChannel) {
var dcId = 'WebRtcPeer-' + self.id;
var dcOptions = undefined;
if (dataChannelConfig) {
dcId = dataChannelConfig.id || dcId;
dcOptions = dataChannelConfig.options;
}
dataChannel = pc.createDataChannel(dcId, dcOptions);
if (dataChannelConfig) {
dataChannel.onopen = dataChannelConfig.onopen;
dataChannel.onclose = dataChannelConfig.onclose;
dataChannel.onmessage = dataChannelConfig.onmessage;
dataChannel.onbufferedamountlow = dataChannelConfig.onbufferedamountlow;
dataChannel.onerror = dataChannelConfig.onerror || noop;
}
}
}
pc.addEventListener('icecandidate', function (event) {
var candidate = event.candidate;
if (EventEmitter.listenerCount(self, 'icecandidate') || EventEmitter.listenerCount(self, 'candidategatheringdone')) {
if (candidate) {
var cand;
if (multistream && usePlanB) {
cand = interop.candidateToUnifiedPlan(candidate);
} else {
cand = candidate;
}
self.emit('icecandidate', cand);
candidategatheringdone = false;
} else if (!candidategatheringdone) {
self.emit('candidategatheringdone');
candidategatheringdone = true;
}
} else if (!candidategatheringdone) {
candidatesQueueOut.push(candidate);
if (!candidate)
candidategatheringdone = true;
}
});
pc.onaddstream = options.onaddstream;
pc.onnegotiationneeded = options.onnegotiationneeded;
this.on('newListener', function (event, listener) {
if (event === 'icecandidate' || event === 'candidategatheringdone') {
while (candidatesQueueOut.length) {
var candidate = candidatesQueueOut.shift();
if (!candidate === (event === 'candidategatheringdone')) {
listener(candidate);
}
}
}
});
var addIceCandidate = bufferizeCandidates(pc);
this.addIceCandidate = function (iceCandidate, callback) {
var candidate;
if (multistream && usePlanB) {
candidate = interop.candidateToPlanB(iceCandidate);
} else {
candidate = new RTCIceCandidate(iceCandidate);
}
console.log('ICE candidate received');
callback = (callback || noop).bind(this);
addIceCandidate(candidate, callback);
};
this.generateOffer = function (callback) {
callback = callback.bind(this);
var offerAudio = true;
var offerVideo = true;
if (mediaConstraints) {
offerAudio = typeof mediaConstraints.audio === 'boolean' ? mediaConstraints.audio : true;
offerVideo = typeof mediaConstraints.video === 'boolean' ? mediaConstraints.video : true;
}
var browserDependantConstraints = browser.name === 'Firefox' && browser.version > 34 ? {
offerToReceiveAudio: mode !== 'sendonly' && offerAudio,
offerToReceiveVideo: mode !== 'sendonly' && offerVideo
} : {
mandatory: {
OfferToReceiveAudio: mode !== 'sendonly' && offerAudio,
OfferToReceiveVideo: mode !== 'sendonly' && offerVideo
},
optional: [{ DtlsSrtpKeyAgreement: true }]
};
var constraints = recursive(browserDependantConstraints, connectionConstraints);
console.log('constraints: ' + JSON.stringify(constraints));
pc.createOffer(constraints).then(function (offer) {
console.log('Created SDP offer');
offer = mangleSdpToAddSimulcast(offer);
return pc.setLocalDescription(offer);
}).then(function () {
var localDescription = pc.localDescription;
console.log('Local description set', localDescription.sdp);
if (multistream && usePlanB) {
localDescription = interop.toUnifiedPlan(localDescription);
console.log('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription));
}
callback(null, localDescription.sdp, self.processAnswer.bind(self));
}).catch(callback);
};
this.getLocalSessionDescriptor = function () {
return pc.localDescription;
};
this.getRemoteSessionDescriptor = function () {
return pc.remoteDescription;
};
function setRemoteVideo() {
if (remoteVideo) {
var stream = pc.getRemoteStreams()[0];
var url = stream;
remoteVideo.pause();
remoteVideo.srcObject = url;
remoteVideo.load();
console.log('Remote URL:', url);
}
}
this.showLocalVideo = function () {
localVideo.srcObject = videoStream;
localVideo.muted = true;
};
this.send = function (data) {
if (dataChannel && dataChannel.readyState === 'open') {
dataChannel.send(data);
} else {
console.warn('Trying to send data over a non-existing or closed data channel');
}
};
this.processAnswer = function (sdpAnswer, callback) {
callback = (callback || noop).bind(this);
var answer = new RTCSessionDescription({
type: 'answer',
sdp: sdpAnswer
});
if (multistream && usePlanB) {
var planBAnswer = interop.toPlanB(answer);
console.log('asnwer::planB', dumpSDP(planBAnswer));
answer = planBAnswer;
}
console.log('SDP answer received, setting remote description');
if (pc.signalingState === 'closed') {
return callback('PeerConnection is closed');
}
pc.setRemoteDescription(answer, function () {
setRemoteVideo();
callback();
}, callback);
};
this.processOffer = function (sdpOffer, callback) {
callback = callback.bind(this);
var offer = new RTCSessionDescription({
type: 'offer',
sdp: sdpOffer
});
if (multistream && usePlanB) {
var planBOffer = interop.toPlanB(offer);
console.log('offer::planB', dumpSDP(planBOffer));
offer = planBOffer;
}
console.log('SDP offer received, setting remote description');
if (pc.signalingState === 'closed') {
return callback('PeerConnection is closed');
}
pc.setRemoteDescription(offer).then(function () {
return setRemoteVideo();
}).then(function () {
return pc.createAnswer();
}).then(function (answer) {
answer = mangleSdpToAddSimulcast(answer);
console.log('Created SDP answer');
return pc.setLocalDescription(answer);
}).then(function () {
var localDescription = pc.localDescription;
if (multistream && usePlanB) {
localDescription = interop.toUnifiedPlan(localDescription);
console.log('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription));
}
console.log('Local description set', localDescription.sdp);
callback(null, localDescription.sdp);
}).catch(callback);
};
function mangleSdpToAddSimulcast(answer) {
if (simulcast) {
if (browser.name === 'Chrome' || browser.name === 'Chromium') {
console.log('Adding multicast info');
answer = new RTCSessionDescription({
'type': answer.type,
'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream)
});
} else {
console.warn('Simulcast is only available in Chrome browser.');
}
}
return answer;
}
function start() {
if (pc.signalingState === 'closed') {
callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
}
if (videoStream && localVideo) {
self.showLocalVideo();
}
if (videoStream) {
pc.addStream(videoStream);
}
if (audioStream) {
pc.addStream(audioStream);
}
var browser = parser.getBrowser();
if (mode === 'sendonly' && (browser.name === 'Chrome' || browser.name === 'Chromium') && browser.major === 39) {
mode = 'sendrecv';
}
callback();
}
if (mode !== 'recvonly' && !videoStream && !audioStream) {
function getMedia(constraints) {
if (constraints === undefined) {
constraints = MEDIA_CONSTRAINTS;
}
getUserMedia(constraints, function (stream) {
videoStream = stream;
start();
}, callback);
}
if (sendSource === 'webcam') {
getMedia(mediaConstraints);
} else {
getScreenConstraints(sendSource, function (error, constraints_) {
if (error)
return callback(error);
constraints = [mediaConstraints];
constraints.unshift(constraints_);
getMedia(recursive.apply(undefined, constraints));
}, guid);
}
} else {
setTimeout(start, 0);
}
this.on('_dispose', function () {
if (localVideo) {
localVideo.pause();
localVideo.srcObject = '';
localVideo.load();
localVideo.muted = false;
}
if (remoteVideo) {
remoteVideo.pause();
remoteVideo.srcObject = '';
remoteVideo.load();
}
self.removeAllListeners();
if (window.cancelChooseDesktopMedia !== undefined) {
window.cancelChooseDesktopMedia(guid);
}
});
}
inherits(WebRtcPeer, EventEmitter);
function createEnableDescriptor(type) {
var method = 'get' + type + 'Tracks';
return {
enumerable: true,
get: function () {
if (!this.peerConnection)
return;
var streams = this.peerConnection.getLocalStreams();
if (!streams.length)
return;
for (var i = 0, stream; stream = streams[i]; i++) {
var tracks = stream[method]();
for (var j = 0, track; track = tracks[j]; j++)
if (!track.enabled)
return false;
}
return true;
},
set: function (value) {
function trackSetEnable(track) {
track.enabled = value;
}
this.peerConnection.getLocalStreams().forEach(function (stream) {
stream[method]().forEach(trackSetEnable);
});
}
};
}
Object.defineProperties(WebRtcPeer.prototype, {
'enabled': {
enumerable: true,
get: function () {
return this.audioEnabled && this.videoEnabled;
},
set: function (value) {
this.audioEnabled = this.videoEnabled = value;
}
},
'audioEnabled': createEnableDescriptor('Audio'),
'videoEnabled': createEnableDescriptor('Video')
});
WebRtcPeer.prototype.getLocalStream = function (index) {
if (this.peerConnection) {
return this.peerConnection.getLocalStreams()[index || 0];
}
};
WebRtcPeer.prototype.getRemoteStream = function (index) {
if (this.peerConnection) {
return this.peerConnection.getRemoteStreams()[index || 0];
}
};
WebRtcPeer.prototype.dispose = function () {
console.log('Disposing WebRtcPeer');
var pc = this.peerConnection;
var dc = this.dataChannel;
try {
if (dc) {
if (dc.signalingState === 'closed')
return;
dc.close();
}
if (pc) {
if (pc.signalingState === 'closed')
return;
pc.getLocalStreams().forEach(streamStop);
pc.close();
}
} catch (err) {
console.warn('Exception disposing webrtc peer ' + err);
}
this.emit('_dispose');
};
function WebRtcPeerRecvonly(options, callback) {
if (!(this instanceof WebRtcPeerRecvonly)) {
return new WebRtcPeerRecvonly(options, callback);
}
WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback);
}
inherits(WebRtcPeerRecvonly, WebRtcPeer);
function WebRtcPeerSendonly(options, callback) {
if (!(this instanceof WebRtcPeerSendonly)) {
return new WebRtcPeerSendonly(options, callback);
}
WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback);
}
inherits(WebRtcPeerSendonly, WebRtcPeer);
function WebRtcPeerSendrecv(options, callback) {
if (!(this instanceof WebRtcPeerSendrecv)) {
return new WebRtcPeerSendrecv(options, callback);
}
WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback);
}
inherits(WebRtcPeerSendrecv, WebRtcPeer);
function harkUtils(stream, options) {
return hark(stream, options);
}
exports.bufferizeCandidates = bufferizeCandidates;
exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
exports.hark = harkUtils;
I want to offer above mentioned sdp , however chrome is offering its defualt sdp. Also I have updated to unified plan in webrtcpeer.js , however chrome is running on planb.
in console I get:
This appears to be Chrome
WebRtcPeer.js:30 Chrome: using SDP PlanB
The text was updated successfully, but these errors were encountered:
I want to send modified sdp to chrome. However it is not receiving that modified sdp which is changed in sdp_pattern.txt
webrtcpeer.js
I want to offer above mentioned sdp , however chrome is offering its defualt sdp. Also I have updated to unified plan in webrtcpeer.js , however chrome is running on planb.
in console I get:
The text was updated successfully, but these errors were encountered: