forked from mirrors/gecko-dev
Automatic update from web-platform-tests [webcodecs] Allow odd coded sizes Allow odd (not sample-aligned) sizes in VideoFrame coded size and copyTo() |rect|. Sizes are rounded up in subsampled planes. See https://github.com/w3c/webcodecs/issues/638. Bug: 1413632 Change-Id: I23679e5b2cd06d1512d37ff57f4f4d40c47317e8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4443092 Commit-Queue: Dan Sanders <sandersd@chromium.org> Reviewed-by: Eugene Zemtsov <eugene@chromium.org> Cr-Commit-Position: refs/heads/main@{#1200409} -- wpt-commits: 2a504c3e6ed8512a1cb3ad44da0a121598d3b820 wpt-pr: 39630
312 lines
8.8 KiB
JavaScript
312 lines
8.8 KiB
JavaScript
// META: global=window,dedicatedworker
|
|
// META: script=/webcodecs/videoFrame-utils.js
|
|
|
|
function makeRGBA_2x2() {
|
|
const data = new Uint8Array([
|
|
1,2,3,4, 5,6,7,8,
|
|
9,10,11,12, 13,14,15,16,
|
|
]);
|
|
const init = {
|
|
format: 'RGBA',
|
|
timestamp: 0,
|
|
codedWidth: 2,
|
|
codedHeight: 2,
|
|
};
|
|
return new VideoFrame(data, init);
|
|
}
|
|
|
|
const NV12_DATA = new Uint8Array([
|
|
1, 2, 3, 4, // y
|
|
5, 6, 7, 8,
|
|
9, 10, 11, 12 // uv
|
|
]);
|
|
|
|
function makeNV12_4x2() {
|
|
const init = {
|
|
format: 'NV12',
|
|
timestamp: 0,
|
|
codedWidth: 4,
|
|
codedHeight: 2,
|
|
};
|
|
return new VideoFrame(NV12_DATA, init);
|
|
}
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
frame.close();
|
|
|
|
assert_throws_dom('InvalidStateError', () => frame.allocationSize(), 'allocationSize()');
|
|
|
|
let data = new Uint8Array(12);
|
|
await promise_rejects_dom(t, 'InvalidStateError', frame.copyTo(data), 'copyTo()');
|
|
}, 'Test closed frame.');
|
|
|
|
promise_test(async t => {
|
|
const destination = new ArrayBuffer(I420_DATA.length);
|
|
await testI420_4x2_copyTo(destination);
|
|
}, 'Test copying I420 frame to a non-shared ArrayBuffer');
|
|
|
|
promise_test(async t => {
|
|
const destination = new Uint8Array(I420_DATA.length);
|
|
await testI420_4x2_copyTo(destination);
|
|
}, 'Test copying I420 frame to a non-shared ArrayBufferView');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeRGBA_2x2();
|
|
const expectedLayout = [
|
|
{offset: 0, stride: 8},
|
|
];
|
|
const expectedData = new Uint8Array([
|
|
1,2,3,4, 5,6,7,8,
|
|
9,10,11,12, 13,14,15,16,
|
|
]);
|
|
assert_equals(frame.allocationSize(), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data);
|
|
assert_layout_equals(layout, expectedLayout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test RGBA frame.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeNV12_4x2();
|
|
const expectedLayout = [
|
|
{offset: 0, stride: 4},
|
|
{offset: 8, stride: 4},
|
|
];
|
|
const expectedData = new Uint8Array([
|
|
1,2,3,4,
|
|
5,6,7,8,
|
|
9,10,11,12
|
|
]);
|
|
assert_equals(frame.allocationSize(), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data);
|
|
assert_layout_equals(layout, expectedLayout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test NV12 frame.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const data = new Uint8Array(11);
|
|
await promise_rejects_js(t, TypeError, frame.copyTo(data));
|
|
}, 'Test undersized buffer.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
layout: [{offset: 0, stride: 4}],
|
|
};
|
|
assert_throws_js(TypeError, () => frame.allocationSize(options));
|
|
const data = new Uint8Array(12);
|
|
await promise_rejects_js(t, TypeError, frame.copyTo(data, options));
|
|
}, 'Test incorrect plane count.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
layout: [
|
|
{offset: 4, stride: 4},
|
|
{offset: 0, stride: 2},
|
|
{offset: 2, stride: 2},
|
|
],
|
|
};
|
|
const expectedData = new Uint8Array([
|
|
9, 10, // u
|
|
11, 12, // v
|
|
1, 2, 3, 4, // y
|
|
5, 6, 7, 8,
|
|
]);
|
|
assert_equals(frame.allocationSize(options), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data, options);
|
|
assert_layout_equals(layout, options.layout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test I420 stride and offset work.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
layout: [
|
|
{offset: 9, stride: 5},
|
|
{offset: 1, stride: 3},
|
|
{offset: 5, stride: 3},
|
|
],
|
|
};
|
|
const expectedData = new Uint8Array([
|
|
0,
|
|
9, 10, 0, // u
|
|
0,
|
|
11, 12, 0, // v
|
|
0,
|
|
1, 2, 3, 4, 0, // y
|
|
5, 6, 7, 8, 0,
|
|
]);
|
|
assert_equals(frame.allocationSize(options), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data, options);
|
|
assert_layout_equals(layout, options.layout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test I420 stride and offset with padding.');
|
|
|
|
promise_test(async t => {
|
|
const init = {
|
|
format: 'I420A',
|
|
timestamp: 0,
|
|
codedWidth: 4,
|
|
codedHeight: 2,
|
|
};
|
|
const buf = new Uint8Array([
|
|
1, 2, 3, 4, // y
|
|
5, 6, 7, 8,
|
|
9, 10, // u
|
|
11, 12, // v
|
|
13, 14, 15, 16, // a
|
|
17, 18, 19, 20,
|
|
]);
|
|
const frame = new VideoFrame(buf, init);
|
|
const options = {
|
|
layout: [
|
|
{offset: 12, stride: 4},
|
|
{offset: 8, stride: 2},
|
|
{offset: 10, stride: 2},
|
|
{offset: 0, stride: 4},
|
|
],
|
|
};
|
|
const expectedData = new Uint8Array([
|
|
13, 14, 15, 16, // a
|
|
17, 18, 19, 20,
|
|
9, 10, // u
|
|
11, 12, // v
|
|
1, 2, 3, 4, // y
|
|
5, 6, 7, 8,
|
|
]);
|
|
assert_equals(frame.allocationSize(options), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data, options);
|
|
assert_layout_equals(layout, options.layout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test I420A stride and offset work.');
|
|
|
|
promise_test(async t => {
|
|
const init = {
|
|
format: 'NV12',
|
|
timestamp: 0,
|
|
codedWidth: 4,
|
|
codedHeight: 2,
|
|
};
|
|
const buf = new Uint8Array([
|
|
1, 2, 3, 4, // y
|
|
5, 6, 7, 8,
|
|
9, 10, 11, 12 // uv
|
|
]);
|
|
const frame = new VideoFrame(buf, init);
|
|
const options = {
|
|
layout: [
|
|
{offset: 4, stride: 4},
|
|
{offset: 0, stride: 4},
|
|
],
|
|
};
|
|
const expectedData = new Uint8Array([
|
|
9, 10, 11, 12, // uv
|
|
1, 2, 3, 4, // y
|
|
5, 6, 7, 8
|
|
]);
|
|
assert_equals(frame.allocationSize(options), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data, options);
|
|
assert_layout_equals(layout, options.layout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test NV12 stride and offset work.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
layout: [
|
|
{offset: 0, stride: 1},
|
|
{offset: 8, stride: 2},
|
|
{offset: 10, stride: 2},
|
|
],
|
|
};
|
|
assert_throws_js(TypeError, () => frame.allocationSize(options));
|
|
const data = new Uint8Array(12);
|
|
await promise_rejects_js(t, TypeError, frame.copyTo(data, options));
|
|
}, 'Test invalid stride.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
layout: [
|
|
{offset: 0, stride: 4},
|
|
{offset: 8, stride: 2},
|
|
{offset: 2 ** 32 - 2, stride: 2},
|
|
],
|
|
};
|
|
assert_throws_js(TypeError, () => frame.allocationSize(options));
|
|
const data = new Uint8Array(12);
|
|
await promise_rejects_js(t, TypeError, frame.copyTo(data, options));
|
|
}, 'Test address overflow.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
rect: frame.codedRect,
|
|
};
|
|
const expectedLayout = [
|
|
{offset: 0, stride: 4},
|
|
{offset: 8, stride: 2},
|
|
{offset: 10, stride: 2},
|
|
];
|
|
const expectedData = new Uint8Array([
|
|
1, 2, 3, 4, 5, 6, 7, 8, // y
|
|
9, 10, // u
|
|
11, 12 // v
|
|
]);
|
|
assert_equals(frame.allocationSize(options), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data, options);
|
|
assert_layout_equals(layout, expectedLayout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test codedRect.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
rect: {x: 0, y: 0, width: 4, height: 0},
|
|
};
|
|
assert_throws_js(TypeError, () => frame.allocationSize(options));
|
|
const data = new Uint8Array(12);
|
|
await promise_rejects_js(t, TypeError, frame.copyTo(data, options));
|
|
}, 'Test empty rect.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
rect: {x: 2, y: 0, width: 2, height: 2},
|
|
};
|
|
const expectedLayout = [
|
|
{offset: 0, stride: 2},
|
|
{offset: 4, stride: 1},
|
|
{offset: 5, stride: 1},
|
|
];
|
|
const expectedData = new Uint8Array([
|
|
3, 4, // y
|
|
7, 8,
|
|
10, // u
|
|
12 // v
|
|
]);
|
|
assert_equals(frame.allocationSize(options), expectedData.length, 'allocationSize()');
|
|
const data = new Uint8Array(expectedData.length);
|
|
const layout = await frame.copyTo(data, options);
|
|
assert_layout_equals(layout, expectedLayout);
|
|
assert_buffer_equals(data, expectedData);
|
|
}, 'Test left crop.');
|
|
|
|
promise_test(async t => {
|
|
const frame = makeI420_4x2();
|
|
const options = {
|
|
rect: {x: 0, y: 0, width: 4, height: 4},
|
|
};
|
|
assert_throws_js(TypeError, () => frame.allocationSize(options));
|
|
const data = new Uint8Array(12);
|
|
await promise_rejects_js(t, TypeError, frame.copyTo(data, options));
|
|
}, 'Test invalid rect.');
|