Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

now firefox to firefox works. It looks like there is a conection betw…

…een firefox and chrome to but I have not gotten the media to play back. I dont know why the video is not playing back in the video tag... any one please have a look
  • Loading branch information...
commit e9b831374d87c7beb5e28d6e4746fc3f3367a21a 1 parent 8bd941d
Dennis Mårtensson authored
Showing with 224 additions and 86 deletions.
  1. +3 −2 site/script.js
  2. +0 −13 site/server.js
  3. +221 −71 site/webrtc.io.js
View
5 site/script.js
@@ -1,5 +1,5 @@
var videos = [];
-var PeerConnection = window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection;
+var PeerConnection = window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.RTCPeerConnection;
function getNumPerRow() {
var len = videos.length;
@@ -164,10 +164,11 @@ function initChat() {
function init() {
if(PeerConnection) {
rtc.createStream({
- "video": true,
+ "video": {"mandatory": {}, "optional": []},
"audio": true
}, function(stream) {
document.getElementById('you').src = URL.createObjectURL(stream);
+ document.getElementById('you').play();
videos.push(document.getElementById('you'));
//rtc.attachStream(stream, 'you');
subdivideVideos();
View
13 site/server.js
@@ -27,19 +27,6 @@ app.get('/webrtc.io.js', function(req, res) {
res.sendfile(__dirname + '/webrtc.io.js');
});
-
-webRTC.rtc.on('connect', function(rtc) {
- //Client connected
-});
-
-webRTC.rtc.on('send answer', function(rtc) {
- //answer sent
-});
-
-webRTC.rtc.on('disconnect', function(rtc) {
- //Client disconnect
-});
-
webRTC.rtc.on('chat_msg', function(data, socket) {
var roomList = webRTC.rtc.rooms[data.room] || [];
View
292 site/webrtc.io.js
@@ -1,10 +1,40 @@
//CLIENT
- // Fallbacks for vendor-specific variables until the spec is finalized.
+// Fallbacks for vendor-specific variables until the spec is finalized.
+
+var PeerConnection = (window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection || window.mozRTCPeerConnection);
+var URL = (window.URL || window.webkitURL || window.msURL || window.oURL);
+var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
+var nativeRTCIceCandidate = (window.mozRTCIceCandidate || window.RTCIceCandidate);
+var nativeRTCSessionDescription = (window.mozRTCSessionDescription || window.RTCSessionDescription); // order is very important: "RTCSessionDescription" defined in Nighly but useless
+
+var sdpConstraints = {
+ 'mandatory': {
+ 'OfferToReceiveAudio': true,
+ 'OfferToReceiveVideo': true
+ }
+};
-var PeerConnection = window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection;
-var URL = window.URL || window.webkitURL || window.msURL || window.oURL;
-var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+if (navigator.webkitGetUserMedia) {
+ if (!webkitMediaStream.prototype.getVideoTracks) {
+ webkitMediaStream.prototype.getVideoTracks = function() {
+ return this.videoTracks;
+ };
+ webkitMediaStream.prototype.getAudioTracks = function() {
+ return this.audioTracks;
+ };
+ }
+
+ // New syntax of getXXXStreams method in M26.
+ if (!webkitRTCPeerConnection.prototype.getLocalStreams) {
+ webkitRTCPeerConnection.prototype.getLocalStreams = function() {
+ return this.localStreams;
+ };
+ webkitRTCPeerConnection.prototype.getRemoteStreams = function() {
+ return this.remoteStreams;
+ };
+ }
+}
(function() {
@@ -44,7 +74,21 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
};
// Holds the STUN/ICE server to use for PeerConnections.
- rtc.SERVER = {iceServers:[{url:"stun:stun.l.google.com:19302"}]};
+ rtc.SERVER = function() {
+ if (navigator.mozGetUserMedia) {
+ return {
+ "iceServers": [{
+ "url": "stun:23.21.150.121"
+ }]
+ };
+ }
+ return {
+ "iceServers": [{
+ "url": "stun:stun.l.google.com:19302"
+ }]
+ };
+ }
+
// Reference to the lone PeerConnection instance.
rtc.peerConnections = {};
@@ -61,18 +105,32 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
rtc.dataChannels = {};
// PeerConnection datachannel configuration
- rtc.dataChannelConfig = {optional: [ {RtpDataChannels: true} ] };
+ rtc.dataChannelConfig = {
+ "optional": [{
+ "RtpDataChannels": true
+ }, {
+ "DtlsSrtpKeyAgreement": true
+ }]
+ };
+
+ rtc.pc_constraints = {
+ "optional": [{
+ "DtlsSrtpKeyAgreement": true
+ }]
+ }
// check whether data channel is supported.
rtc.checkDataChannelSupport = function() {
try {
// raises exception if createDataChannel is not supported
- var pc = new PeerConnection(rtc.SERVER, rtc.dataChannelConfig);
- var channel = pc.createDataChannel('supportCheck', {reliable: false});
+ var pc = new PeerConnection(rtc.SERVER(), rtc.dataChannelConfig);
+ var channel = pc.createDataChannel('supportCheck', {
+ reliable: false
+ });
channel.close();
return true;
- } catch(e) {
+ } catch (e) {
return false;
}
};
@@ -91,7 +149,7 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
rtc._socket.send(JSON.stringify({
"eventName": "join_room",
- "data":{
+ "data": {
"room": room
}
}));
@@ -119,7 +177,7 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
});
rtc.on('receive_ice_candidate', function(data) {
- var candidate = new RTCIceCandidate(data);
+ var candidate = new nativeRTCIceCandidate(data);
rtc.peerConnections[data.socketId].addIceCandidate(candidate);
rtc.fire('receive ice candidate', candidate);
});
@@ -174,24 +232,24 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
};
rtc.createPeerConnection = function(id) {
- var config;
- if (rtc.dataChannelSupport)
- config = rtc.dataChannelConfig;
- var pc = rtc.peerConnections[id] = new PeerConnection(rtc.SERVER, config);
+ var config = rtc.pc_constraints;
+ if (rtc.dataChannelSupport) config = rtc.dataChannelConfig;
+
+ var pc = rtc.peerConnections[id] = new PeerConnection(rtc.SERVER(), config);
pc.onicecandidate = function(event) {
if (event.candidate) {
- rtc._socket.send(JSON.stringify({
- "eventName": "send_ice_candidate",
- "data": {
- "label": event.candidate.label,
- "candidate": event.candidate.candidate,
- "socketId": id
- }
- }));
- }
- rtc.fire('ice candidate', event.candidate);
- };
+ rtc._socket.send(JSON.stringify({
+ "eventName": "send_ice_candidate",
+ "data": {
+ "label": event.candidate.sdpMLineIndex,
+ "candidate": event.candidate.candidate,
+ "socketId": id
+ }
+ }));
+ }
+ rtc.fire('ice candidate', event.candidate);
+ };
pc.onopen = function() {
// TODO: Finalize this API
@@ -204,7 +262,7 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
};
if (rtc.dataChannelSupport) {
- pc.ondatachannel = function (evt) {
+ pc.ondatachannel = function(evt) {
console.log('data channel connecting ' + id);
rtc.addDataChannel(id, evt.channel);
};
@@ -215,60 +273,73 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
rtc.sendOffer = function(socketId) {
var pc = rtc.peerConnections[socketId];
- pc.createOffer( function(session_description) {
- pc.setLocalDescription(session_description);
- rtc._socket.send(JSON.stringify({
+
+ var constraints = {
+ "optional": [],
+ "mandatory": {
+ "MozDontOfferDataChannel": true
+ }
+ };
+ // temporary measure to remove Moz* constraints in Chrome
+ if (navigator.webkitGetUserMedia) {
+ for (prop in constraints.mandatory) {
+ if (prop.indexOf("Moz") != -1) {
+ delete constraints.mandatory[prop];
+ }
+ }
+ }
+ constraints = mergeConstraints(constraints, sdpConstraints);
+
+ pc.createOffer(function(session_description) {
+ session_description.sdp = preferOpus(session_description.sdp);
+ pc.setLocalDescription(session_description);
+ rtc._socket.send(JSON.stringify({
"eventName": "send_offer",
- "data":{
- "socketId": socketId,
- "sdp": session_description
- }
- }));
- });
+ "data": {
+ "socketId": socketId,
+ "sdp": session_description
+ }
+ }));
+ }, null, sdpConstraints);
};
-
rtc.receiveOffer = function(socketId, sdp) {
var pc = rtc.peerConnections[socketId];
- pc.setRemoteDescription(new RTCSessionDescription(sdp));
- rtc.sendAnswer(socketId);
+ rtc.sendAnswer(socketId, sdp);
};
-
- rtc.sendAnswer = function(socketId) {
+ rtc.sendAnswer = function(socketId, sdp) {
var pc = rtc.peerConnections[socketId];
- pc.createAnswer( function(session_description) {
- pc.setLocalDescription(session_description);
- rtc._socket.send(JSON.stringify({
+ pc.setRemoteDescription(new nativeRTCSessionDescription(sdp));
+ pc.createAnswer(function(session_description) {
+ pc.setLocalDescription(session_description);
+ rtc._socket.send(JSON.stringify({
"eventName": "send_answer",
- "data":{
- "socketId": socketId,
- "sdp": session_description
- }
+ "data": {
+ "socketId": socketId,
+ "sdp": session_description
}
- ));
- //TODO Unused variable!?
- var offer = pc.remoteDescription;
- });
+ }));
+ //TODO Unused variable!?
+ var offer = pc.remoteDescription;
+ }, null, sdpConstraints);
};
rtc.receiveAnswer = function(socketId, sdp) {
var pc = rtc.peerConnections[socketId];
- pc.setRemoteDescription(new RTCSessionDescription(sdp));
+ pc.setRemoteDescription(new nativeRTCSessionDescription(sdp));
};
rtc.createStream = function(opt, onSuccess, onFail) {
var options;
- onSuccess = onSuccess ||
- function() {};
- onFail = onFail ||
- function() {};
+ onSuccess = onSuccess || function() {};
+ onFail = onFail || function() {};
options = {
- video: !!opt.video,
- audio: !!opt.audio
+ video: !! opt.video,
+ audio: !! opt.audio
};
if (getUserMedia) {
@@ -300,7 +371,14 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
};
rtc.attachStream = function(stream, domId) {
- document.getElementById(domId).src = URL.createObjectURL(stream);
+ var element = document.getElementById(domId);
+ if (navigator.mozGetUserMedia) {
+ console.log("Attaching media stream");
+ element.mozSrcObject = stream;
+ element.play();
+ } else {
+ element.src = webkitURL.createObjectURL(stream);
+ }
};
@@ -308,7 +386,7 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
if (!rtc.dataChannelSupport) {
//TODO this should be an exception
alert('webRTC data channel is not yet supported in this browser,' +
- ' or you must turn on experimental flags');
+ ' or you must turn on experimental flags');
return;
}
@@ -320,22 +398,21 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
pc = pcOrId;
id = undefined;
for (var key in rtc.peerConnections) {
- if (rtc.peerConnections[key] === pc)
- id = key;
+ if (rtc.peerConnections[key] === pc) id = key;
}
}
- if (!id)
- throw new Error ('attempt to createDataChannel with unknown id');
+ if (!id) throw new Error('attempt to createDataChannel with unknown id');
- if (!pc || !(pc instanceof PeerConnection))
- throw new Error ('attempt to createDataChannel without peerConnection');
+ if (!pc || !(pc instanceof PeerConnection)) throw new Error('attempt to createDataChannel without peerConnection');
// need a label
label = label || 'fileTransfer' || String(id);
// chrome only supports reliable false atm.
- var options = {reliable: false};
+ var options = {
+ reliable: false
+ };
var channel;
try {
@@ -379,11 +456,10 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
};
rtc.addDataChannels = function() {
- if (!rtc.dataChannelSupport)
- return;
+ if (!rtc.dataChannelSupport) return;
for (var connection in rtc.peerConnections)
- rtc.createDataChannel(connection);
+ rtc.createDataChannel(connection);
};
@@ -395,3 +471,77 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav
});
}).call(this);
+
+function preferOpus(sdp) {
+ var sdpLines = sdp.split('\r\n');
+
+ // Search for m line.
+ for (var i = 0; i < sdpLines.length; i++) {
+ if (sdpLines[i].search('m=audio') !== -1) {
+ var mLineIndex = i;
+ break;
+ }
+ }
+ if (mLineIndex === null) return sdp;
+
+ // If Opus is available, set it as the default in m line.
+ for (var i = 0; i < sdpLines.length; i++) {
+ if (sdpLines[i].search('opus/48000') !== -1) {
+ var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
+ if (opusPayload) sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
+ break;
+ }
+ }
+
+ // Remove CN in m line and sdp.
+ sdpLines = removeCN(sdpLines, mLineIndex);
+
+ sdp = sdpLines.join('\r\n');
+ return sdp;
+}
+
+function extractSdp(sdpLine, pattern) {
+ var result = sdpLine.match(pattern);
+ return (result && result.length == 2) ? result[1] : null;
+}
+
+function setDefaultCodec(mLine, payload) {
+ var elements = mLine.split(' ');
+ var newLine = new Array();
+ var index = 0;
+ for (var i = 0; i < elements.length; i++) {
+ if (index === 3) // Format of media starts from the fourth.
+ newLine[index++] = payload; // Put target payload to the first.
+ if (elements[i] !== payload) newLine[index++] = elements[i];
+ }
+ return newLine.join(' ');
+}
+
+function removeCN(sdpLines, mLineIndex) {
+ var mLineElements = sdpLines[mLineIndex].split(' ');
+ // Scan from end for the convenience of removing an item.
+ for (var i = sdpLines.length - 1; i >= 0; i--) {
+ var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
+ if (payload) {
+ var cnPos = mLineElements.indexOf(payload);
+ if (cnPos !== -1) {
+ // Remove CN payload from m line.
+ mLineElements.splice(cnPos, 1);
+ }
+ // Remove CN line in sdp
+ sdpLines.splice(i, 1);
+ }
+ }
+
+ sdpLines[mLineIndex] = mLineElements.join(' ');
+ return sdpLines;
+}
+
+function mergeConstraints(cons1, cons2) {
+ var merged = cons1;
+ for (var name in cons2.mandatory) {
+ merged.mandatory[name] = cons2.mandatory[name];
+ }
+ merged.optional.concat(cons2.optional);
+ return merged;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.