test_rvfc_timestamp_alignment.html (4745B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <script src="pc.js" type="application/javascript"></script> 5 <script src="/tests/dom/canvas/test/captureStream_common.js" type="application/javascript"></script> 6 <script src="stats.js" type="application/javascript"></script> 7 </head> 8 <body> 9 <pre id="test"> 10 <script type="application/javascript"> 11 createHTML({ 12 bug: "1937776", 13 title: "Verify VideoFrameCallback receiveTime/captureTime alignment", 14 }); 15 16 const {AppConstants} = SpecialPowers.ChromeUtils.importESModule( 17 "resource://gre/modules/AppConstants.sys.mjs" 18 ); 19 20 runNetworkTest(async function(options) { 21 async function WAIT_FOR_SYNCED_RTCP(test, count) { 22 for (let i = 0; i < count; i++) { 23 await waitForSyncedRtcp(test.pcLocal._pc); 24 await waitForSyncedRtcp(test.pcRemote._pc); 25 } 26 } 27 28 async function CHECK_TIMESTAMP_ALIGNMENT(test, ok_or_todo, header_text) { 29 const video = test.pcRemote.remoteMediaElements[0]; 30 const maxFrames = 60; 31 const maxRecvDelta = 250; 32 const maxCaptDelta = 250; 33 const minCaptCount = 5; 34 let frameCount = 0; 35 let captCount = 0; 36 37 // macOS fixes for high jitter on try 38 const recvOffset = AppConstants.platform == "macosx" ? -200 : 0; 39 const captOffset = AppConstants.platform == "macosx" ? -200 : 0; 40 41 // captureTime may not be present for several frames 42 let missedCaptCount = 0; 43 44 info(`***** RUNNING ${header_text} ALIGNMENT TEST`); 45 info(`***** USING ASSERT ${ok_or_todo == ok ? "ok" : "todo"}() FOR captureTime`); 46 info(`***** APPLYING ${recvOffset} ms OFFSET TO receiveTime ASSERTS`); 47 48 while (++frameCount <= maxFrames) { 49 info(`Checking frame #${frameCount} of ${maxFrames}`); 50 const {now, metadata} = 51 await new Promise(r => video.requestVideoFrameCallback( 52 (now, metadata) => r({now, metadata}))); 53 const {presentationTime, receiveTime, captureTime} = metadata; 54 55 ok(receiveTime, "receiveTime is present"); 56 if (receiveTime) { 57 const dt = presentationTime - receiveTime; 58 ok(dt > recvOffset, `receiveTime (${receiveTime.toFixed(2)} ms) < ` 59 + `presentationTime (${presentationTime.toFixed(2)} ms)`); 60 if (dt > recvOffset) { 61 ok(dt <= maxRecvDelta, `receiveTime delta (${dt.toFixed(2)} ms) <= ${maxRecvDelta} ms`); 62 } 63 } 64 65 if (captureTime) { 66 ok_or_todo(captureTime, `captureTime is present`); 67 const dt = presentationTime - captureTime; 68 ok(dt > captOffset, `captureTime (${captureTime.toFixed(2)} ms) < ` 69 + `presentationTime (${presentationTime.toFixed(2)} ms)`); 70 if (dt > captOffset) { 71 ok(dt <= maxCaptDelta, `captureTime delta (${dt.toFixed(2)} ms) <= ${maxCaptDelta} ms`); 72 } 73 if (++captCount >= minCaptCount) { 74 info(`Received ${minCaptCount} captureTime, exiting test`); 75 break; 76 } 77 } else { 78 ok(++missedCaptCount == frameCount, 79 "missing captureTime occurred sequentially from test start."); 80 } 81 } 82 ok_or_todo(captCount >= minCaptCount, 83 `Captured at least ${captCount} captureTime`) 84 } 85 86 function arg_wrapper(fn, argsArr) { 87 return async function wrap() { 88 return fn(...argsArr); 89 }; 90 } 91 92 SimpleTest.requestCompleteLog(); 93 await pushPrefs( 94 ["media.video_loopback_dev", ""], 95 ["media.navigator.streams.fake", true] 96 ); 97 98 // Note we use two RTCP syncs in these tests as we currently need two 99 // RTCP measurements in order to estimate a NTP timestamp. 100 // See: Use of rtp_to_ntp_.Estimate(rtp_timestamp) in 101 // RemoteNtpTimeEstimator::EstimateNtp() and 102 // the two measurement requirement in 103 // RtpToNtpEstimator::UpdateParameters() 104 // (as of 618678dd32e52dbaa8a56d72c6655032f48068b3) 105 106 // Unidirectional captureTime is currently BROKEN. 107 // See: bug 1971078 , bug 1971117 108 const test_uni = new PeerConnectionTest(options); 109 test_uni.setMediaConstraints([{ video: true }], []); 110 test_uni.chain.append([ 111 arg_wrapper(WAIT_FOR_SYNCED_RTCP, [test_uni, 2]), 112 arg_wrapper(CHECK_TIMESTAMP_ALIGNMENT, [test_uni, todo, "UNIDIRECTIONAL"]), 113 ]); 114 await test_uni.run(); 115 116 // Bidirectional test should pass. 117 const test_bi = new PeerConnectionTest(options); 118 test_bi.setMediaConstraints([{ video: true }], [{ video: true }]); 119 test_bi.chain.append([ 120 arg_wrapper(WAIT_FOR_SYNCED_RTCP, [test_bi, 2]), 121 arg_wrapper(CHECK_TIMESTAMP_ALIGNMENT, [test_bi, ok, "BIDIRECTIONAL"]), 122 ]); 123 await test_bi.run(); 124 }); 125 </script> 126 </pre> 127 </body> 128 </html>