| <!DOCTYPE html> |
| <html> |
| <!-- Load the polyfill to switch-hit between Chrome and Firefox --> |
| <script src='../../base/adapter.js'></script> |
| <head> |
| <title>PC1 SDP Munge Demo</title> |
| <style> |
| div#left { |
| float: left; |
| margin: 0 2em 2.5em 0; |
| } |
| div#right { |
| float: left; |
| margin: 0 0 1.5em 0; |
| } |
| div#buttons button { |
| margin: 0 1.3em 1em 0; |
| width: 13em; |
| } |
| div#buttons { |
| max-width: 30em; |
| } |
| div#source { |
| clear: both; |
| margin: 0 0 1em 0; |
| } |
| div#select { |
| margin: 0 0 1em 0; |
| } |
| select { |
| margin: 0 1em 0 0; |
| } |
| h2 { |
| font-size: 1em; |
| font-family: sans-serif; |
| margin: 0 0 0.3em 0; |
| padding: 0; |
| } |
| textarea { |
| height: 20em; |
| width: 98%; |
| } |
| video { |
| background: #666; |
| margin: 0 0 1.5em 0; |
| width: 320px; |
| height: 240px; |
| } |
| </style> |
| </head> |
| <body> |
| <div id="left"> |
| <h2>Local Preview</h2> |
| <video id="vid1" autoplay muted></video> |
| <h2>Offer SDP</h2> |
| <textarea id="offerSdp"></textarea><br><br> |
| </div> |
| <div id="right"> |
| <h2>Remote Preview</h2> |
| <video id="vid2" autoplay></video> |
| <h2>Answer SDP</h2> |
| <textarea id="answerSdp"></textarea> |
| </div> |
| <div id="source"> |
| <label for="audiosrc">Audio source: </label><select id="audiosrc"></select> |
| <label for="videosrc">Video source: </label><select id="videosrc"></select> |
| </div> |
| <div id="select">Select an audio & video source, then click GetUserMedia:</div> |
| <div id="buttons"> |
| <button id="btnMedia" onclick="getMedia()">GetUserMedia</button> |
| <button id="btnCreatePC" onclick="createPC()">Create PeerConnection</button> |
| <button id="btnOffer" onclick="createOffer()">Create Offer</button> |
| <button id="btnSetOffer" onclick="setOffer()">Set Offer</button> |
| <button id="btnAnswer" onclick="createAnswer()">Create Answer</button> |
| <button id="btnSetAnswer" onclick="setAnswer()">Set Answer</button> |
| <button id="btnHangUp" onclick="hangup()">Hang Up</button> |
| </div> |
| <script> |
| var audio_select = document.getElementById("audiosrc"); |
| var video_select = document.getElementById("videosrc"); |
| btnMedia.disabled = false; |
| btnCreatePC.disabled = true; |
| btnOffer.disabled = true; |
| btnSetOffer.disabled = true; |
| btnAnswer.disabled = true; |
| btnSetAnswer.disabled = true; |
| btnHangUp.disabled = true; |
| //audio_select.onchange = changeDevices; |
| //video_select.onchange = changeDevices; |
| var pc1,pc2; |
| var localstream; |
| var sdpConstraints = {'mandatory': { |
| 'OfferToReceiveAudio':true, |
| 'OfferToReceiveVideo':true }}; |
| refreshSources(); |
| |
| function refreshSources() { |
| if (webrtcDetectedVersion >= 30) { |
| MediaStreamTrack.getSources(gotSources); |
| } else { |
| alert('Make sure that you have Chrome M30 to test device enumeration api.'); |
| } |
| } |
| |
| function gotSources(sourceInfos) { |
| var audio_count = 0; |
| var video_count = 0; |
| audio_select.disabled = true; |
| video_select.disabled = true; |
| audio_select.innerHTML = ''; |
| video_select.innerHTML = ''; |
| for (var i = 0; i < sourceInfos.length; i++) { |
| var option = document.createElement("option"); |
| option.value = sourceInfos[i].id; |
| option.text = sourceInfos[i].label; |
| if (sourceInfos[i].kind === 'audio') { |
| audio_count++; |
| if (option.text === '') { |
| option.text = 'Audio ' + audio_count; |
| } |
| audio_select.appendChild(option); |
| } else { |
| video_count++; |
| if (option.text === '') { |
| option.text = 'Video ' + video_count; |
| } |
| video_select.appendChild(option); |
| } |
| } |
| audio_select.disabled = false; |
| video_select.disabled = false; |
| } |
| |
| function getMedia() { |
| changeDevices(); |
| audio_select.disabled = true; |
| video_select.disabled = true; |
| btnMedia.disabled = true; |
| btnCreatePC.disabled = false; |
| } |
| |
| function changeDevices() { |
| var audio_source = null; |
| var video_source = null; |
| if (audio_select.options.length > 0) { |
| audio_source = audio_select.options[audio_select.selectedIndex].value; |
| trace('selected audio_source :' + audio_source); |
| } |
| if (video_select.options.length > 0 ) { |
| video_source = video_select.options[video_select.selectedIndex].value; |
| trace('selected video_source :' + video_source); |
| } |
| setWebcamAndMic(audio_source, video_source); |
| } |
| |
| function setWebcamAndMic(audio_source, video_source) { |
| trace("Requesting local stream"); |
| // Call into getUserMedia via the polyfill (adapter.js). |
| getUserMedia({ audio: {optional: [{sourceId: audio_source}]}, |
| video: {optional: [{sourceId: video_source}]} |
| }, gotStream, function() {}); |
| } |
| |
| function gotStream(stream) { |
| trace("Received local stream"); |
| // Call the polyfill wrapper to attach the media stream to this element. |
| attachMediaStream(vid1, stream); |
| localstream = stream; |
| } |
| |
| function createPC() { |
| btnCreatePC.disabled = true; |
| btnOffer.disabled = false; |
| btnAnswer.disabled = false; |
| btnSetOffer.disabled = false; |
| btnSetAnswer.disabled = false; |
| btnHangUp.disabled = false; |
| trace("Starting call"); |
| videoTracks = localstream.getVideoTracks(); |
| audioTracks = localstream.getAudioTracks(); |
| if (videoTracks.length > 0) { |
| trace('Using Video device: ' + videoTracks[0].label); |
| } |
| if (audioTracks.length > 0) { |
| trace('Using Audio device: ' + audioTracks[0].label); |
| } |
| var servers = null; |
| pc1 = new RTCPeerConnection(servers); |
| trace("Created local peer connection object pc1"); |
| pc1.onicecandidate = iceCallback1; |
| pc2 = new RTCPeerConnection(servers); |
| trace("Created remote peer connection object pc2"); |
| pc2.onicecandidate = iceCallback2; |
| pc2.onaddstream = gotRemoteStream; |
| |
| pc1.addStream(localstream); |
| trace("Adding Local Stream to peer connection"); |
| } |
| |
| function onSetSessionDescriptionSuccess() { |
| trace('Set session description success.'); |
| } |
| |
| function onSetSessionDescriptionError(error) { |
| trace('Failed to set session description: ' + error.toString()); |
| } |
| |
| // Workaround for crbug/322756. |
| function maybeAddLineBreakToEnd(sdp) { |
| var endWithLineBreak = new RegExp(/\n$/); |
| if (!endWithLineBreak.test(sdp)) { |
| return sdp + '\n'; |
| } |
| return sdp; |
| } |
| |
| function createOffer(){ |
| pc1.createOffer(gotDescription1,null,null); |
| } |
| |
| function setOffer(){ |
| var sdp = document.getElementById("offerSdp").value; |
| sdp = maybeAddLineBreakToEnd(sdp); |
| var offer = new RTCSessionDescription({type:'offer',sdp:sdp}); |
| pc1.setLocalDescription(offer, |
| onSetSessionDescriptionSuccess, |
| onSetSessionDescriptionError); |
| trace("Modified Offer from pc1 \n" + sdp); |
| pc2.setRemoteDescription(offer, |
| onSetSessionDescriptionSuccess, |
| onSetSessionDescriptionError); |
| } |
| |
| function gotDescription1(desc) { |
| document.getElementById("offerSdp").disabled = false; |
| document.getElementById("offerSdp").value = desc.sdp; |
| } |
| |
| function createAnswer(){ |
| // Since the "remote" side has no media stream we need |
| // to pass in the right constraints in order for it to |
| // accept the incoming offer of audio and video. |
| pc2.createAnswer(gotDescription2, null, sdpConstraints); |
| } |
| |
| function setAnswer(){ |
| var sdp = document.getElementById("answerSdp").value; |
| sdp = maybeAddLineBreakToEnd(sdp); |
| var answer = new RTCSessionDescription({type:'answer',sdp:sdp}); |
| pc2.setLocalDescription(answer, |
| onSetSessionDescriptionSuccess, |
| onSetSessionDescriptionError); |
| trace("Modified Answer from pc2 \n" + sdp); |
| pc1.setRemoteDescription(answer, |
| onSetSessionDescriptionSuccess, |
| onSetSessionDescriptionError); |
| } |
| |
| function gotDescription2(desc) { |
| document.getElementById("answerSdp").disabled = false; |
| document.getElementById("answerSdp").value = desc.sdp; |
| } |
| |
| function hangup() { |
| trace("Ending call"); |
| localstream.stop(); |
| pc1.close(); |
| pc2.close(); |
| pc1 = null; |
| pc2 = null; |
| audio_select.disabled = false; |
| video_select.disabled = false; |
| document.getElementById("offerSdp").disabled = true; |
| document.getElementById("answerSdp").disabled = true; |
| btnMedia.disabled = false; |
| btnCreatePC.disabled = true; |
| btnOffer.disabled = true; |
| btnSetOffer.disabled = true; |
| btnAnswer.disabled = true; |
| btnSetAnswer.disabled = true; |
| btnHangUp.disabled = true; |
| } |
| |
| function gotRemoteStream(e) { |
| // Call the polyfill wrapper to attach the media stream to this element. |
| attachMediaStream(vid2, e.stream); |
| trace("Received remote stream"); |
| } |
| |
| function iceCallback1(event) { |
| if (event.candidate) { |
| pc2.addIceCandidate(new RTCIceCandidate(event.candidate)); |
| trace("Local ICE candidate: \n" + event.candidate.candidate); |
| } |
| } |
| |
| function iceCallback2(event) { |
| if (event.candidate) { |
| pc1.addIceCandidate(new RTCIceCandidate(event.candidate)); |
| trace("Remote ICE candidate: \n " + event.candidate.candidate); |
| } |
| } |
| </script> |
| </body> |
| </html> |