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 |