| OLD | NEW |
| 1 <html> | 1 <html> |
| 2 <head> | 2 <head> |
| 3 <script type="text/javascript" src="webrtc_test_utilities.js"></script> | 3 <script type="text/javascript" src="webrtc_test_utilities.js"></script> |
| 4 <script type="text/javascript" src="webrtc_test_audio.js"></script> | 4 <script type="text/javascript" src="webrtc_test_audio.js"></script> |
| 5 <script type="text/javascript"> | 5 <script type="text/javascript"> |
| 6 $ = function(id) { | 6 $ = function(id) { |
| 7 return document.getElementById(id); | 7 return document.getElementById(id); |
| 8 }; | 8 }; |
| 9 | 9 |
| 10 var gFirstConnection = null; | 10 var gFirstConnection = null; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 // Remove all other codecs (not the video codecs though). Also leave | 30 // Remove all other codecs (not the video codecs though). Also leave |
| 31 // 126 for DTMF. | 31 // 126 for DTMF. |
| 32 sdp = sdp.replace(/m=audio (\d+) RTP\/SAVPF.*\r\n/g, | 32 sdp = sdp.replace(/m=audio (\d+) RTP\/SAVPF.*\r\n/g, |
| 33 'm=audio $1 RTP/SAVPF 103 126\r\n'); | 33 'm=audio $1 RTP/SAVPF 103 126\r\n'); |
| 34 sdp = sdp.replace('a=fmtp:111 minptime=10', 'a=fmtp:103 minptime=10'); | 34 sdp = sdp.replace('a=fmtp:111 minptime=10', 'a=fmtp:103 minptime=10'); |
| 35 sdp = sdp.replace( | 35 sdp = sdp.replace( |
| 36 /a=rtpmap:(?!(103|126))\d{1,3} (?!X?VP8|red|ulpfec).*\r\n/g, | 36 /a=rtpmap:(?!(103|126))\d{1,3} (?!X?VP8|red|ulpfec).*\r\n/g, |
| 37 ''); | 37 ''); |
| 38 return sdp; | 38 return sdp; |
| 39 }; | 39 }; |
| 40 sendValueToTest('isac-forced'); |
| 40 } | 41 } |
| 41 | 42 |
| 42 // When using external SDES, the crypto key is chosen by javascript. | 43 // When using external SDES, the crypto key is chosen by javascript. |
| 43 var EXTERNAL_SDES_LINES = { | 44 var EXTERNAL_SDES_LINES = { |
| 44 'audio': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + | 45 'audio': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + |
| 45 'inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR', | 46 'inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR', |
| 46 'video': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + | 47 'video': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + |
| 47 'inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj', | 48 'inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj', |
| 48 'data': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + | 49 'data': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + |
| 49 'inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj' | 50 'inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj' |
| 50 }; | 51 }; |
| 51 | 52 |
| 52 // When using GICE, the ICE credentials can be chosen by javascript. | 53 // When using GICE, the ICE credentials can be chosen by javascript. |
| 53 var EXTERNAL_GICE_UFRAG = '1234567890123456'; | 54 var EXTERNAL_GICE_UFRAG = '1234567890123456'; |
| 54 var EXTERNAL_GICE_PWD = '123456789012345678901234'; | 55 var EXTERNAL_GICE_PWD = '123456789012345678901234'; |
| 55 | 56 |
| 56 setAllEventsOccuredHandler(function() { | 57 setAllEventsOccuredHandler(reportTestSuccess); |
| 57 // The C++ tests look for this 'OK' in the title. | |
| 58 document.title = 'OK'; | |
| 59 }); | |
| 60 | 58 |
| 61 // Test that we can setup call with an audio and video track. | 59 // Test that we can setup call with an audio and video track. |
| 62 function call(constraints) { | 60 function call(constraints) { |
| 63 createConnections(null); | 61 createConnections(null); |
| 64 navigator.webkitGetUserMedia(constraints, | 62 navigator.webkitGetUserMedia(constraints, |
| 65 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 63 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 66 waitForVideo('remote-view-1'); | 64 waitForVideo('remote-view-1'); |
| 67 waitForVideo('remote-view-2'); | 65 waitForVideo('remote-view-2'); |
| 68 } | 66 } |
| 69 | 67 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 navigator.webkitGetUserMedia({audio: true, video: true}, | 135 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 138 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 136 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 139 waitForVideo('remote-view-1'); | 137 waitForVideo('remote-view-1'); |
| 140 waitForVideo('remote-view-2'); | 138 waitForVideo('remote-view-2'); |
| 141 } | 139 } |
| 142 | 140 |
| 143 // Test that we can't setup a call with an unsupported video codec | 141 // Test that we can't setup a call with an unsupported video codec |
| 144 function negotiateUnsupportedVideoCodec() { | 142 function negotiateUnsupportedVideoCodec() { |
| 145 createConnections(null); | 143 createConnections(null); |
| 146 transformSdp = removeVideoCodec; | 144 transformSdp = removeVideoCodec; |
| 145 |
| 147 onLocalDescriptionError = function(error) { | 146 onLocalDescriptionError = function(error) { |
| 148 var expectedMsg = 'Failed to set local offer sdp:' + | 147 var expectedMsg = 'Failed to set local offer sdp:' + |
| 149 ' Session error code: ERROR_CONTENT. Session error description:' + | 148 ' Session error code: ERROR_CONTENT. Session error description:' + |
| 150 ' Failed to set video receive codecs..'; | 149 ' Failed to set video receive codecs..'; |
| 151 expectEquals(expectedMsg, error); | 150 assertEquals(expectedMsg, error); |
| 152 | 151 reportTestSuccess(); |
| 153 // Got the right message, test succeeded. | |
| 154 document.title = 'OK'; | |
| 155 }; | 152 }; |
| 156 navigator.webkitGetUserMedia({audio: true, video: true}, | 153 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 157 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 154 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 158 } | 155 } |
| 159 | 156 |
| 160 // Test that we can't setup a call if one peer does not support encryption | 157 // Test that we can't setup a call if one peer does not support encryption |
| 161 function negotiateNonCryptoCall() { | 158 function negotiateNonCryptoCall() { |
| 162 createConnections(null); | 159 createConnections(null); |
| 163 transformSdp = removeCrypto; | 160 transformSdp = removeCrypto; |
| 164 onLocalDescriptionError = function(error) { | 161 onLocalDescriptionError = function(error) { |
| 165 var expectedMsg = 'Failed to set local offer sdp:' + | 162 var expectedMsg = 'Failed to set local offer sdp:' + |
| 166 ' Called with SDP without DTLS fingerprint.'; | 163 ' Called with SDP without DTLS fingerprint.'; |
| 167 expectEquals(expectedMsg, error); | |
| 168 | 164 |
| 169 // Got the right message, test succeeded. | 165 assertEquals(expectedMsg, error); |
| 170 document.title = 'OK'; | 166 reportTestSuccess(); |
| 171 }; | 167 }; |
| 172 navigator.webkitGetUserMedia({audio: true, video: true}, | 168 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 173 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 169 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 174 } | 170 } |
| 175 | 171 |
| 176 // Test that we can negotiate a call with an SDP offer that includes a | 172 // Test that we can negotiate a call with an SDP offer that includes a |
| 177 // b=AS:XX line to control audio and video bandwidth | 173 // b=AS:XX line to control audio and video bandwidth |
| 178 function negotiateOfferWithBLine() { | 174 function negotiateOfferWithBLine() { |
| 179 createConnections(null); | 175 createConnections(null); |
| 180 transformSdp = addBandwithControl; | 176 transformSdp = addBandwithControl; |
| 181 navigator.webkitGetUserMedia({audio: true, video: true}, | 177 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 182 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 178 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 183 waitForVideo('remote-view-1'); | 179 waitForVideo('remote-view-1'); |
| 184 waitForVideo('remote-view-2'); | 180 waitForVideo('remote-view-2'); |
| 185 } | 181 } |
| 186 | 182 |
| 187 // Test that we can setup call with legacy settings. | 183 // Test that we can setup call with legacy settings. |
| 188 function callWithLegacySdp() { | 184 function callWithLegacySdp() { |
| 189 transformSdp = function(sdp) { | 185 transformSdp = function(sdp) { |
| 190 return removeBundle(useGice(useExternalSdes(sdp))); | 186 return removeBundle(useGice(useExternalSdes(sdp))); |
| 191 }; | 187 }; |
| 192 transformCandidate = addGiceCredsToCandidate; | 188 transformCandidate = addGiceCredsToCandidate; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 | 233 |
| 238 // Test call with a data channel and later add audio and video. | 234 // Test call with a data channel and later add audio and video. |
| 239 function callWithDataAndLaterAddMedia() { | 235 function callWithDataAndLaterAddMedia() { |
| 240 createConnections({optional:[{RtpDataChannels: true}]}); | 236 createConnections({optional:[{RtpDataChannels: true}]}); |
| 241 setupDataChannel({reliable: false}); | 237 setupDataChannel({reliable: false}); |
| 242 negotiate(); | 238 negotiate(); |
| 243 | 239 |
| 244 // Set an event handler for when the data channel has been closed. | 240 // Set an event handler for when the data channel has been closed. |
| 245 setAllEventsOccuredHandler(function() { | 241 setAllEventsOccuredHandler(function() { |
| 246 // When the video is flowing the test is done. | 242 // When the video is flowing the test is done. |
| 247 setAllEventsOccuredHandler(function() { | 243 setAllEventsOccuredHandler(reportTestSuccess); |
| 248 document.title = 'OK'; | |
| 249 }); | |
| 250 navigator.webkitGetUserMedia({audio: true, video: true}, | 244 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 251 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 245 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 252 waitForVideo('remote-view-1'); | 246 waitForVideo('remote-view-1'); |
| 253 waitForVideo('remote-view-2'); | 247 waitForVideo('remote-view-2'); |
| 254 }); | 248 }); |
| 255 } | 249 } |
| 256 | 250 |
| 257 // Test that we can setup call and send DTMF. | 251 // Test that we can setup call and send DTMF. |
| 258 function callAndSendDtmf(tones) { | 252 function callAndSendDtmf(tones) { |
| 259 createConnections(null); | 253 createConnections(null); |
| 260 navigator.webkitGetUserMedia({audio: true, video: true}, | 254 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 261 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 255 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 262 var onCallEstablished = function() { | 256 var onCallEstablished = function() { |
| 263 // Send DTMF tones. | 257 // Send DTMF tones. |
| 264 var localAudioTrack = gLocalStream.getAudioTracks()[0]; | 258 var localAudioTrack = gLocalStream.getAudioTracks()[0]; |
| 265 var dtmfSender = gFirstConnection.createDTMFSender(localAudioTrack); | 259 var dtmfSender = gFirstConnection.createDTMFSender(localAudioTrack); |
| 266 dtmfSender.ontonechange = onToneChange; | 260 dtmfSender.ontonechange = onToneChange; |
| 267 dtmfSender.insertDTMF(tones); | 261 dtmfSender.insertDTMF(tones); |
| 268 // Wait for the DTMF tones callback. | 262 // Wait for the DTMF tones callback. |
| 269 document.title = 'Waiting for dtmf...'; | |
| 270 addExpectedEvent(); | 263 addExpectedEvent(); |
| 271 var waitDtmf = setInterval(function() { | 264 var waitDtmf = setInterval(function() { |
| 272 if (gSentTones == tones) { | 265 if (gSentTones == tones) { |
| 273 clearInterval(waitDtmf); | 266 clearInterval(waitDtmf); |
| 274 eventOccured(); | 267 eventOccured(); |
| 275 } | 268 } |
| 276 }, 100); | 269 }, 100); |
| 277 } | 270 } |
| 278 | 271 |
| 279 // Do the DTMF test after we have received video. | 272 // Do the DTMF test after we have received video. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 function callAndEnsureAudioMutingWorks() { | 309 function callAndEnsureAudioMutingWorks() { |
| 317 callAndEnsureAudioIsPlaying(); | 310 callAndEnsureAudioIsPlaying(); |
| 318 setAllEventsOccuredHandler(function() { | 311 setAllEventsOccuredHandler(function() { |
| 319 // Call is up, now mute the track and check everything goes silent (give | 312 // Call is up, now mute the track and check everything goes silent (give |
| 320 // it a small delay though, we don't expect it to happen instantly). | 313 // it a small delay though, we don't expect it to happen instantly). |
| 321 enableRemoteAudio(gSecondConnection, false); | 314 enableRemoteAudio(gSecondConnection, false); |
| 322 | 315 |
| 323 setTimeout(function() { | 316 setTimeout(function() { |
| 324 gatherAudioLevelSamples(gSecondConnection, 200, 100, function(samples) { | 317 gatherAudioLevelSamples(gSecondConnection, 200, 100, function(samples) { |
| 325 verifyIsSilent(samples); | 318 verifyIsSilent(samples); |
| 326 document.title = 'OK'; | 319 reportTestSuccess(); |
| 327 }); | 320 }); |
| 328 }, 500); | 321 }, 500); |
| 329 }); | 322 }); |
| 330 } | 323 } |
| 331 | 324 |
| 332 function callAndEnsureVideoMutingWorks() { | 325 function callAndEnsureVideoMutingWorks() { |
| 333 createConnections(null); | 326 createConnections(null); |
| 334 navigator.webkitGetUserMedia({audio: true, video: true}, | 327 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 335 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 328 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 336 | 329 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 // Add an audio track to the local stream and remove the video track and | 370 // Add an audio track to the local stream and remove the video track and |
| 378 // then renegotiate. But first - setup the expectations. | 371 // then renegotiate. But first - setup the expectations. |
| 379 local_stream = gFirstConnection.getLocalStreams()[0]; | 372 local_stream = gFirstConnection.getLocalStreams()[0]; |
| 380 | 373 |
| 381 remote_stream_1 = gFirstConnection.getRemoteStreams()[0]; | 374 remote_stream_1 = gFirstConnection.getRemoteStreams()[0]; |
| 382 // Add an expected event that onaddtrack will be called on the remote | 375 // Add an expected event that onaddtrack will be called on the remote |
| 383 // mediastream received on gFirstConnection when the audio track is | 376 // mediastream received on gFirstConnection when the audio track is |
| 384 // received. | 377 // received. |
| 385 addExpectedEvent(); | 378 addExpectedEvent(); |
| 386 remote_stream_1.onaddtrack = function(){ | 379 remote_stream_1.onaddtrack = function(){ |
| 387 expectEquals(remote_stream_1.getAudioTracks()[0].id, | 380 assertEquals(remote_stream_1.getAudioTracks()[0].id, |
| 388 local_stream.getAudioTracks()[0].id); | 381 local_stream.getAudioTracks()[0].id); |
| 389 eventOccured(); | 382 eventOccured(); |
| 390 } | 383 } |
| 391 | 384 |
| 392 // Add an expectation that the received video track is removed from | 385 // Add an expectation that the received video track is removed from |
| 393 // gFirstConnection. | 386 // gFirstConnection. |
| 394 addExpectedEvent(); | 387 addExpectedEvent(); |
| 395 remote_stream_1.onremovetrack = function() { | 388 remote_stream_1.onremovetrack = function() { |
| 396 eventOccured(); | 389 eventOccured(); |
| 397 } | 390 } |
| 398 | 391 |
| 399 // Add an expected event that onaddtrack will be called on the remote | 392 // Add an expected event that onaddtrack will be called on the remote |
| 400 // mediastream received on gSecondConnection when the audio track is | 393 // mediastream received on gSecondConnection when the audio track is |
| 401 // received. | 394 // received. |
| 402 remote_stream_2 = gSecondConnection.getRemoteStreams()[0]; | 395 remote_stream_2 = gSecondConnection.getRemoteStreams()[0]; |
| 403 addExpectedEvent(); | 396 addExpectedEvent(); |
| 404 remote_stream_2.onaddtrack = function() { | 397 remote_stream_2.onaddtrack = function() { |
| 405 expectEquals(remote_stream_2.getAudioTracks()[0].id, | 398 assertEquals(remote_stream_2.getAudioTracks()[0].id, |
| 406 local_stream.getAudioTracks()[0].id); | 399 local_stream.getAudioTracks()[0].id); |
| 407 eventOccured(); | 400 eventOccured(); |
| 408 } | 401 } |
| 409 | 402 |
| 410 // Add an expectation that the received video track is removed from | 403 // Add an expectation that the received video track is removed from |
| 411 // gSecondConnection. | 404 // gSecondConnection. |
| 412 addExpectedEvent(); | 405 addExpectedEvent(); |
| 413 remote_stream_2.onremovetrack = function() { | 406 remote_stream_2.onremovetrack = function() { |
| 414 eventOccured(); | 407 eventOccured(); |
| 415 } | 408 } |
| 416 // When all the above events have occurred- the test pass. | 409 // When all the above events have occurred- the test pass. |
| 417 setAllEventsOccuredHandler(function() { document.title = 'OK'; }); | 410 setAllEventsOccuredHandler(reportTestSuccess); |
| 418 | 411 |
| 419 local_stream.addTrack(gLocalStream.getAudioTracks()[0]); | 412 local_stream.addTrack(gLocalStream.getAudioTracks()[0]); |
| 420 local_stream.removeTrack(local_stream.getVideoTracks()[0]); | 413 local_stream.removeTrack(local_stream.getVideoTracks()[0]); |
| 421 negotiate(); | 414 negotiate(); |
| 422 }); | 415 }); |
| 423 } | 416 } |
| 424 | 417 |
| 425 // This function is used for setting up a test that: | 418 // This function is used for setting up a test that: |
| 426 // 1. Creates a data channel on |gFirstConnection| and sends data to | 419 // 1. Creates a data channel on |gFirstConnection| and sends data to |
| 427 // |gSecondConnection|. | 420 // |gSecondConnection|. |
| 428 // 2. When data is received on |gSecondConnection| a message | 421 // 2. When data is received on |gSecondConnection| a message |
| 429 // is sent to |gFirstConnection|. | 422 // is sent to |gFirstConnection|. |
| 430 // 3. When data is received on |gFirstConnection|, the data | 423 // 3. When data is received on |gFirstConnection|, the data |
| 431 // channel is closed. The test passes when the state transition completes. | 424 // channel is closed. The test passes when the state transition completes. |
| 432 function setupDataChannel(params) { | 425 function setupDataChannel(params) { |
| 433 var sendDataString = "send some text on a data channel." | 426 var sendDataString = "send some text on a data channel." |
| 434 firstDataChannel = gFirstConnection.createDataChannel( | 427 firstDataChannel = gFirstConnection.createDataChannel( |
| 435 "sendDataChannel", params); | 428 "sendDataChannel", params); |
| 436 expectEquals('connecting', firstDataChannel.readyState); | 429 assertEquals('connecting', firstDataChannel.readyState); |
| 437 | 430 |
| 438 // When |firstDataChannel| transition to open state, send a text string. | 431 // When |firstDataChannel| transition to open state, send a text string. |
| 439 firstDataChannel.onopen = function() { | 432 firstDataChannel.onopen = function() { |
| 440 expectEquals('open', firstDataChannel.readyState); | 433 assertEquals('open', firstDataChannel.readyState); |
| 441 firstDataChannel.send(sendDataString); | 434 firstDataChannel.send(sendDataString); |
| 442 } | 435 } |
| 443 | 436 |
| 444 // When |firstDataChannel| receive a message, close the channel and | 437 // When |firstDataChannel| receive a message, close the channel and |
| 445 // initiate a new offer/answer exchange to complete the closure. | 438 // initiate a new offer/answer exchange to complete the closure. |
| 446 firstDataChannel.onmessage = function(event) { | 439 firstDataChannel.onmessage = function(event) { |
| 447 expectEquals(event.data, sendDataString); | 440 assertEquals(event.data, sendDataString); |
| 448 firstDataChannel.close(); | 441 firstDataChannel.close(); |
| 449 negotiate(); | 442 negotiate(); |
| 450 } | 443 } |
| 451 | 444 |
| 452 // When |firstDataChannel| transition to closed state, the test pass. | 445 // When |firstDataChannel| transition to closed state, the test pass. |
| 446 // TODO(phoglund): This is flaky, at least in the setupLegacyCall case. |
| 447 // See http://crbug.com/350388. |
| 453 addExpectedEvent(); | 448 addExpectedEvent(); |
| 454 firstDataChannel.onclose = function() { | 449 firstDataChannel.onclose = function() { |
| 455 expectEquals('closed', firstDataChannel.readyState); | 450 assertEquals('closed', firstDataChannel.readyState); |
| 456 eventOccured(); | 451 eventOccured(); |
| 457 } | 452 } |
| 458 | 453 |
| 459 // Event handler for when |gSecondConnection| receive a new dataChannel. | 454 // Event handler for when |gSecondConnection| receive a new dataChannel. |
| 460 gSecondConnection.ondatachannel = function (event) { | 455 gSecondConnection.ondatachannel = function (event) { |
| 461 var secondDataChannel = event.channel; | 456 var secondDataChannel = event.channel; |
| 462 | 457 |
| 463 // When |secondDataChannel| receive a message, send a message back. | 458 // When |secondDataChannel| receive a message, send a message back. |
| 464 secondDataChannel.onmessage = function(event) { | 459 secondDataChannel.onmessage = function(event) { |
| 465 expectEquals(event.data, sendDataString); | 460 assertEquals(event.data, sendDataString); |
| 466 expectEquals('open', secondDataChannel.readyState); | 461 assertEquals('open', secondDataChannel.readyState); |
| 467 secondDataChannel.send(sendDataString); | 462 secondDataChannel.send(sendDataString); |
| 468 } | 463 } |
| 469 } | 464 } |
| 470 } | 465 } |
| 471 | 466 |
| 472 // SCTP data channel setup is slightly different then RTP based | 467 // SCTP data channel setup is slightly different then RTP based |
| 473 // channels. Due to a bug in libjingle, we can't send data immediately | 468 // channels. Due to a bug in libjingle, we can't send data immediately |
| 474 // after channel becomes open. So for that reason in SCTP, | 469 // after channel becomes open. So for that reason in SCTP, |
| 475 // we are sending data from second channel, when ondatachannel event is | 470 // we are sending data from second channel, when ondatachannel event is |
| 476 // received. So data flow happens 2 -> 1 -> 2. | 471 // received. So data flow happens 2 -> 1 -> 2. |
| 477 function setupSctpDataChannel(params) { | 472 function setupSctpDataChannel(params) { |
| 478 var sendDataString = "send some text on a data channel." | 473 var sendDataString = "send some text on a data channel." |
| 479 firstDataChannel = gFirstConnection.createDataChannel( | 474 firstDataChannel = gFirstConnection.createDataChannel( |
| 480 "sendDataChannel", params); | 475 "sendDataChannel", params); |
| 481 expectEquals('connecting', firstDataChannel.readyState); | 476 assertEquals('connecting', firstDataChannel.readyState); |
| 482 | 477 |
| 483 // When |firstDataChannel| transition to open state, send a text string. | 478 // When |firstDataChannel| transition to open state, send a text string. |
| 484 firstDataChannel.onopen = function() { | 479 firstDataChannel.onopen = function() { |
| 485 expectEquals('open', firstDataChannel.readyState); | 480 assertEquals('open', firstDataChannel.readyState); |
| 486 } | 481 } |
| 487 | 482 |
| 488 // When |firstDataChannel| receive a message, send message back. | 483 // When |firstDataChannel| receive a message, send message back. |
| 489 // initiate a new offer/answer exchange to complete the closure. | 484 // initiate a new offer/answer exchange to complete the closure. |
| 490 firstDataChannel.onmessage = function(event) { | 485 firstDataChannel.onmessage = function(event) { |
| 491 expectEquals('open', firstDataChannel.readyState); | 486 assertEquals('open', firstDataChannel.readyState); |
| 492 expectEquals(event.data, sendDataString); | 487 assertEquals(event.data, sendDataString); |
| 493 firstDataChannel.send(sendDataString); | 488 firstDataChannel.send(sendDataString); |
| 494 } | 489 } |
| 495 | 490 |
| 496 | 491 |
| 497 // Event handler for when |gSecondConnection| receive a new dataChannel. | 492 // Event handler for when |gSecondConnection| receive a new dataChannel. |
| 498 gSecondConnection.ondatachannel = function (event) { | 493 gSecondConnection.ondatachannel = function (event) { |
| 499 var secondDataChannel = event.channel; | 494 var secondDataChannel = event.channel; |
| 500 secondDataChannel.onopen = function() { | 495 secondDataChannel.onopen = function() { |
| 501 secondDataChannel.send(sendDataString); | 496 secondDataChannel.send(sendDataString); |
| 502 } | 497 } |
| 503 | 498 |
| 504 // When |secondDataChannel| receive a message, close the channel and | 499 // When |secondDataChannel| receive a message, close the channel and |
| 505 // initiate a new offer/answer exchange to complete the closure. | 500 // initiate a new offer/answer exchange to complete the closure. |
| 506 secondDataChannel.onmessage = function(event) { | 501 secondDataChannel.onmessage = function(event) { |
| 507 expectEquals(event.data, sendDataString); | 502 assertEquals(event.data, sendDataString); |
| 508 expectEquals('open', secondDataChannel.readyState); | 503 assertEquals('open', secondDataChannel.readyState); |
| 509 secondDataChannel.close(); | 504 secondDataChannel.close(); |
| 510 negotiate(); | 505 negotiate(); |
| 511 } | 506 } |
| 512 | 507 |
| 513 // When |secondDataChannel| transition to closed state, the test pass. | 508 // When |secondDataChannel| transition to closed state, the test pass. |
| 514 addExpectedEvent(); | 509 addExpectedEvent(); |
| 515 secondDataChannel.onclose = function() { | 510 secondDataChannel.onclose = function() { |
| 516 expectEquals('closed', secondDataChannel.readyState); | 511 assertEquals('closed', secondDataChannel.readyState); |
| 517 eventOccured(); | 512 eventOccured(); |
| 518 } | 513 } |
| 519 } | 514 } |
| 520 } | 515 } |
| 521 | 516 |
| 522 // Test call with a stream that has been created by getUserMedia, clone | 517 // Test call with a stream that has been created by getUserMedia, clone |
| 523 // the stream to a cloned stream, send them via the same peer connection. | 518 // the stream to a cloned stream, send them via the same peer connection. |
| 524 function addTwoMediaStreamsToOneConnection() { | 519 function addTwoMediaStreamsToOneConnection() { |
| 525 createConnections(null); | 520 createConnections(null); |
| 526 navigator.webkitGetUserMedia({audio: true, video: true}, | 521 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 527 CloneStreamAndAddTwoStreamstoOneConnection, printGetUserMediaError); | 522 CloneStreamAndAddTwoStreamstoOneConnection, printGetUserMediaError); |
| 528 } | 523 } |
| 529 | 524 |
| 530 function onToneChange(tone) { | 525 function onToneChange(tone) { |
| 531 gSentTones += tone.tone; | 526 gSentTones += tone.tone; |
| 532 document.title = gSentTones; | |
| 533 } | 527 } |
| 534 | 528 |
| 535 function createConnections(constraints) { | 529 function createConnections(constraints) { |
| 536 gFirstConnection = createConnection(constraints, 'remote-view-1'); | 530 gFirstConnection = createConnection(constraints, 'remote-view-1'); |
| 537 expectEquals('stable', gFirstConnection.signalingState); | 531 assertEquals('stable', gFirstConnection.signalingState); |
| 538 | 532 |
| 539 gSecondConnection = createConnection(constraints, 'remote-view-2'); | 533 gSecondConnection = createConnection(constraints, 'remote-view-2'); |
| 540 expectEquals('stable', gSecondConnection.signalingState); | 534 assertEquals('stable', gSecondConnection.signalingState); |
| 541 } | 535 } |
| 542 | 536 |
| 543 function createConnection(constraints, remoteView) { | 537 function createConnection(constraints, remoteView) { |
| 544 var pc = new webkitRTCPeerConnection(null, constraints); | 538 var pc = new webkitRTCPeerConnection(null, constraints); |
| 545 pc.onaddstream = function(event) { | 539 pc.onaddstream = function(event) { |
| 546 onRemoteStream(event, remoteView); | 540 onRemoteStream(event, remoteView); |
| 547 } | 541 } |
| 548 return pc; | 542 return pc; |
| 549 } | 543 } |
| 550 | 544 |
| 551 function displayAndRemember(localStream) { | 545 function displayAndRemember(localStream) { |
| 552 var localStreamUrl = URL.createObjectURL(localStream); | 546 var localStreamUrl = URL.createObjectURL(localStream); |
| 553 $('local-view').src = localStreamUrl; | 547 $('local-view').src = localStreamUrl; |
| 554 | 548 |
| 555 gLocalStream = localStream; | 549 gLocalStream = localStream; |
| 556 } | 550 } |
| 557 | 551 |
| 558 // Called if getUserMedia fails. | 552 // Called if getUserMedia fails. |
| 559 function printGetUserMediaError(error) { | 553 function printGetUserMediaError(error) { |
| 560 document.title = 'getUserMedia request failed:'; | 554 var message = 'getUserMedia request unexpectedly failed:'; |
| 561 if (error.constraintName) | 555 if (error.constraintName) |
| 562 document.title += ' could not satisfy constraint ' + error.constraintName; | 556 message += ' could not satisfy constraint ' + error.constraintName; |
| 563 else | 557 else |
| 564 document.title += ' devices not working/user denied access.'; | 558 message += ' devices not working/user denied access.'; |
| 565 console.log(document.title); | 559 failTest(message); |
| 566 } | 560 } |
| 567 | 561 |
| 568 // Called if getUserMedia succeeds and we want to send from both connections. | 562 // Called if getUserMedia succeeds and we want to send from both connections. |
| 569 function addStreamToBothConnectionsAndNegotiate(localStream) { | 563 function addStreamToBothConnectionsAndNegotiate(localStream) { |
| 570 displayAndRemember(localStream); | 564 displayAndRemember(localStream); |
| 571 gFirstConnection.addStream(localStream); | 565 gFirstConnection.addStream(localStream); |
| 572 gSecondConnection.addStream(localStream); | 566 gSecondConnection.addStream(localStream); |
| 573 negotiate(); | 567 negotiate(); |
| 574 } | 568 } |
| 575 | 569 |
| 576 // Called if getUserMedia succeeds when we want to send from one connection. | 570 // Called if getUserMedia succeeds when we want to send from one connection. |
| 577 function addStreamToTheFirstConnectionAndNegotiate(localStream) { | 571 function addStreamToTheFirstConnectionAndNegotiate(localStream) { |
| 578 displayAndRemember(localStream); | 572 displayAndRemember(localStream); |
| 579 gFirstConnection.addStream(localStream); | 573 gFirstConnection.addStream(localStream); |
| 580 negotiate(); | 574 negotiate(); |
| 581 } | 575 } |
| 582 | 576 |
| 583 function verifyHasOneAudioAndVideoTrack(stream) { | 577 function verifyHasOneAudioAndVideoTrack(stream) { |
| 584 expectEquals(1, stream.getAudioTracks().length); | 578 assertEquals(1, stream.getAudioTracks().length); |
| 585 expectEquals(1, stream.getVideoTracks().length); | 579 assertEquals(1, stream.getVideoTracks().length); |
| 586 } | 580 } |
| 587 | 581 |
| 588 // Called if getUserMedia succeeds, then clone the stream, send two streams | 582 // Called if getUserMedia succeeds, then clone the stream, send two streams |
| 589 // from one peer connection. | 583 // from one peer connection. |
| 590 function CloneStreamAndAddTwoStreamstoOneConnection(localStream) { | 584 function CloneStreamAndAddTwoStreamstoOneConnection(localStream) { |
| 591 displayAndRemember(localStream); | 585 displayAndRemember(localStream); |
| 592 | 586 |
| 593 var clonedStream = null; | 587 var clonedStream = null; |
| 594 if (typeof localStream.clone === "function") { | 588 if (typeof localStream.clone === "function") { |
| 595 clonedStream = localStream.clone(); | 589 clonedStream = localStream.clone(); |
| 596 } else { | 590 } else { |
| 597 clonedStream = new webkitMediaStream(localStream); | 591 clonedStream = new webkitMediaStream(localStream); |
| 598 } | 592 } |
| 599 | 593 |
| 600 gFirstConnection.addStream(localStream); | 594 gFirstConnection.addStream(localStream); |
| 601 gFirstConnection.addStream(clonedStream); | 595 gFirstConnection.addStream(clonedStream); |
| 602 | 596 |
| 603 // Verify the local streams are correct. | 597 // Verify the local streams are correct. |
| 604 expectEquals(2, gFirstConnection.getLocalStreams().length); | 598 assertEquals(2, gFirstConnection.getLocalStreams().length); |
| 605 verifyHasOneAudioAndVideoTrack(gFirstConnection.getLocalStreams()[0]); | 599 verifyHasOneAudioAndVideoTrack(gFirstConnection.getLocalStreams()[0]); |
| 606 verifyHasOneAudioAndVideoTrack(gFirstConnection.getLocalStreams()[1]); | 600 verifyHasOneAudioAndVideoTrack(gFirstConnection.getLocalStreams()[1]); |
| 607 | 601 |
| 608 // The remote side should receive two streams. After that, verify the | 602 // The remote side should receive two streams. After that, verify the |
| 609 // remote side has the correct number of streams and tracks. | 603 // remote side has the correct number of streams and tracks. |
| 610 addExpectedEvent(); | 604 addExpectedEvent(); |
| 611 addExpectedEvent(); | 605 addExpectedEvent(); |
| 612 gSecondConnection.onaddstream = function(event) { | 606 gSecondConnection.onaddstream = function(event) { |
| 613 eventOccured(); | 607 eventOccured(); |
| 614 } | 608 } |
| 615 setAllEventsOccuredHandler(function() { | 609 setAllEventsOccuredHandler(function() { |
| 616 // Negotiation complete, verify remote streams on the receiving side. | 610 // Negotiation complete, verify remote streams on the receiving side. |
| 617 expectEquals(2, gSecondConnection.getRemoteStreams().length); | 611 assertEquals(2, gSecondConnection.getRemoteStreams().length); |
| 618 verifyHasOneAudioAndVideoTrack(gSecondConnection.getRemoteStreams()[0]); | 612 verifyHasOneAudioAndVideoTrack(gSecondConnection.getRemoteStreams()[0]); |
| 619 verifyHasOneAudioAndVideoTrack(gSecondConnection.getRemoteStreams()[1]); | 613 verifyHasOneAudioAndVideoTrack(gSecondConnection.getRemoteStreams()[1]); |
| 620 | 614 |
| 621 document.title = "OK"; | 615 reportTestSuccess(); |
| 622 }); | 616 }); |
| 623 | 617 |
| 624 negotiate(); | 618 negotiate(); |
| 625 } | 619 } |
| 626 | 620 |
| 627 // Called if getUserMedia succeeds when we want to send a modified | 621 // Called if getUserMedia succeeds when we want to send a modified |
| 628 // MediaStream. A new MediaStream is created and the video track from | 622 // MediaStream. A new MediaStream is created and the video track from |
| 629 // |localStream| is added. | 623 // |localStream| is added. |
| 630 function createNewVideoStreamAndAddToBothConnections(localStream) { | 624 function createNewVideoStreamAndAddToBothConnections(localStream) { |
| 631 displayAndRemember(localStream); | 625 displayAndRemember(localStream); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 651 | 645 |
| 652 caller.createOffer( | 646 caller.createOffer( |
| 653 function (offer) { | 647 function (offer) { |
| 654 onOfferCreated(offer, caller, callee); | 648 onOfferCreated(offer, caller, callee); |
| 655 }); | 649 }); |
| 656 } | 650 } |
| 657 | 651 |
| 658 function onOfferCreated(offer, caller, callee) { | 652 function onOfferCreated(offer, caller, callee) { |
| 659 offer.sdp = maybeForceIsac16K(transformSdp(offer.sdp)); | 653 offer.sdp = maybeForceIsac16K(transformSdp(offer.sdp)); |
| 660 caller.setLocalDescription(offer, function() { | 654 caller.setLocalDescription(offer, function() { |
| 661 expectEquals('have-local-offer', caller.signalingState); | 655 assertEquals('have-local-offer', caller.signalingState); |
| 662 receiveOffer(offer.sdp, caller, callee); | 656 receiveOffer(offer.sdp, caller, callee); |
| 663 }, onLocalDescriptionError); | 657 }, onLocalDescriptionError); |
| 664 } | 658 } |
| 665 | 659 |
| 666 function receiveOffer(offerSdp, caller, callee) { | 660 function receiveOffer(offerSdp, caller, callee) { |
| 667 console.log("Receiving offer..."); | 661 console.log("Receiving offer..."); |
| 668 offerSdp = transformRemoteSdp(offerSdp); | 662 offerSdp = transformRemoteSdp(offerSdp); |
| 669 | 663 |
| 670 var parsedOffer = new RTCSessionDescription({ type: 'offer', | 664 var parsedOffer = new RTCSessionDescription({ type: 'offer', |
| 671 sdp: offerSdp }); | 665 sdp: offerSdp }); |
| 672 callee.setRemoteDescription(parsedOffer); | 666 callee.setRemoteDescription(parsedOffer); |
| 673 callee.createAnswer(function (answer) { | 667 callee.createAnswer(function (answer) { |
| 674 onAnswerCreated(answer, caller, callee); | 668 onAnswerCreated(answer, caller, callee); |
| 675 }); | 669 }); |
| 676 expectEquals('have-remote-offer', callee.signalingState); | 670 assertEquals('have-remote-offer', callee.signalingState); |
| 677 } | 671 } |
| 678 | 672 |
| 679 function removeMsid(offerSdp) { | 673 function removeMsid(offerSdp) { |
| 680 offerSdp = offerSdp.replace(/a=msid-semantic.*\r\n/g, ''); | 674 offerSdp = offerSdp.replace(/a=msid-semantic.*\r\n/g, ''); |
| 681 offerSdp = offerSdp.replace('a=mid:audio\r\n', ''); | 675 offerSdp = offerSdp.replace('a=mid:audio\r\n', ''); |
| 682 offerSdp = offerSdp.replace('a=mid:video\r\n', ''); | 676 offerSdp = offerSdp.replace('a=mid:video\r\n', ''); |
| 683 offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, ''); | 677 offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, ''); |
| 684 return offerSdp; | 678 return offerSdp; |
| 685 } | 679 } |
| 686 | 680 |
| 687 function removeVideoCodec(offerSdp) { | 681 function removeVideoCodec(offerSdp) { |
| 688 offerSdp = offerSdp.replace('a=rtpmap:100 VP8/90000\r\n', | 682 offerSdp = offerSdp.replace('a=rtpmap:100 VP8/90000\r\n', |
| 689 'a=rtpmap:100 XVP8/90000\r\n'); | 683 'a=rtpmap:100 XVP8/90000\r\n'); |
| 690 return offerSdp; | 684 return offerSdp; |
| 691 } | 685 } |
| 692 | 686 |
| 693 function removeCrypto(offerSdp) { | 687 function removeCrypto(offerSdp) { |
| 694 offerSdp = offerSdp.replace(/a=crypto.*\r\n/g, 'a=Xcrypto\r\n'); | 688 offerSdp = offerSdp.replace(/a=crypto.*\r\n/g, 'a=Xcrypto\r\n'); |
| 695 offerSdp = offerSdp.replace(/a=fingerprint.*\r\n/g, ''); | 689 offerSdp = offerSdp.replace(/a=fingerprint.*\r\n/g, ''); |
| 696 return offerSdp; | 690 return offerSdp; |
| 697 } | 691 } |
| 698 | 692 |
| 699 function addBandwithControl(offerSdp) { | 693 function addBandwithControl(offerSdp) { |
| 700 offerSdp = offerSdp.replace('a=mid:audio\r\n', 'a=mid:audio\r\n'+ | 694 offerSdp = offerSdp.replace('a=mid:audio\r\n', 'a=mid:audio\r\n'+ |
| 701 'b=AS:16\r\n'); | 695 'b=AS:16\r\n'); |
| 702 offerSdp = offerSdp.replace('a=mid:video\r\n', 'a=mid:video\r\n'+ | 696 offerSdp = offerSdp.replace('a=mid:video\r\n', 'a=mid:video\r\n'+ |
| 703 'b=AS:512\r\n'); | 697 'b=AS:512\r\n'); |
| 704 return offerSdp; | 698 return offerSdp; |
| 705 } | 699 } |
| 706 | 700 |
| 707 function removeBundle(sdp) { | 701 function removeBundle(sdp) { |
| 708 return sdp.replace(/a=group:BUNDLE .*\r\n/g, ''); | 702 return sdp.replace(/a=group:BUNDLE .*\r\n/g, ''); |
| 709 } | 703 } |
| 710 | 704 |
| 711 function useGice(sdp) { | 705 function useGice(sdp) { |
| 712 sdp = sdp.replace(/t=.*\r\n/g, function(subString) { | 706 sdp = sdp.replace(/t=.*\r\n/g, function(subString) { |
| 713 return subString + 'a=ice-options:google-ice\r\n'; | 707 return subString + 'a=ice-options:google-ice\r\n'; |
| 714 }); | 708 }); |
| 715 sdp = sdp.replace(/a=ice-ufrag:.*\r\n/g, | 709 sdp = sdp.replace(/a=ice-ufrag:.*\r\n/g, |
| 716 'a=ice-ufrag:' + EXTERNAL_GICE_UFRAG + '\r\n'); | 710 'a=ice-ufrag:' + EXTERNAL_GICE_UFRAG + '\r\n'); |
| 717 sdp = sdp.replace(/a=ice-pwd:.*\r\n/g, | 711 sdp = sdp.replace(/a=ice-pwd:.*\r\n/g, |
| 718 'a=ice-pwd:' + EXTERNAL_GICE_PWD + '\r\n'); | 712 'a=ice-pwd:' + EXTERNAL_GICE_PWD + '\r\n'); |
| 719 return sdp; | 713 return sdp; |
| 720 } | 714 } |
| 721 | 715 |
| 722 function useExternalSdes(sdp) { | 716 function useExternalSdes(sdp) { |
| 723 // Remove current crypto specification. | 717 // Remove current crypto specification. |
| 724 sdp = sdp.replace(/a=crypto.*\r\n/g, ''); | 718 sdp = sdp.replace(/a=crypto.*\r\n/g, ''); |
| 725 sdp = sdp.replace(/a=fingerprint.*\r\n/g, ''); | 719 sdp = sdp.replace(/a=fingerprint.*\r\n/g, ''); |
| 726 // Add external crypto. This is not compatible with |removeMsid|. | 720 // Add external crypto. This is not compatible with |removeMsid|. |
| 727 sdp = sdp.replace(/a=mid:(\w+)\r\n/g, function(subString, group) { | 721 sdp = sdp.replace(/a=mid:(\w+)\r\n/g, function(subString, group) { |
| 728 return subString + EXTERNAL_SDES_LINES[group] + '\r\n'; | 722 return subString + EXTERNAL_SDES_LINES[group] + '\r\n'; |
| 729 }); | 723 }); |
| 730 return sdp; | 724 return sdp; |
| 731 } | 725 } |
| 732 | 726 |
| 733 function onAnswerCreated(answer, caller, callee) { | 727 function onAnswerCreated(answer, caller, callee) { |
| 734 answer.sdp = maybeForceIsac16K(transformSdp(answer.sdp)); | 728 answer.sdp = maybeForceIsac16K(transformSdp(answer.sdp)); |
| 735 callee.setLocalDescription(answer); | 729 callee.setLocalDescription(answer); |
| 736 expectEquals('stable', callee.signalingState); | 730 assertEquals('stable', callee.signalingState); |
| 737 receiveAnswer(answer.sdp, caller); | 731 receiveAnswer(answer.sdp, caller); |
| 738 } | 732 } |
| 739 | 733 |
| 740 function receiveAnswer(answerSdp, caller) { | 734 function receiveAnswer(answerSdp, caller) { |
| 741 console.log("Receiving answer..."); | 735 console.log("Receiving answer..."); |
| 742 answerSdp = transformRemoteSdp(answerSdp); | 736 answerSdp = transformRemoteSdp(answerSdp); |
| 743 var parsedAnswer = new RTCSessionDescription({ type: 'answer', | 737 var parsedAnswer = new RTCSessionDescription({ type: 'answer', |
| 744 sdp: answerSdp }); | 738 sdp: answerSdp }); |
| 745 caller.setRemoteDescription(parsedAnswer); | 739 caller.setRemoteDescription(parsedAnswer); |
| 746 expectEquals('stable', caller.signalingState); | 740 assertEquals('stable', caller.signalingState); |
| 747 } | 741 } |
| 748 | 742 |
| 749 function connectOnIceCandidate(caller, callee) { | 743 function connectOnIceCandidate(caller, callee) { |
| 750 caller.onicecandidate = function(event) { onIceCandidate(event, callee); } | 744 caller.onicecandidate = function(event) { onIceCandidate(event, callee); } |
| 751 callee.onicecandidate = function(event) { onIceCandidate(event, caller); } | 745 callee.onicecandidate = function(event) { onIceCandidate(event, caller); } |
| 752 } | 746 } |
| 753 | 747 |
| 754 function addGiceCredsToCandidate(candidate) { | 748 function addGiceCredsToCandidate(candidate) { |
| 755 return candidate.trimRight() + | 749 return candidate.trimRight() + |
| 756 ' username ' + EXTERNAL_GICE_UFRAG + ' password ' + EXTERNAL_GICE_PWD; | 750 ' username ' + EXTERNAL_GICE_UFRAG + ' password ' + EXTERNAL_GICE_PWD; |
| 757 } | 751 } |
| 758 | 752 |
| 759 function onIceCandidate(event, target) { | 753 function onIceCandidate(event, target) { |
| 760 if (event.candidate) { | 754 if (event.candidate) { |
| 761 console.log("onIceCandidate, candidate is:" + event.candidate.candidate); | 755 console.log("onIceCandidate, candidate is:" + event.candidate.candidate); |
| 762 var candidate = new RTCIceCandidate(event.candidate); | 756 var candidate = new RTCIceCandidate(event.candidate); |
| 763 candidate.candidate = transformCandidate(candidate.candidate); | 757 candidate.candidate = transformCandidate(candidate.candidate); |
| 764 target.addIceCandidate(candidate); | 758 target.addIceCandidate(candidate); |
| 765 } | 759 } |
| 766 } | 760 } |
| 767 | 761 |
| 768 function onRemoteStream(e, target) { | 762 function onRemoteStream(e, target) { |
| 769 console.log("Receiving remote stream..."); | 763 console.log("Receiving remote stream..."); |
| 770 if (gTestWithoutMsid && e.stream.id != "default") { | 764 if (gTestWithoutMsid && e.stream.id != "default") { |
| 771 document.title = 'a default remote stream was expected but instead ' + | 765 failTest('a default remote stream was expected but instead ' + |
| 772 e.stream.id + ' was received.'; | 766 e.stream.id + ' was received.'); |
| 773 return; | |
| 774 } | 767 } |
| 775 gRemoteStreams[target] = e.stream; | 768 gRemoteStreams[target] = e.stream; |
| 776 var remoteStreamUrl = URL.createObjectURL(e.stream); | 769 var remoteStreamUrl = URL.createObjectURL(e.stream); |
| 777 var remoteVideo = $(target); | 770 var remoteVideo = $(target); |
| 778 remoteVideo.src = remoteStreamUrl; | 771 remoteVideo.src = remoteStreamUrl; |
| 779 } | 772 } |
| 780 | 773 |
| 781 </script> | 774 </script> |
| 782 </head> | 775 </head> |
| 783 <body> | 776 <body> |
| (...skipping 22 matching lines...) Expand all Loading... |
| 806 <td><canvas width="320" height="240" id="remote-view-2-canvas" | 799 <td><canvas width="320" height="240" id="remote-view-2-canvas" |
| 807 style="display:none"></canvas></td> | 800 style="display:none"></canvas></td> |
| 808 <td><canvas width="320" height="240" id="remote-view-3-canvas" | 801 <td><canvas width="320" height="240" id="remote-view-3-canvas" |
| 809 style="display:none"></canvas></td> | 802 style="display:none"></canvas></td> |
| 810 <td><canvas width="320" height="240" id="remote-view-4-canvas" | 803 <td><canvas width="320" height="240" id="remote-view-4-canvas" |
| 811 style="display:none"></canvas></td> | 804 style="display:none"></canvas></td> |
| 812 </tr> | 805 </tr> |
| 813 </table> | 806 </table> |
| 814 </body> | 807 </body> |
| 815 </html> | 808 </html> |
| OLD | NEW |