setParameters-maxFramerate.https.html (4197B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>RTCPeerConnection Simulcast Tests - setParameters/maxFramerate</title> 4 <meta name="timeout" content="long"> 5 <script src="../third_party/sdp/sdp.js"></script> 6 <script src="simulcast.js"></script> 7 <script src="../RTCPeerConnection-helper.js"></script> 8 <script src="/resources/testharness.js"></script> 9 <script src="/resources/testharnessreport.js"></script> 10 <script src="/resources/testdriver.js"></script> 11 <script src="/resources/testdriver-vendor.js"></script> 12 <script src="../../mediacapture-streams/permission-helper.js"></script> 13 <script> 14 async function queryReceiverStats(pc) { 15 const inboundStats = []; 16 await Promise.all(pc.getReceivers().map(async receiver => { 17 const receiverStats = await receiver.getStats(); 18 receiverStats.forEach(stat => { 19 if (stat.type === 'inbound-rtp') { 20 inboundStats.push(stat); 21 } 22 }); 23 })); 24 return inboundStats; 25 } 26 27 async function statsDelta(pc, t) { 28 const initialStats = await queryReceiverStats(pc); 29 await new Promise(resolve => t.step_timeout(resolve, 1000)); // Wait more. 30 const subsequentStats = await queryReceiverStats(pc); 31 return {initialStats, subsequentStats}; 32 } 33 34 function calculateFramerate(newStats, oldStats) { 35 const deltaF = newStats.framesDecoded - oldStats.framesDecoded; 36 const deltaT = newStats.timestamp - oldStats.timestamp; 37 return deltaF / deltaT * 1000; 38 } 39 40 function calculateConservativeFramerate(newStats, oldStats) { 41 // The timestamp represents the exact point in time that the integer 42 // framesDecoded was sampled. For both samples, one time unit (say a 43 // nanosecond, i.e. virtually 0) could sway the integer framesDecoded value 44 // up to 1 frame. For checking that we don't exceed maxFramerate, in the worst 45 // case, the old timestamp is then at the end of a frame period (right before 46 // framesDecoded gets incremented) while the new timestamp is at the beginning 47 // of a frame period. Thus for avoiding intermittents we need to allow up to 48 // two frames more for the given sampling period, regardless of length. 49 const deltaF = newStats.framesDecoded - oldStats.framesDecoded - 2; 50 const deltaT = newStats.timestamp - oldStats.timestamp; 51 return deltaF / deltaT * 1000; 52 } 53 54 promise_test(async t => { 55 const expectedFramerates = [15, 10, 5]; 56 const rids = [0, 1, 2]; 57 const pc1 = new RTCPeerConnection(); 58 t.add_cleanup(() => pc1.close()); 59 const pc2 = new RTCPeerConnection(); 60 t.add_cleanup(() => pc2.close()); 61 62 await negotiateSimulcastAndWaitForVideo( 63 t, 64 await getCameraStream(t), 65 rids, 66 pc1, 67 pc2 68 ); 69 70 // Wait for framerate to stabilize. 71 await new Promise(resolve => t.step_timeout(resolve, 1000)); 72 73 // Assert that our framerate is bigger than 20, otherwise this test does not 74 // assert anything useful. 75 const defaultStats = await statsDelta(pc2, t); 76 defaultStats.subsequentStats.forEach((_, idx) => { 77 const actualFramerate = calculateFramerate( 78 defaultStats.subsequentStats[idx], 79 defaultStats.initialStats[idx] 80 ); 81 assert_greater_than(actualFramerate, 20); 82 }); 83 84 // Change the framerate on all layers. 85 const parameters = pc1.getSenders()[0].getParameters(); 86 parameters.encodings.forEach((e, idx) => { 87 e.maxFramerate = expectedFramerates[idx]; 88 }); 89 await pc1.getSenders()[0].setParameters(parameters); 90 // Wait for the change to propagate to the receiver. 91 await new Promise(resolve => t.step_timeout(resolve, 100)); 92 93 // Assert the approximate framerate 94 const newStats = await statsDelta(pc2, t); 95 96 const framerates = []; 97 newStats.subsequentStats.forEach((_, idx) => { 98 const expectedFramerate = expectedFramerates[idx]; 99 const actualFramerate = calculateConservativeFramerate( 100 newStats.subsequentStats[idx], 101 newStats.initialStats[idx] 102 ); 103 // Assert that the framerate is at most the expected framerate. 104 assert_less_than(actualFramerate, expectedFramerate); 105 framerates.push(actualFramerate); 106 }); 107 // Assert that the framerates are ordered as configured. 108 assert_array_equals(framerates, framerates.toSorted((a, b) => a < b)); 109 }, 'Simulcast setParameters maxFramerate reduces the framerate'); 110 </script>