diff options
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/test_peerConnection_simulcastOddResolution.html')
-rw-r--r-- | dom/media/webrtc/tests/mochitests/test_peerConnection_simulcastOddResolution.html | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_simulcastOddResolution.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_simulcastOddResolution.html new file mode 100644 index 0000000000..c380b34f1a --- /dev/null +++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_simulcastOddResolution.html @@ -0,0 +1,183 @@ +<!DOCTYPE HTML> +<html> +<head> + <script type="application/javascript" src="pc.js"></script> + <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script> + <script type="application/javascript" src="helpers_from_wpt/sdp.js"></script> + <script type="application/javascript" src="simulcast.js"></script> + <script type="application/javascript" src="stats.js"></script> +</head> +<body> +<pre id="test"> +<script type="application/javascript"> + createHTML({ + bug: "1432793", + title: "Simulcast with odd resolution", + visible: true + }); + + runNetworkTest(async () => { + const helper = new VideoStreamHelper(); + const emitter = new VideoFrameEmitter(helper.green, helper.red, 705, 528); + + async function checkVideoElement(senderElement, receiverElement, encoding) { + info(`Waiting for receiver video element ${encoding.rid} to start playing`); + await helper.checkVideoPlaying(receiverElement); + const srcWidth = senderElement.videoWidth; + const srcHeight = senderElement.videoHeight; + info(`Source resolution is ${srcWidth}x${srcHeight}`); + + const scaleDownBy = encoding.scaleResolutionDownBy; + const expectedWidth = srcWidth / scaleDownBy; + const expectedHeight = srcHeight / scaleDownBy; + const margin = srcWidth * 0.1; + const width = receiverElement.videoWidth; + const height = receiverElement.videoHeight; + const rid = encoding.rid; + ok(width >= expectedWidth - margin && width <= expectedWidth + margin, + `Width ${width} should be within 10% of ${expectedWidth} for rid '${rid}'`); + ok(height >= expectedHeight - margin && height <= expectedHeight + margin, + `Height ${height} should be within 10% of ${expectedHeight} for rid '${rid}'`); + } + + async function checkVideoElements(senderElement, receiverElements, encodings) { + is(receiverElements.length, encodings.length, 'Number of video elements should match number of encodings'); + info('Waiting for sender video element to start playing'); + await helper.checkVideoPlaying(senderElement); + for (let i = 0; i < encodings.length; i++) { + await checkVideoElement(senderElement, receiverElements[i], encodings[i]); + } + } + + const sendEncodings = [{ rid: "0", maxBitrate: 40000, scaleResolutionDownBy: 1.9 }, + { rid: "1", maxBitrate: 40000, scaleResolutionDownBy: 3.5 }, + { rid: "2", maxBitrate: 40000, scaleResolutionDownBy: 17.8 }]; + + async function checkSenderStats(sender) { + const senderStats = await sender.getStats(); + checkSenderStats(senderStats, sendEncodings.length); + checkExpectedFields(senderStats); + pedanticChecks(senderStats); + } + + async function waitForResizeEvents(elements) { + return Promise.all(elements.map(elem => haveEvent(elem, 'resize'))); + } + + await pushPrefs( + // 180Kbps was determined empirically, set well-higher than + // the 80Kbps+overhead needed for the two simulcast streams. + // 100Kbps was apparently too low. + ['media.peerconnection.video.min_bitrate_estimate', 180*1000]); + + + const offerer = new RTCPeerConnection(); + const answerer = new RTCPeerConnection(); + + const add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed); + offerer.onicecandidate = e => add(answerer, e.candidate, generateErrorCallback()); + answerer.onicecandidate = e => add(offerer, e.candidate, generateErrorCallback()); + + const metadataToBeLoaded = []; + answerer.ontrack = (e) => { + metadataToBeLoaded.push(getPlaybackWithLoadedMetadata(e.track)); + }; + + // One send transceiver, that will be used to send both simulcast streams + const videoStream = emitter.stream(); + offerer.addTransceiver(videoStream.getVideoTracks()[0], {sendEncodings}); + const senderElement = document.createElement('video'); + senderElement.autoplay = true; + senderElement.srcObject = videoStream; + senderElement.id = videoStream.id + + const sender = offerer.getSenders()[0]; + let parameters = sender.getParameters(); + is(parameters.encodings[0].maxBitrate, sendEncodings[0].maxBitrate); + isfuzzy(parameters.encodings[0].scaleResolutionDownBy, + sendEncodings[0].scaleResolutionDownBy, 0.01); + is(parameters.encodings[1].maxBitrate, sendEncodings[1].maxBitrate); + isfuzzy(parameters.encodings[1].scaleResolutionDownBy, + sendEncodings[1].scaleResolutionDownBy, 0.01); + is(parameters.encodings[2].maxBitrate, sendEncodings[2].maxBitrate); + isfuzzy(parameters.encodings[2].scaleResolutionDownBy, + sendEncodings[2].scaleResolutionDownBy, 0.01); + + const offer = await offerer.createOffer(); + + const mungedOffer = ridToMid(offer); + info(`Transformed send simulcast offer to multiple m-sections: ${offer.sdp} to ${mungedOffer}`); + + await answerer.setRemoteDescription({type: 'offer', sdp: mungedOffer}); + await offerer.setLocalDescription(offer); + + const rids = answerer.getTransceivers().map(t => t.mid); + is(rids.length, 3, 'Should have 3 mids in offer'); + ok(rids[0], 'First mid should be non-empty'); + ok(rids[1], 'Second mid should be non-empty'); + ok(rids[2], 'Third mid should be non-empty'); + info(`rids: ${JSON.stringify(rids)}`); + + const answer = await answerer.createAnswer(); + + const mungedAnswer = midToRid(answer); + info(`Transformed recv answer to simulcast: ${answer.sdp} to ${mungedAnswer}`); + await offerer.setRemoteDescription({type: 'answer', sdp: mungedAnswer}); + await answerer.setLocalDescription(answer); + + is(metadataToBeLoaded.length, 3, 'Offerer should have gotten 3 ontrack events'); + emitter.start(); + info('Waiting for 3 loadedmetadata events'); + const videoElems = await Promise.all(metadataToBeLoaded); + await checkVideoElements(senderElement, videoElems, parameters.encodings); + emitter.stop(); + + await Promise.all([waitForSyncedRtcp(offerer), waitForSyncedRtcp(answerer)]); + + info(`Changing source resolution to 1280x720`); + emitter.size(1280, 720); + emitter.start(); + await waitForResizeEvents([senderElement, ...videoElems]); + await checkVideoElements(senderElement, videoElems, parameters.encodings); + await checkSenderStats(sender); + + parameters = sender.getParameters(); + parameters.encodings[0].scaleResolutionDownBy = 1; + parameters.encodings[1].scaleResolutionDownBy = 2; + parameters.encodings[2].scaleResolutionDownBy = 3; + info(`Changing encodings to ${JSON.stringify(parameters.encodings)}`); + await sender.setParameters(parameters); + await waitForResizeEvents(videoElems); + await checkVideoElements(senderElement, videoElems, parameters.encodings); + await checkSenderStats(sender); + + parameters = sender.getParameters(); + parameters.encodings[0].scaleResolutionDownBy = 6; + parameters.encodings[1].scaleResolutionDownBy = 5; + parameters.encodings[2].scaleResolutionDownBy = 4; + info(`Changing encodings to ${JSON.stringify(parameters.encodings)}`); + await sender.setParameters(parameters); + await waitForResizeEvents(videoElems); + await checkVideoElements(senderElement, videoElems, parameters.encodings); + await checkSenderStats(sender); + + parameters = sender.getParameters(); + parameters.encodings[0].scaleResolutionDownBy = 4; + parameters.encodings[1].scaleResolutionDownBy = 1; + parameters.encodings[2].scaleResolutionDownBy = 2; + info(`Changing encodings to ${JSON.stringify(parameters.encodings)}`); + await sender.setParameters(parameters); + await waitForResizeEvents(videoElems); + await checkVideoElements(senderElement, videoElems, parameters.encodings); + await checkSenderStats(sender); + + emitter.stop(); + videoStream.getVideoTracks()[0].stop(); + offerer.close(); + answerer.close(); + }); + +</script> +</pre> +</body> +</html> |