peerconnection-call.html revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org<html> 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org<head> 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org <script type="text/javascript"> 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org $ = function(id) { 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return document.getElementById(id); 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org }; 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // These must match with how the video and canvas tags are declared in html. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VIDEO_TAG_WIDTH = 320; 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VIDEO_TAG_HEIGHT = 240; 11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var gFirstConnection = null; 13cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org var gSecondConnection = null; 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var gTestWithoutMsidAndBundle = false; 15cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Number of test events to occur before the test pass. When the test pass, 17cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org // the document title change to OK. 18cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org var gNumberOfExpectedEvents = 0; 19cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org 207fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // Number of events that currently have occured. 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var gNumberOfEvents = 0; 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var gLocalStream = null; 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var gSentTones = ''; 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 267fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // Test that we can setup call with an audio and video track. 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function call(constraints) { 28b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org createConnections(null); 29b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org navigator.webkitGetUserMedia(constraints, 30b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-1'); 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-2'); 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // First calls without streams on any connections, and then adds a stream 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to peer connection 1 which gets sent to peer connection 2. 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function makeEmptyCallThenAddOneStreamAndRenegotiate(constraints) { 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org createConnections(null); 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org negotiate(); 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org navigator.webkitGetUserMedia(constraints, 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addStreamToTheFirstConnectionAndNegotiate, printGetUserMediaError); 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Only the first connection is sending here. 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-2'); 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Test that we can setup call with an audio and video track and 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // simulate that the remote peer don't support MSID. 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function callWithoutMsidAndBundle() { 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org createConnections(null); 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gTestWithoutMsidAndBundle = true; 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org navigator.webkitGetUserMedia({audio:true, video:true}, 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(phoglund): this should work but it doesn't! http://crbug.com/177443. 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // waitForVideo('remote-view-1'); 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-2'); 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Test only a data channel. 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function callWithDataOnly() { 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org createConnections({optional:[{RtpDataChannels: true}]}); 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org setupDataChannel(); 627fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gFirstConnection.createOffer(onOfferCreated); 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 64b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org 65b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org // Test call with audio, video and a data channel. 66b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org function callWithDataAndMedia() { 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org createConnections({optional:[{RtpDataChannels: true}]}); 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org setupDataChannel(); 69b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org navigator.webkitGetUserMedia({audio:true, video:true}, 70b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org addStreamToBothConnectionsAndNegotiate, 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org printGetUserMediaError); 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-1'); 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-2'); 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Test call with a data channel and later add audio and video. 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function callWithDataAndLaterAddMedia() { 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(perkj): This is needed for now until 797fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // https://code.google.com/p/webrtc/issues/detail?id=1203 is fixed. 80b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org gTestWithoutMsidAndBundle = true; 81b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org createConnections({optional:[{RtpDataChannels: true}]}); 83b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org setupDataChannel(); 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gFirstConnection.createOffer(onOfferCreated); 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 86b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org navigator.webkitGetUserMedia({audio:true, video:true}, 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-1'); 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitForVideo('remote-view-2'); 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Test that we can setup call and send DTMF. 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function callAndSendDtmf(tones) { 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org createConnections(null); 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org navigator.webkitGetUserMedia({audio:true, video:true}, 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var onCallEstablished = function() { 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Send DTMF tones. 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var localAudioTrack = gLocalStream.getAudioTracks()[0]; 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var dtmfSender = gFirstConnection.createDTMFSender(localAudioTrack); 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dtmfSender.ontonechange = onToneChange; 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dtmfSender.insertDTMF(tones); 1031bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org // Wait for the DTMF tones callback. 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org document.title = 'Waiting for dtmf...'; 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addExpectedEvent(); 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var waitDtmf = setInterval(function() { 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (gSentTones == tones) { 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org clearInterval(waitDtmf); 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org eventOccured(); 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org }, 100); 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Do the DTMF test after we have received video. 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org detectVideoIn('remote-view-2', onCallEstablished); 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This function is used for setting up a test that: 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1. Creates a data channel on |gFirstConnection| and sends data to 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // |gSecondConnection|. 1217fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // 2. When data is received on |gSecondConnection| a message 1227fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // is sent to |gFirstConnection|. 1237fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // 3. When data is received on |gFirstConnection|, the data 1247fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // channel is closed. The test passes when the state transition completes. 12599681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org function setupDataChannel() { 1267fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var sendDataString = "send some text on a data channel." 12799681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org firstDataChannel = gFirstConnection.createDataChannel( 1287fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org "sendDataChannel", {reliable : false}); 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org expectEquals('connecting', firstDataChannel.readyState); 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When |firstDataChannel| transition to open state, send a text string. 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org firstDataChannel.onopen = function() { 1337fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals('open', firstDataChannel.readyState); 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org firstDataChannel.send(sendDataString); 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When |firstDataChannel| receive a message, close the channel and 1387fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // initiate a new offer/answer exchange to complete the closure. 1397fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org firstDataChannel.onmessage = function(event) { 1407fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals(event.data, sendDataString); 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org firstDataChannel.close(); 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gFirstConnection.createOffer(onOfferCreated); 1437fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When |firstDataChannel| transition to closed state, the test pass. 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addExpectedEvent(); 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org firstDataChannel.onclose = function() { 1487fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals('closed', firstDataChannel.readyState); 1497fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org eventOccured(); 1507fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 1517fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 1527fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // Event handler for when |gSecondConnection| receive a new dataChannel. 1537fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gSecondConnection.ondatachannel = function (event) { 1547fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var secondDataChannel = event.channel; 1557fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When |secondDataChannel| receive a message, send a message back. 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org secondDataChannel.onmessage = function(event) { 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org expectEquals(event.data, sendDataString); 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org expectEquals('open', secondDataChannel.readyState); 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org secondDataChannel.send(sendDataString); 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function onToneChange(tone) { 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gSentTones += tone.tone; 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org document.title = gSentTones; 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function createConnections(constraints) { 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gFirstConnection = new webkitRTCPeerConnection(null, constraints); 1727fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gFirstConnection.onicecandidate = onIceCandidateToFirst; 1737fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gFirstConnection.onaddstream = function(event) { 1747fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org onRemoteStream(event, 'remote-view-1'); 1757fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 1767fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals('stable', gFirstConnection.signalingState); 1777fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gSecondConnection = new webkitRTCPeerConnection(null, constraints); 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gSecondConnection.onicecandidate = onIceCandidateToSecond; 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gSecondConnection.onaddstream = function(event) { 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org onRemoteStream(event, 'remote-view-2'); 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 184b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org 185b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org function displayAndRemember(localStream) { 186b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org var localStreamUrl = webkitURL.createObjectURL(localStream); 187b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org $('local-view').src = localStreamUrl; 1881bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gLocalStream = localStream; 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 192903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org // Called if getUserMedia fails. 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function printGetUserMediaError(error) { 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org document.title = 'getUserMedia request failed with code ' + error.code; 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1967fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Called if getUserMedia succeeds and we want to send from both connections. 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function addStreamToBothConnectionsAndNegotiate(localStream) { 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org displayAndRemember(localStream); 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gFirstConnection.addStream(localStream); 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gSecondConnection.addStream(localStream); 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org negotiate(); 2037fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Called if getUserMedia succeeds when we want to send from one connection. 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function addStreamToTheFirstConnectionAndNegotiate(localStream) { 2077fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org displayAndRemember(localStream); 20864b5c6141a124816290795f80d555eb994edec32pbos@webrtc.org gFirstConnection.addStream(localStream); 2097fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org negotiate(); 2107fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2117fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2127fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function negotiate() { 2137fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gFirstConnection.createOffer(onOfferCreated); 2147fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2157fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2167fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function onOfferCreated(offer) { 2177fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gFirstConnection.setLocalDescription(offer); 2187fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals('have-local-offer', gFirstConnection.signalingState); 2197fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org receiveOffer(offer.sdp); 2207fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2217fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2227fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function receiveOffer(offerSdp) { 2237fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org if (gTestWithoutMsidAndBundle) { 2247fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org offerSdp = removeMsidAndBundle(offerSdp); 2257fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2267fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2277fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var parsedOffer = new RTCSessionDescription({ type: 'offer', 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sdp: offerSdp }); 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gSecondConnection.setRemoteDescription(parsedOffer); 230b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org gSecondConnection.createAnswer(onAnswerCreated); 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org expectEquals('have-remote-offer', gSecondConnection.signalingState); 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2347fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function removeMsidAndBundle(offerSdp) { 2357e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.org offerSdp = offerSdp.replace(/a=msid-semantic.*\r\n/g, ''); 2367e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.org offerSdp = offerSdp.replace('a=group:BUNDLE audio video\r\n', ''); 2377e97e4c84dc21b2853f5158a03dcceb569e493adstefan@webrtc.org offerSdp = offerSdp.replace('a=mid:audio\r\n', ''); 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org offerSdp = offerSdp.replace('a=mid:video\r\n', ''); 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, ''); 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return offerSdp; 2417fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 24264b5c6141a124816290795f80d555eb994edec32pbos@webrtc.org 2437fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function onAnswerCreated(answer) { 2447fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gSecondConnection.setLocalDescription(answer); 2457fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals('stable', gSecondConnection.signalingState); 2467fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org handleAnswer(answer.sdp); 2477fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2487fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2497fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function handleAnswer(answerSdp) { 2507fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var parsedAnswer = new RTCSessionDescription({ type: 'answer', 2517fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org sdp: answerSdp }); 2527fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gFirstConnection.setRemoteDescription(parsedAnswer); 2537fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org expectEquals('stable', gFirstConnection.signalingState); 2547fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2557fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2567fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function onIceCandidateToFirst(event) { 2577fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org if (event.candidate) { 2587fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var candidate = new RTCIceCandidate(event.candidate); 2597fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org gSecondConnection.addIceCandidate(candidate); 2607fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2617fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 263903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org function onIceCandidateToSecond(event) { 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (event.candidate) { 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var candidate = new RTCIceCandidate(event.candidate); 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org gFirstConnection.addIceCandidate(candidate); 2677fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2687fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2697fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function onRemoteStream(e, target) { 2717fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org if (gTestWithoutMsidAndBundle && e.stream.label != "default") { 272b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org document.title = 'a default remote stream was expected but instead ' + 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org e.stream.label + ' was received.'; 2747fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org return; 2757fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2767fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var remoteStreamUrl = webkitURL.createObjectURL(e.stream); 2777fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var remoteVideo = $(target); 2787fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org remoteVideo.src = remoteStreamUrl; 2797fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 2807fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 2817fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // TODO(phoglund): perhaps use the video detector in chrome/test/data/webrtc/? 2827fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function detectVideoIn(videoElementName, callback) { 2837fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var width = VIDEO_TAG_WIDTH; 2847fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var height = VIDEO_TAG_HEIGHT; 2857fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var videoElement = $(videoElementName); 2867fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var canvas = $(videoElementName + '-canvas'); 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var waitVideo = setInterval(function() { 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var context = canvas.getContext('2d'); 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org context.drawImage(videoElement, 0, 0, width, height); 290b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org var pixels = context.getImageData(0, 0, width, height).data; 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (isVideoPlaying(pixels, width, height)) { 293b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org clearInterval(waitVideo); 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org callback(); 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 296b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org }, 100); 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 299b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org function waitForVideo(videoElement) { 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org document.title = 'Waiting for video...'; 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org addExpectedEvent(); 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org detectVideoIn(videoElement, function () { eventOccured(); }); 303b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org } 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This very basic video verification algorithm will be satisfied if any 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // pixels are nonzero in a small sample area in the middle. It relies on the 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // assumption that a video element with null source just presents zeroes. 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org function isVideoPlaying(pixels, width, height) { 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sample somewhere near the middle of the image. 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org var middle = width * height / 2; 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (var i = 0; i < 20; i++) { 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pixels[middle + i] > 0) { 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 3147fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 31564b5c6141a124816290795f80d555eb994edec32pbos@webrtc.org } 3167fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org return false; 3177fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 3187fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 3197fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 3207fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // This function matches |left| and |right| and throws an exception if the 3217fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org // values don't match. 3227fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function expectEquals(left, right) { 3237fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org if (left != right) { 3247fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org var s = "expectEquals failed left: " + left + " right: " + right; 3257fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org document.title = s; 3267fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org throw s; 3277fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 3287fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 3297fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 3307fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function addExpectedEvent() { 3317fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org ++gNumberOfExpectedEvents; 3327fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org } 3337fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org 3347fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org function eventOccured() { 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ++gNumberOfEvents; 336903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org if (gNumberOfEvents == gNumberOfExpectedEvents) { 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org document.title = 'OK'; 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org </script> 3417fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org</head> 3427fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org<body> 3437fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <table border="0"> 3447fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <tr> 3457fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <td>Local Preview</td> 3467fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <td>Remote Stream for Connection 1</td> 3477fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <td>Remote Stream for Connection 2</td> 3487fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org </tr> 3497fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <tr> 3507fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org <td><video width="320" height="240" id="local-view" 3517fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org autoplay="autoplay"></video></td> 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org <td><video width="320" height="240" id="remote-view-1" 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org autoplay="autoplay"></video></td> 354b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org <td><video width="320" height="240" id="remote-view-2" 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org autoplay="autoplay"></video></td> 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org <!-- Canvases are named after their corresponding video elements. --> 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org <td><canvas width="320" height="240" id="remote-view-1-canvas" 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org style="display:none"></canvas></td> 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org <td><canvas width="320" height="240" id="remote-view-2-canvas"> 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org style="display:none"></canvas></td> 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org </tr> 362b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org </table> 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org</body> 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org</html> 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org