blob: e7a29acff6370ed9d81832ab7469496204be40ec [file] [log] [blame]
// META: global=window,dedicatedworker
function makeI420_4x2() {
const yData = new Uint8Array([
1, 2, 3, 4,
5, 6, 7, 8,
]);
const uData = new Uint8Array([
9, 10,
]);
const vData = new Uint8Array([
11, 12,
]);
const planes = [
{data: yData, stride: 4},
{data: uData, stride: 2},
{data: vData, stride: 2},
];
const init = {
format: 'I420',
timestamp: 0,
codedWidth: 4,
codedHeight: 2,
};
return new VideoFrame(planes, init);
}
function makeRGBA_2x2() {
const rgbaData = new Uint8Array([
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16,
]);
const planes = [
{data: rgbaData, stride: 8},
];
const init = {
format: 'ABGR',
timestamp: 0,
codedWidth: 2,
codedHeight: 2,
};
// TODO(sandersd): Should be RGBA but the IDL is reversed right now.
return new VideoFrame(planes, init);
}
function assert_buffer_equals(actual, expected) {
assert_true(actual instanceof Uint8Array, 'actual instanceof Uint8Array');
assert_true(expected instanceof Uint8Array, 'buffer instanceof Uint8Array');
assert_equals(actual.length, expected.length, 'buffer length');
for (let i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
assert_equals(actual[i], expected[i], 'buffer contents at index ' + i);
}
}
}
function assert_layout_equals(actual, expected) {
assert_equals(actual.length, expected.length, 'layout planes');
for (let i = 0; i < actual.length; i++) {
assert_object_equals(actual[i], expected[i], 'plane ' + i + ' layout');
}
}
promise_test(async t => {
const frame = makeI420_4x2();
const expectedLayout = [
{offset: 0, stride: 4},
{offset: 8, stride: 2},
{offset: 10, stride: 2},
];
const expectedData = new Uint8Array([
1, 2, 3, 4, // y
5, 6, 7, 8,
9, 10, // u
11, 12 // v
]);
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 I420 frame.');
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 = makeI420_4x2();
const data = new Uint8Array(11);
await promise_rejects_dom(t, 'ConstraintError', frame.copyTo(data));
}, 'Test undersized buffer.');
promise_test(async t => {
const frame = makeI420_4x2();
const options = {
layout: [{offset: 0, stride: 4}],
};
assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
const data = new Uint8Array(12);
await promise_rejects_dom(t, 'ConstraintError', 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 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 stride and offset with padding.');
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_dom('ConstraintError', () => frame.allocationSize(options));
const data = new Uint8Array(12);
await promise_rejects_dom(t, 'ConstraintError', 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_dom('ConstraintError', () => frame.allocationSize(options));
const data = new Uint8Array(12);
await promise_rejects_dom(t, 'ConstraintError', 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: {left: 0, top: 0, width: 4, height: 0},
};
assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
const data = new Uint8Array(12);
await promise_rejects_dom(t, 'ConstraintError', frame.copyTo(data, options));
}, 'Test empty rect.');
promise_test(async t => {
const frame = makeI420_4x2();
const options = {
rect: {left: 0, top: 0, width: 4, height: 1},
};
assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
const data = new Uint8Array(12);
await promise_rejects_dom(t, 'ConstraintError', frame.copyTo(data, options));
}, 'Test unaligned rect.');
promise_test(async t => {
const frame = makeI420_4x2();
const options = {
rect: {left: 2, top: 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: {left: 0, top: 0, width: 4, height: 4},
};
assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
const data = new Uint8Array(12);
await promise_rejects_dom(t, 'ConstraintError', frame.copyTo(data, options));
}, 'Test invalid rect.');