| OLD | NEW |
| 1 /** | 1 /** |
| 2 * Copyright 2014 The Chromium Authors. All rights reserved. | 2 * Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The one and only peer connection in this page. | 8 * The one and only peer connection in this page. |
| 9 * @private | 9 * @private |
| 10 */ | 10 */ |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 gPeerConnection = createPeerConnection_(); | 37 gPeerConnection = createPeerConnection_(); |
| 38 returnToTest('ok-peerconnection-created'); | 38 returnToTest('ok-peerconnection-created'); |
| 39 } | 39 } |
| 40 | 40 |
| 41 /** | 41 /** |
| 42 * Asks this page to create a local offer. | 42 * Asks this page to create a local offer. |
| 43 * | 43 * |
| 44 * Returns a string on the format ok-(JSON encoded session description). | 44 * Returns a string on the format ok-(JSON encoded session description). |
| 45 * | 45 * |
| 46 * @param {!Object} constraints Any createOffer constraints. | 46 * @param {!Object} constraints Any createOffer constraints. |
| 47 * @param {string} videoCodec If not null, promotes the specified codec to be |
| 48 * the default video codec, e.g. the first one in the list on the 'm=video' |
| 49 * SDP offer line. |videoCodec| is the case-sensitive codec name, e.g. |
| 50 * 'VP8' or 'H264'. |
| 47 */ | 51 */ |
| 48 function createLocalOffer(constraints) { | 52 function createLocalOffer(constraints, videoCodec = null) { |
| 49 peerConnection_().createOffer( | 53 peerConnection_().createOffer( |
| 50 function(localOffer) { | 54 function(localOffer) { |
| 51 success_('createOffer'); | 55 success('createOffer'); |
| 56 |
| 52 setLocalDescription(peerConnection, localOffer); | 57 setLocalDescription(peerConnection, localOffer); |
| 58 if (videoCodec !== null) |
| 59 localOffer.sdp = setSdpDefaultVideoCodec(localOffer.sdp, videoCodec); |
| 53 | 60 |
| 54 returnToTest('ok-' + JSON.stringify(localOffer)); | 61 returnToTest('ok-' + JSON.stringify(localOffer)); |
| 55 }, | 62 }, |
| 56 function(error) { failure_('createOffer', error); }, | 63 function(error) { failure('createOffer', error); }, |
| 57 constraints); | 64 constraints); |
| 58 } | 65 } |
| 59 | 66 |
| 60 /** | 67 /** |
| 61 * Asks this page to accept an offer and generate an answer. | 68 * Asks this page to accept an offer and generate an answer. |
| 62 * | 69 * |
| 63 * Returns a string on the format ok-(JSON encoded session description). | 70 * Returns a string on the format ok-(JSON encoded session description). |
| 64 * | 71 * |
| 65 * @param {!string} sessionDescJson A JSON-encoded session description of type | 72 * @param {!string} sessionDescJson A JSON-encoded session description of type |
| 66 * 'offer'. | 73 * 'offer'. |
| 67 * @param {!Object} constraints Any createAnswer constraints. | 74 * @param {!Object} constraints Any createAnswer constraints. |
| 68 */ | 75 */ |
| 69 function receiveOfferFromPeer(sessionDescJson, constraints) { | 76 function receiveOfferFromPeer(sessionDescJson, constraints) { |
| 70 offer = parseJson_(sessionDescJson); | 77 offer = parseJson_(sessionDescJson); |
| 71 if (!offer.type) | 78 if (!offer.type) |
| 72 failTest('Got invalid session description from peer: ' + sessionDescJson); | 79 failTest('Got invalid session description from peer: ' + sessionDescJson); |
| 73 if (offer.type != 'offer') | 80 if (offer.type != 'offer') |
| 74 failTest('Expected to receive offer from peer, got ' + offer.type); | 81 failTest('Expected to receive offer from peer, got ' + offer.type); |
| 75 | 82 |
| 76 var sessionDescription = new RTCSessionDescription(offer); | 83 var sessionDescription = new RTCSessionDescription(offer); |
| 77 peerConnection_().setRemoteDescription( | 84 peerConnection_().setRemoteDescription( |
| 78 sessionDescription, | 85 sessionDescription, |
| 79 function() { success_('setRemoteDescription'); }, | 86 function() { success('setRemoteDescription'); }, |
| 80 function(error) { failure_('setRemoteDescription', error); }); | 87 function(error) { failure('setRemoteDescription', error); }); |
| 81 | 88 |
| 82 peerConnection_().createAnswer( | 89 peerConnection_().createAnswer( |
| 83 function(answer) { | 90 function(answer) { |
| 84 success_('createAnswer'); | 91 success('createAnswer'); |
| 85 setLocalDescription(peerConnection, answer); | 92 setLocalDescription(peerConnection, answer); |
| 86 returnToTest('ok-' + JSON.stringify(answer)); | 93 returnToTest('ok-' + JSON.stringify(answer)); |
| 87 }, | 94 }, |
| 88 function(error) { failure_('createAnswer', error); }, | 95 function(error) { failure('createAnswer', error); }, |
| 89 constraints); | 96 constraints); |
| 90 } | 97 } |
| 91 | 98 |
| 92 /** | 99 /** |
| 100 * Verifies that the specified codec is the default video codec, e.g. the first |
| 101 * one in the list on the 'm=video' SDP answer line. If this is not the case, |
| 102 * |failure| occurs. |
| 103 * |
| 104 * @param {!string} sessionDescJson A JSON-encoded session description. |
| 105 * @param {!string} expectedVideoCodec The case-sensitive codec name, e.g. |
| 106 * 'VP8' or 'H264'. |
| 107 */ |
| 108 function verifyDefaultVideoCodec(sessionDescJson, expectedVideoCodec) { |
| 109 var sessionDesc = parseJson_(sessionDescJson); |
| 110 if (!sessionDesc.type) { |
| 111 failure('verifyDefaultVideoCodec', |
| 112 'Invalid session description: ' + sessionDescJson); |
| 113 } |
| 114 var defaultVideoCodec = getSdpDefaultVideoCodec(sessionDesc.sdp); |
| 115 if (defaultVideoCodec === null) { |
| 116 failure('verifyDefaultVideoCodec', |
| 117 'Could not determine default video codec.'); |
| 118 } |
| 119 if (expectedVideoCodec !== defaultVideoCodec) { |
| 120 failure('verifyDefaultVideoCodec', |
| 121 'Expected default video codec ' + expectedVideoCodec + |
| 122 ', got ' + defaultVideoCodec + '.'); |
| 123 } |
| 124 returnToTest('ok-verified'); |
| 125 } |
| 126 |
| 127 /** |
| 93 * Asks this page to accept an answer generated by the peer in response to a | 128 * Asks this page to accept an answer generated by the peer in response to a |
| 94 * previous offer by this page | 129 * previous offer by this page |
| 95 * | 130 * |
| 96 * Returns a string ok-accepted-answer on success. | 131 * Returns a string ok-accepted-answer on success. |
| 97 * | 132 * |
| 98 * @param {!string} sessionDescJson A JSON-encoded session description of type | 133 * @param {!string} sessionDescJson A JSON-encoded session description of type |
| 99 * 'answer'. | 134 * 'answer'. |
| 100 */ | 135 */ |
| 101 function receiveAnswerFromPeer(sessionDescJson) { | 136 function receiveAnswerFromPeer(sessionDescJson) { |
| 102 answer = parseJson_(sessionDescJson); | 137 answer = parseJson_(sessionDescJson); |
| 103 if (!answer.type) | 138 if (!answer.type) |
| 104 failTest('Got invalid session description from peer: ' + sessionDescJson); | 139 failTest('Got invalid session description from peer: ' + sessionDescJson); |
| 105 if (answer.type != 'answer') | 140 if (answer.type != 'answer') |
| 106 failTest('Expected to receive answer from peer, got ' + answer.type); | 141 failTest('Expected to receive answer from peer, got ' + answer.type); |
| 107 | 142 |
| 108 var sessionDescription = new RTCSessionDescription(answer); | 143 var sessionDescription = new RTCSessionDescription(answer); |
| 109 peerConnection_().setRemoteDescription( | 144 peerConnection_().setRemoteDescription( |
| 110 sessionDescription, | 145 sessionDescription, |
| 111 function() { | 146 function() { |
| 112 success_('setRemoteDescription'); | 147 success('setRemoteDescription'); |
| 113 returnToTest('ok-accepted-answer'); | 148 returnToTest('ok-accepted-answer'); |
| 114 }, | 149 }, |
| 115 function(error) { failure_('setRemoteDescription', error); }); | 150 function(error) { failure('setRemoteDescription', error); }); |
| 116 } | 151 } |
| 117 | 152 |
| 118 /** | 153 /** |
| 119 * Adds the local stream to the peer connection. You will have to re-negotiate | 154 * Adds the local stream to the peer connection. You will have to re-negotiate |
| 120 * the call for this to take effect in the call. | 155 * the call for this to take effect in the call. |
| 121 */ | 156 */ |
| 122 function addLocalStream() { | 157 function addLocalStream() { |
| 123 addLocalStreamToPeerConnection(peerConnection_()); | 158 addLocalStreamToPeerConnection(peerConnection_()); |
| 124 returnToTest('ok-added'); | 159 returnToTest('ok-added'); |
| 125 } | 160 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 if (!iceCandidates.length) | 222 if (!iceCandidates.length) |
| 188 throw failTest('Received invalid ICE candidate list from peer: ' + | 223 throw failTest('Received invalid ICE candidate list from peer: ' + |
| 189 iceCandidatesJson); | 224 iceCandidatesJson); |
| 190 | 225 |
| 191 iceCandidates.forEach(function(iceCandidate) { | 226 iceCandidates.forEach(function(iceCandidate) { |
| 192 if (!iceCandidate.candidate) | 227 if (!iceCandidate.candidate) |
| 193 failTest('Received invalid ICE candidate from peer: ' + | 228 failTest('Received invalid ICE candidate from peer: ' + |
| 194 iceCandidatesJson); | 229 iceCandidatesJson); |
| 195 | 230 |
| 196 peerConnection_().addIceCandidate(new RTCIceCandidate(iceCandidate, | 231 peerConnection_().addIceCandidate(new RTCIceCandidate(iceCandidate, |
| 197 function() { success_('addIceCandidate'); }, | 232 function() { success('addIceCandidate'); }, |
| 198 function(error) { failure_('addIceCandidate', error); } | 233 function(error) { failure('addIceCandidate', error); } |
| 199 )); | 234 )); |
| 200 }); | 235 }); |
| 201 | 236 |
| 202 returnToTest('ok-received-candidates'); | 237 returnToTest('ok-received-candidates'); |
| 203 } | 238 } |
| 204 | 239 |
| 205 /** | 240 /** |
| 206 * Sets the mute state of the selected media element. | 241 * Sets the mute state of the selected media element. |
| 207 * | 242 * |
| 208 * Returns ok-muted on success. | 243 * Returns ok-muted on success. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 } | 276 } |
| 242 | 277 |
| 243 /** @private */ | 278 /** @private */ |
| 244 function peerConnection_() { | 279 function peerConnection_() { |
| 245 if (gPeerConnection == null) | 280 if (gPeerConnection == null) |
| 246 throw failTest('Trying to use peer connection, but none was created.'); | 281 throw failTest('Trying to use peer connection, but none was created.'); |
| 247 return gPeerConnection; | 282 return gPeerConnection; |
| 248 } | 283 } |
| 249 | 284 |
| 250 /** @private */ | 285 /** @private */ |
| 251 function success_(method) { | |
| 252 debug(method + '(): success.'); | |
| 253 } | |
| 254 | |
| 255 /** @private */ | |
| 256 function failure_(method, error) { | |
| 257 throw failTest(method + '() failed: ' + JSON.stringify(error)); | |
| 258 } | |
| 259 | |
| 260 /** @private */ | |
| 261 function iceCallback_(event) { | 286 function iceCallback_(event) { |
| 262 if (event.candidate) | 287 if (event.candidate) |
| 263 gIceCandidates.push(event.candidate); | 288 gIceCandidates.push(event.candidate); |
| 264 } | 289 } |
| 265 | 290 |
| 266 /** @private */ | 291 /** @private */ |
| 267 function setLocalDescription(peerConnection, sessionDescription) { | 292 function setLocalDescription(peerConnection, sessionDescription) { |
| 268 if (sessionDescription.sdp.search('a=crypto') != -1 || | 293 if (sessionDescription.sdp.search('a=crypto') != -1 || |
| 269 sessionDescription.sdp.search('a=fingerprint') != -1) | 294 sessionDescription.sdp.search('a=fingerprint') != -1) |
| 270 gHasSeenCryptoInSdp = 'crypto-seen'; | 295 gHasSeenCryptoInSdp = 'crypto-seen'; |
| 271 | 296 |
| 272 peerConnection.setLocalDescription( | 297 peerConnection.setLocalDescription( |
| 273 sessionDescription, | 298 sessionDescription, |
| 274 function() { success_('setLocalDescription'); }, | 299 function() { success('setLocalDescription'); }, |
| 275 function(error) { failure_('setLocalDescription', error); }); | 300 function(error) { failure('setLocalDescription', error); }); |
| 276 } | 301 } |
| 277 | 302 |
| 278 /** @private */ | 303 /** @private */ |
| 279 function addStreamCallback_(event) { | 304 function addStreamCallback_(event) { |
| 280 debug('Receiving remote stream...'); | 305 debug('Receiving remote stream...'); |
| 281 var videoTag = document.getElementById('remote-view'); | 306 var videoTag = document.getElementById('remote-view'); |
| 282 attachMediaStream(videoTag, event.stream); | 307 attachMediaStream(videoTag, event.stream); |
| 283 } | 308 } |
| 284 | 309 |
| 285 /** @private */ | 310 /** @private */ |
| 286 function removeStreamCallback_(event) { | 311 function removeStreamCallback_(event) { |
| 287 debug('Call ended.'); | 312 debug('Call ended.'); |
| 288 document.getElementById('remote-view').src = ''; | 313 document.getElementById('remote-view').src = ''; |
| 289 } | 314 } |
| 290 | 315 |
| 291 /** | 316 /** |
| 292 * Parses JSON-encoded session descriptions and ICE candidates. | 317 * Parses JSON-encoded session descriptions and ICE candidates. |
| 293 * @private | 318 * @private |
| 294 */ | 319 */ |
| 295 function parseJson_(json) { | 320 function parseJson_(json) { |
| 296 // Escape since the \r\n in the SDP tend to get unescaped. | 321 // Escape since the \r\n in the SDP tend to get unescaped. |
| 297 jsonWithEscapedLineBreaks = json.replace(/\r\n/g, '\\r\\n'); | 322 jsonWithEscapedLineBreaks = json.replace(/\r\n/g, '\\r\\n'); |
| 298 try { | 323 try { |
| 299 return JSON.parse(jsonWithEscapedLineBreaks); | 324 return JSON.parse(jsonWithEscapedLineBreaks); |
| 300 } catch (exception) { | 325 } catch (exception) { |
| 301 failTest('Failed to parse JSON: ' + jsonWithEscapedLineBreaks + ', got ' + | 326 failTest('Failed to parse JSON: ' + jsonWithEscapedLineBreaks + ', got ' + |
| 302 exception); | 327 exception); |
| 303 } | 328 } |
| 304 } | 329 } |
| OLD | NEW |