| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>VideoFrame.metadata.rtpTimestamp exposed via MediaStreamTrackProcessor over WebRTC</title> |
| |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/webrtc/RTCPeerConnection-helper.js"></script> |
| |
| <script> |
| promise_test(async t => { |
| if (!("MediaStreamTrackProcessor" in self) || |
| !("VideoFrame" in self)) { |
| assert_implements_optional(true, "MediaStreamTrackProcessor/VideoFrame APIs not supported. Skipping test."); |
| return; |
| } |
| |
| const stream = await getNoiseStream({ video: true }); |
| const track = stream.getVideoTracks()[0]; |
| |
| // This test validates the RTP timestamps on the encoded video frames |
| // sent by a WebRTC peer (sender) are preserved when received by the |
| // WebRTC receiver which in turn uses the MediaStreamTrackProcessor |
| // API to render the video frames. We expect the RTP timestamps to |
| // be available in the metadata() object exposed by the VideoFrame |
| // in MediaStreamTrackProcessor if the VideoFrameMetadataRtpTimestamp |
| // feature is enabled. |
| |
| const senderPc = new RTCPeerConnection(); |
| const receiverPc = new RTCPeerConnection(); |
| |
| senderPc.onicecandidate = e => e.candidate && receiverPc.addIceCandidate(e.candidate); |
| receiverPc.onicecandidate = e => e.candidate && senderPc.addIceCandidate(e.candidate); |
| |
| const receiverTrackPromise = new Promise(resolve => { |
| receiverPc.ontrack = e => resolve(e.track); |
| }); |
| |
| const sender = senderPc.addTrack(track, stream); |
| |
| // Offer/Answer exchange |
| const offer = await senderPc.createOffer(); |
| await senderPc.setLocalDescription(offer); |
| await receiverPc.setRemoteDescription(offer); |
| |
| const answer = await receiverPc.createAnswer(); |
| await receiverPc.setLocalDescription(answer); |
| await senderPc.setRemoteDescription(answer); |
| |
| let receiverTrack = await receiverTrackPromise; |
| |
| // Send the received track to MediaStreamTrackProcessor for rendering. |
| const processor = new MediaStreamTrackProcessor({ track: receiverTrack }); |
| const reader = processor.readable.getReader(); |
| |
| const result = await reader.read(); |
| const frame = result.value; |
| const metadata = frame.metadata?.(); |
| |
| // If the VideoFrameMetadataRtpTimestamp feature is enabled we expect that |
| // the rtpTimestamp will be available in the metadata. |
| if (metadata && 'rtpTimestamp' in metadata) { |
| assert_equals(typeof metadata.rtpTimestamp, "number", "rtpTimestamp should be a number"); |
| assert_greater_than(metadata.rtpTimestamp, 0, "rtpTimestamp should be non-zero"); |
| assert_true(true, "rtpTimestamp present in VideoFrame metadata") |
| } else { |
| assert_true(true, "rtpTimestamp not present in VideoFrame metadata. Skipping validation because feature may be disabled."); |
| } |
| |
| frame.close(); |
| receiverTrack.stop(); |
| track.stop(); |
| senderPc.close(); |
| receiverPc.close(); |
| }, "Check VideoFrame.metadata.rtpTimestamp only when feature is enabled"); |
| </script> |