1 // META: title=VideoTrackGenerator tests.
3 importScripts("/resources/testharness.js");
5 const pixelColour = [50, 100, 150, 255];
8 function makeVideoFrame(timestamp) {
9 const canvas = new OffscreenCanvas(width, height);
11 const ctx = canvas.getContext('2d', {alpha: false});
12 ctx.fillStyle = `rgba(${pixelColour.join()})`;
13 ctx.fillRect(0, 0, width, height);
15 return new VideoFrame(canvas, {timestamp, alpha: 'discard'});
18 promise_test(async t => {
19 const videoFrame = makeVideoFrame(1);
20 const originalWidth = videoFrame.displayWidth;
21 const originalHeight = videoFrame.displayHeight;
22 const originalTimestamp = videoFrame.timestamp;
23 const generator = new VideoTrackGenerator();
24 t.add_cleanup(() => generator.track.stop());
26 // Use a MediaStreamTrackProcessor as a sink for |generator| to verify
27 // that |processor| actually forwards the frames written to its writable
29 const processor = new MediaStreamTrackProcessor(generator);
30 const reader = processor.readable.getReader();
31 const readerPromise = new Promise(async resolve => {
32 const result = await reader.read();
33 t.add_cleanup(() => result.value.close());
35 assert_equals(result.value.displayWidth, originalWidth);
36 assert_equals(result.value.displayHeight, originalHeight);
37 assert_equals(result.value.timestamp, originalTimestamp);
42 generator.writable.getWriter().write(videoFrame);
44 }, 'Tests that VideoTrackGenerator forwards frames to sink');
46 promise_test(async t => {
47 const generator = new VideoTrackGenerator();
48 t.add_cleanup(() => generator.track.stop());
50 const writer = generator.writable.getWriter();
51 const frame = makeVideoFrame(1);
52 await writer.write(frame);
54 assert_equals(generator.track.kind, "video");
55 assert_equals(generator.track.readyState, "live");
56 }, "Tests that creating a VideoTrackGenerator works as expected");
58 promise_test(async t => {
59 const generator = new VideoTrackGenerator();
60 t.add_cleanup(() => generator.track.stop());
62 const writer = generator.writable.getWriter();
63 const frame = makeVideoFrame(1);
64 await writer.write(frame);
66 assert_throws_dom("InvalidStateError", () => frame.clone(), "VideoFrame wasn't destroyed on write.");
67 }, "Tests that VideoFrames are destroyed on write.");
69 promise_test(async t => {
70 const generator = new VideoTrackGenerator();
71 t.add_cleanup(() => generator.track.stop());
73 const writer = generator.writable.getWriter();
74 const frame = makeVideoFrame(1);
75 t.add_cleanup(() => frame.close());
76 assert_throws_js(TypeError, writer.write(frame));
77 }, "Mismatched frame and generator kind throws on write.");
79 promise_test(async t => {
80 const generator = new VideoTrackGenerator();
81 t.add_cleanup(() => generator.track.stop());
83 // Use a MediaStreamTrackProcessor as a sink for |generator| to verify
84 // that |processor| actually forwards the frames written to its writable
86 const processor = new MediaStreamTrackProcessor(generator);
87 const reader = processor.readable.getReader();
88 const videoFrame = makeVideoFrame(1);
90 const writer = generator.writable.getWriter();
91 const videoFrame1 = makeVideoFrame(1);
92 writer.write(videoFrame1);
93 const result1 = await reader.read();
94 t.add_cleanup(() => result1.value.close());
95 assert_equals(result1.value.timestamp, 1);
96 generator.muted = true;
98 // This frame is expected to be discarded.
99 const videoFrame2 = makeVideoFrame(2);
100 writer.write(videoFrame2);
101 generator.muted = false;
103 const videoFrame3 = makeVideoFrame(3);
104 writer.write(videoFrame3);
105 const result3 = await reader.read();
106 t.add_cleanup(() => result3.value.close());
107 assert_equals(result3.value.timestamp, 3);
109 // Set up a read ahead of time, then mute, enqueue and unmute.
110 const promise5 = reader.read();
111 generator.muted = true;
112 writer.write(makeVideoFrame(4)); // Expected to be discarded.
113 generator.muted = false;
114 writer.write(makeVideoFrame(5));
115 const result5 = await promise5;
116 t.add_cleanup(() => result5.value.close());
117 assert_equals(result5.value.timestamp, 5);
118 }, 'Tests that VideoTrackGenerator forwards frames only when unmuted');