blob: e73e7fd27e262e2ce31b51734eb3a2a388f2290b [file] [edit]
<!DOCTYPE html>
<html>
<header>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src="../resources/gc.js"></script>
</header>
<body>
<script>
function makeOffscreenCanvas(width, height) {
let canvas = new OffscreenCanvas(width, height);
let ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgba(50, 100, 150, 255)';
ctx.fillRect(0, 0, width, height);
return new VideoFrame(canvas, { timestamp: 1 });
}
let chunks = [];
let config;
async function createChunks(encoderConfig) {
chunks = [];
const encoderInit = {
output(chunk, metadata) {
if (metadata.decoderConfig) {
config = metadata.decoderConfig;
}
chunks.push(chunk);
},
error(e) {
reject(e.message);
}
};
const encoder = new VideoEncoder(encoderInit);
encoder.configure(encoderConfig);
const w = encoderConfig.width;
const h = encoderConfig.height;
const frame = makeOffscreenCanvas(w, h);
encoder.encode(frame, { keyFrame: true });
frame.close();
const timer = setInterval(() => gc(), 100);
await encoder.flush();
clearInterval(timer);
}
async function doEncodeDecode(encoderConfig)
{
await createChunks(encoderConfig);
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
const decoder = new VideoDecoder({
// here, we do not do anything with the frame provided to output, so we will not call close.
output() {
resolve();
},
error(e) {
reject(e.message);
}
});
decoder.configure(config);
for (let chunk of chunks)
decoder.decode(chunk);
const timer = setInterval(() => gc(), 100);
await decoder.flush();
await promise;
await new Promise(resolve => setTimeout(resolve, 500));
clearInterval(timer);
}
function listenToConsoleMessages()
{
window.gotVideoFrameConsoleMessage = false;
const messagePromise = new Promise((resolve, reject) => {
if (!window.internals) {
window.gotVideoFrameConsoleMessage = true;
return;
}
internals.setConsoleMessageListener(message => {
window.gotVideoFrameConsoleMessage |= message.includes("A VideoFrame was destroyed");
});
});
}
function didReceiveVideoFrameConsoleMessage()
{
return window.gotVideoFrameConsoleMessage;
}
function doTest(codec, title)
{
const config = { codec };
config.width = 320;
config.height = 200;
config.bitrate = 1000000;
config.framerate = 30;
promise_test(async t => {
listenToConsoleMessages();
let counter = 0;
while (++counter < 50) {
await doEncodeDecode(config);
if (didReceiveVideoFrameConsoleMessage())
break;
}
assert_less_than(counter, 50);
}, title);
}
doTest('vp8', "VP8 codec GC without calling VideoFrame.close");
</script>
</body>
</html>