| <!doctype html> |
| <meta charset=utf-8> |
| <title>Timestamps in RTCEncodedFrame metadata</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/webrtc/RTCPeerConnection-helper.js"></script> |
| <script src="RTCEncodedFrame-timestamps-helper.js"></script> |
| <script> |
| 'use strict'; |
| |
| function doWorkExpectingCaptureTimestamps() { |
| onrtctransform = async e => { |
| const reader = e.transformer.readable.getReader(); |
| const writer = e.transformer.writable.getWriter(); |
| let oldCaptureTime = -1; |
| let oldReceiveTime = -1; |
| for (let i = 0; i<10; i++) { |
| const frameOrDone = await reader.read(); |
| if (frameOrDone.done) { |
| self.postMessage("Unexpected end of stream"); |
| return; |
| } |
| const metadata = frameOrDone.value.getMetadata(); |
| if (metadata.captureTime > metadata.receiveTime || |
| metadata.captureTime < 0 || |
| metadata.captureTime < oldCaptureTime) { |
| self.postMessage("Unexpected captureTime"); |
| return; |
| } |
| if (metadata.receiveTime > performance.now() || |
| metadata.receiveTime < metadata.captureTime || |
| metadata.receiveTime < oldReceiveTime) { |
| self.postMessage("Unexpected receiveTime"); |
| return; |
| } |
| if (metadata.senderCaptureTimeOffset != 0) { |
| self.postMessage("Unexpected senderReceiveTimeOffset"); |
| return; |
| } |
| oldCaptureTime = metadata.captureTime; |
| oldReceiveTime = metadata.receiveTime; |
| await writer.write(frameOrDone.value); |
| } |
| self.postMessage("OK"); |
| }; |
| } |
| |
| function doWorkExpectingNoCaptureTimestamps() { |
| onrtctransform = async e => { |
| const reader = e.transformer.readable.getReader(); |
| const writer = e.transformer.writable.getWriter(); |
| let oldReceiveTime = -1; |
| for (let i = 0; i<10; i++) { |
| const frameOrDone = await reader.read(); |
| if (frameOrDone.done) { |
| self.postMessage("Unexpected end of stream"); |
| return; |
| } |
| const metadata = frameOrDone.value.getMetadata(); |
| if ("captureTime" in metadata) { |
| self.postMessage("Unexpected captureTime"); |
| return; |
| } |
| if ("senderCaptureTimeOffset" in metadata) { |
| self.postMessage("Unexpected senderReceiveTimeOffset"); |
| return; |
| } |
| if (metadata.receiveTime > performance.now() || |
| metadata.receiveTime < oldReceiveTime) { |
| self.postMessage("Unexpected receiveTime"); |
| return; |
| } |
| oldReceiveTime = metadata.receiveTime; |
| await writer.write(frameOrDone.value); |
| } |
| self.postMessage("OK"); |
| }; |
| } |
| |
| promise_test(async t => { |
| const worker = new Worker(`data:text/javascript,(${doWorkExpectingCaptureTimestamps.toString()})()`); |
| const workerPromise = new Promise((resolve, reject) => { |
| worker.onmessage = t.step_func(message => { |
| if (message.data == "OK") { |
| resolve(); |
| } else { |
| reject(message.data); |
| } |
| }); |
| }); |
| |
| await initiateCall( |
| t, /*streamOptions=*/{audio: true, video: false}, |
| /*enableAbsCaptureTime=*/true, worker, /*enableSenderTransform=*/false, |
| /*enableReceiverTransform=*/true); |
| |
| return workerPromise; |
| }, 'captureTime and senderCaptureTimeOffset present in audio receiver if extension is used'); |
| |
| promise_test(async t => { |
| const worker = new Worker(`data:text/javascript,(${doWorkExpectingNoCaptureTimestamps.toString()})()`); |
| const workerPromise = new Promise((resolve, reject) => { |
| worker.onmessage = t.step_func(message => { |
| if (message.data == "OK") { |
| resolve(); |
| } else { |
| reject(message.data); |
| } |
| }); |
| }); |
| |
| await initiateCall( |
| t, /*streamOptions=*/{audio: true, video: false}, |
| /*enableAbsCaptureTime=*/false, worker, /*enableSenderTransform=*/false, |
| /*enableReceiverTransform=*/true); |
| |
| return workerPromise; |
| }, 'captureTime and senderCaptureTimeOffset not present in audio receiver if extension not used'); |
| |
| promise_test(async t => { |
| const worker = new Worker(`data:text/javascript,(${doWorkExpectingCaptureTimestamps.toString()})()`); |
| const workerPromise = new Promise((resolve, reject) => { |
| worker.onmessage = t.step_func(message => { |
| if (message.data == "OK") { |
| resolve(); |
| } else { |
| reject(message.data); |
| } |
| }); |
| }); |
| |
| await initiateCall( |
| t, /*streamOptions=*/{audio: false, video: true}, |
| /*enableAbsCaptureTime=*/true, worker, /*enableSenderTransform=*/false, |
| /*enableReceiverTransform=*/true); |
| |
| return workerPromise; |
| }, 'captureTime and senderCaptureTimeOffset present in video receiver if extension is used'); |
| |
| promise_test(async t => { |
| const worker = new Worker(`data:text/javascript,(${doWorkExpectingNoCaptureTimestamps.toString()})()`); |
| const workerPromise = new Promise((resolve, reject) => { |
| worker.onmessage = t.step_func(message => { |
| if (message.data == "OK") { |
| resolve(); |
| } else { |
| reject(message.data); |
| } |
| }); |
| }); |
| |
| await initiateCall( |
| t, /*streamOptions=*/{audio: false, video: true}, |
| /*enableAbsCaptureTime=*/false, worker, /*enableSenderTransform=*/false, |
| /*enableReceiverTransform=*/true); |
| |
| return workerPromise; |
| }, 'captureTime and senderCaptureTimeOffset not present in video receiver if extension not used'); |
| |
| </script> |