RTCEncodedFrame-timestamps.html (5366B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>Timestamps in RTCEncodedFrame metadata</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/webrtc/RTCPeerConnection-helper.js"></script> 7 <script src="RTCEncodedFrame-timestamps-helper.js"></script> 8 <script> 9 'use strict'; 10 11 function doWorkExpectingCaptureTimestamps() { 12 onrtctransform = async e => { 13 const reader = e.transformer.readable.getReader(); 14 const writer = e.transformer.writable.getWriter(); 15 let oldCaptureTime = -1; 16 let oldReceiveTime = -1; 17 for (let i = 0; i<10; i++) { 18 const frameOrDone = await reader.read(); 19 if (frameOrDone.done) { 20 self.postMessage("Unexpected end of stream"); 21 return; 22 } 23 const metadata = frameOrDone.value.getMetadata(); 24 if (metadata.captureTime > metadata.receiveTime || 25 metadata.captureTime < 0 || 26 metadata.captureTime < oldCaptureTime) { 27 self.postMessage("Unexpected captureTime"); 28 return; 29 } 30 if (metadata.receiveTime > performance.now() || 31 metadata.receiveTime < metadata.captureTime || 32 metadata.receiveTime < oldReceiveTime) { 33 self.postMessage("Unexpected receiveTime"); 34 return; 35 } 36 if (metadata.senderCaptureTimeOffset != 0) { 37 self.postMessage("Unexpected senderReceiveTimeOffset"); 38 return; 39 } 40 oldCaptureTime = metadata.captureTime; 41 oldReceiveTime = metadata.receiveTime; 42 await writer.write(frameOrDone.value); 43 } 44 self.postMessage("OK"); 45 }; 46 } 47 48 function doWorkExpectingNoCaptureTimestamps() { 49 onrtctransform = async e => { 50 const reader = e.transformer.readable.getReader(); 51 const writer = e.transformer.writable.getWriter(); 52 let oldReceiveTime = -1; 53 for (let i = 0; i<10; i++) { 54 const frameOrDone = await reader.read(); 55 if (frameOrDone.done) { 56 self.postMessage("Unexpected end of stream"); 57 return; 58 } 59 const metadata = frameOrDone.value.getMetadata(); 60 if ("captureTime" in metadata) { 61 self.postMessage("Unexpected captureTime"); 62 return; 63 } 64 if ("senderCaptureTimeOffset" in metadata) { 65 self.postMessage("Unexpected senderReceiveTimeOffset"); 66 return; 67 } 68 if (metadata.receiveTime > performance.now() || 69 metadata.receiveTime < oldReceiveTime) { 70 self.postMessage("Unexpected receiveTime"); 71 return; 72 } 73 oldReceiveTime = metadata.receiveTime; 74 await writer.write(frameOrDone.value); 75 } 76 self.postMessage("OK"); 77 }; 78 } 79 80 promise_test(async t => { 81 const worker = new Worker(`data:text/javascript,(${doWorkExpectingCaptureTimestamps.toString()})()`); 82 const workerPromise = new Promise((resolve, reject) => { 83 worker.onmessage = t.step_func(message => { 84 if (message.data == "OK") { 85 resolve(); 86 } else { 87 reject(message.data); 88 } 89 }); 90 }); 91 92 await initiateCall( 93 t, /*streamOptions=*/{audio: true, video: false}, 94 /*enableAbsCaptureTime=*/true, worker, /*enableSenderTransform=*/false, 95 /*enableReceiverTransform=*/true); 96 97 return workerPromise; 98 }, 'captureTime and senderCaptureTimeOffset present in audio receiver if extension is used'); 99 100 promise_test(async t => { 101 const worker = new Worker(`data:text/javascript,(${doWorkExpectingNoCaptureTimestamps.toString()})()`); 102 const workerPromise = new Promise((resolve, reject) => { 103 worker.onmessage = t.step_func(message => { 104 if (message.data == "OK") { 105 resolve(); 106 } else { 107 reject(message.data); 108 } 109 }); 110 }); 111 112 await initiateCall( 113 t, /*streamOptions=*/{audio: true, video: false}, 114 /*enableAbsCaptureTime=*/false, worker, /*enableSenderTransform=*/false, 115 /*enableReceiverTransform=*/true); 116 117 return workerPromise; 118 }, 'captureTime and senderCaptureTimeOffset not present in audio receiver if extension not used'); 119 120 promise_test(async t => { 121 const worker = new Worker(`data:text/javascript,(${doWorkExpectingCaptureTimestamps.toString()})()`); 122 const workerPromise = new Promise((resolve, reject) => { 123 worker.onmessage = t.step_func(message => { 124 if (message.data == "OK") { 125 resolve(); 126 } else { 127 reject(message.data); 128 } 129 }); 130 }); 131 132 await initiateCall( 133 t, /*streamOptions=*/{audio: false, video: true}, 134 /*enableAbsCaptureTime=*/true, worker, /*enableSenderTransform=*/false, 135 /*enableReceiverTransform=*/true); 136 137 return workerPromise; 138 }, 'captureTime and senderCaptureTimeOffset present in video receiver if extension is used'); 139 140 promise_test(async t => { 141 const worker = new Worker(`data:text/javascript,(${doWorkExpectingNoCaptureTimestamps.toString()})()`); 142 const workerPromise = new Promise((resolve, reject) => { 143 worker.onmessage = t.step_func(message => { 144 if (message.data == "OK") { 145 resolve(); 146 } else { 147 reject(message.data); 148 } 149 }); 150 }); 151 152 await initiateCall( 153 t, /*streamOptions=*/{audio: false, video: true}, 154 /*enableAbsCaptureTime=*/false, worker, /*enableSenderTransform=*/false, 155 /*enableReceiverTransform=*/true); 156 157 return workerPromise; 158 }, 'captureTime and senderCaptureTimeOffset not present in video receiver if extension not used'); 159 160 </script>