diff options
Diffstat (limited to 'testing/web-platform/tests/video-rvfc/request-video-frame-callback-webrtc.https.html')
-rw-r--r-- | testing/web-platform/tests/video-rvfc/request-video-frame-callback-webrtc.https.html | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/testing/web-platform/tests/video-rvfc/request-video-frame-callback-webrtc.https.html b/testing/web-platform/tests/video-rvfc/request-video-frame-callback-webrtc.https.html new file mode 100644 index 0000000000..dcf97e4ca9 --- /dev/null +++ b/testing/web-platform/tests/video-rvfc/request-video-frame-callback-webrtc.https.html @@ -0,0 +1,165 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>WebRTC video.requestVideoFrameCallback() test</title> + <script src="/webrtc/RTCPeerConnection-helper.js"></script> +</head> +<body> + <div id="log"></div> + <div> + <video id="local-view" muted autoplay="autoplay"></video> + <video id="remote-view" muted autoplay="autoplay"/> + </video> + </div> + + <!-- These files are in place when executing on W3C. --> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + var test = async_test('Test video.requestVideoFrameCallback() parameters for WebRTC applications.'); + + // + // This test is based on /webrtc/simplecall.https.html, but it calls to + // video.requestVideoFrameCallback() before ending, to verify WebRTC required + // and optional parameters. + // + + var gFirstConnection = null; + var gSecondConnection = null; + var gCallbackCounter = 0; + var verify_params = (now, metadata) => { + gCallbackCounter = gCallbackCounter + 1; + assert_greater_than(now, 0); + + // Verify all required fields + assert_greater_than(metadata.presentationTime, 0); + assert_greater_than(metadata.expectedDisplayTime, 0); + assert_greater_than(metadata.presentedFrames, 0); + assert_greater_than(metadata.width, 0); + assert_greater_than(metadata.height, 0); + assert_true("mediaTime" in metadata, "mediaTime should be present"); + + // Verify WebRTC only fields. + assert_true("rtpTimestamp" in metadata, "rtpTimestamp should be present"); + assert_true("receiveTime" in metadata, "receiveTime should be present"); + // captureTime is not available until roundtrip time estimation is done. + if (gCallbackCounter > 60 || "captureTime" in metadata) { + assert_true("captureTime" in metadata, "captureTime should be present"); + test.done(); + } + else { + // Keep requesting callbacks. + document.getElementById('remote-view').requestVideoFrameCallback(test.step_func(verify_params)); + } + } + + var verify_local_metadata = (now, metadata) => { + assert_greater_than(metadata.expectedDisplayTime, 0); + assert_greater_than(metadata.presentedFrames, 0); + assert_greater_than(metadata.width, 0); + assert_greater_than(metadata.height, 0); + assert_true("captureTime" in metadata, "captureTime should always be present for local sources."); + assert_greater_than(metadata.captureTime, 0); + } + + // If the remote video gets video data that implies the negotiation + // as well as the ICE and DTLS connection are up. + document.getElementById('remote-view') + .addEventListener('loadedmetadata', function() { + document.getElementById('remote-view').requestVideoFrameCallback(test.step_func(verify_params)); + }); + + document.getElementById('local-view') + .addEventListener('loadmetadata', function() { + document.getElementById('local-view').requestVideoFrameCallback(test.step_func_done(verify_local_metadata)); + }); + + + function getNoiseStreamOkCallback(localStream) { + gFirstConnection = new RTCPeerConnection(null); + test.add_cleanup(() => gFirstConnection.close()); + gFirstConnection.onicecandidate = onIceCandidateToFirst; + + gSecondConnection = new RTCPeerConnection(null); + test.add_cleanup(() => gSecondConnection.close()); + gSecondConnection.onicecandidate = onIceCandidateToSecond; + gSecondConnection.ontrack = onRemoteTrack; + + localStream.getTracks().forEach(function(track) { + // Bidirectional streams are needed in order for captureTime to be + // populated. Use the same source in both directions. + gFirstConnection.addTrack(track, localStream); + gSecondConnection.addTrack(track, localStream); + }); + + gFirstConnection.createOffer().then(onOfferCreated, failed('createOffer')); + + var videoTag = document.getElementById('local-view'); + videoTag.srcObject = localStream; + }; + + var onOfferCreated = test.step_func(function(offer) { + gFirstConnection.setLocalDescription(offer); + + // This would normally go across the application's signaling solution. + // In our case, the "signaling" is to call this function. + receiveCall(offer.sdp); + }); + + function receiveCall(offerSdp) { + var parsedOffer = new RTCSessionDescription({ type: 'offer', + sdp: offerSdp }); + gSecondConnection.setRemoteDescription(parsedOffer); + + gSecondConnection.createAnswer().then(onAnswerCreated, + failed('createAnswer')); + }; + + var onAnswerCreated = test.step_func(function(answer) { + gSecondConnection.setLocalDescription(answer); + + // Similarly, this would go over the application's signaling solution. + handleAnswer(answer.sdp); + }); + + function handleAnswer(answerSdp) { + var parsedAnswer = new RTCSessionDescription({ type: 'answer', + sdp: answerSdp }); + gFirstConnection.setRemoteDescription(parsedAnswer); + }; + + var onIceCandidateToFirst = test.step_func(function(event) { + // If event.candidate is null = no more candidates. + if (event.candidate) { + gSecondConnection.addIceCandidate(event.candidate); + } + }); + + var onIceCandidateToSecond = test.step_func(function(event) { + if (event.candidate) { + gFirstConnection.addIceCandidate(event.candidate); + } + }); + + var onRemoteTrack = test.step_func(function(event) { + var videoTag = document.getElementById('remote-view'); + if (!videoTag.srcObject) { + videoTag.srcObject = event.streams[0]; + } + }); + + // Returns a suitable error callback. + function failed(function_name) { + return test.unreached_func('WebRTC called error callback for ' + function_name); + } + + // This function starts the test. + test.step(function() { + getNoiseStream({ video: true, audio: true }) + .then(test.step_func(getNoiseStreamOkCallback), failed('getNoiseStream')); + }); +</script> + +</body> +</html> |