319 lines
10 KiB
JavaScript
319 lines
10 KiB
JavaScript
// META: global=window,dedicatedworker
|
|
|
|
promise_test(async t => {
|
|
let fmt = 'RGBA';
|
|
const rgb_plane = [
|
|
0xBA, 0xDF, 0x00, 0xD0, 0xBA, 0xDF, 0x01, 0xD0, 0xBA, 0xDF, 0x02, 0xD0,
|
|
0xBA, 0xDF, 0x03, 0xD0
|
|
];
|
|
let data = new Uint8Array(rgb_plane);
|
|
let unused_buffer = new ArrayBuffer(123);
|
|
let init = {
|
|
format: fmt,
|
|
timestamp: 1234,
|
|
codedWidth: 2,
|
|
codedHeight: 2,
|
|
visibleRect: {x: 0, y: 0, width: 2, height: 2},
|
|
transfer: [data.buffer, unused_buffer]
|
|
};
|
|
assert_equals(data.length, 16, 'data.length');
|
|
assert_equals(unused_buffer.byteLength, 123, 'unused_buffer.byteLength');
|
|
|
|
let frame = new VideoFrame(data, init);
|
|
assert_equals(frame.format, fmt, 'format');
|
|
assert_equals(data.length, 0, 'data.length after detach');
|
|
assert_equals(unused_buffer.byteLength, 0, 'unused_buffer after detach');
|
|
|
|
const options = {
|
|
rect: {x: 0, y: 0, width: init.codedWidth, height: init.codedHeight}
|
|
};
|
|
let size = frame.allocationSize(options);
|
|
let output_data = new Uint8Array(size);
|
|
let layout = await frame.copyTo(output_data, options);
|
|
let expected_data = new Uint8Array(rgb_plane);
|
|
assert_equals(expected_data.length, size, 'expected_data size');
|
|
for (let i = 0; i < size; i++) {
|
|
assert_equals(expected_data[i], output_data[i], `expected_data[${i}]`);
|
|
}
|
|
|
|
frame.close();
|
|
}, 'Test transfering ArrayBuffer to VideoFrame');
|
|
|
|
|
|
promise_test(async t => {
|
|
let fmt = 'I420';
|
|
const i420_planes = [0xAA, 0xBB, 0xCC];
|
|
let data = new Uint8Array(i420_planes);
|
|
let init = {
|
|
format: fmt,
|
|
timestamp: 1234,
|
|
codedWidth: 1,
|
|
codedHeight: 1,
|
|
visibleRect: {x: 0, y: 0, width: 1, height: 1},
|
|
transfer: [data.buffer]
|
|
};
|
|
|
|
let frame = new VideoFrame(data, init);
|
|
assert_equals(data.length, 0, 'data.length after detach');
|
|
|
|
const options = {
|
|
rect: {x: 0, y: 0, width: init.codedWidth, height: init.codedHeight}
|
|
};
|
|
let size = frame.allocationSize(options);
|
|
let output_data = new Uint8Array(size);
|
|
let layout = await frame.copyTo(output_data, options);
|
|
let expected_data = new Uint8Array(i420_planes);
|
|
assert_equals(expected_data.length, size, 'expected_data size');
|
|
assert_equals(layout[0].stride, 1, 'layout[0].stride');
|
|
assert_equals(layout[0].offset, 0, 'layout[0].offset');
|
|
assert_equals(layout[1].stride, 1, 'layout[1].stride');
|
|
assert_equals(layout[1].offset, 1, 'layout[1].offset');
|
|
assert_equals(layout[2].stride, 1, 'layout[2].stride');
|
|
assert_equals(layout[2].offset, 2, 'layout[2].offset');
|
|
assert_equals(expected_data.length, size, 'expected_data size');
|
|
for (let i = 0; i < size; i++) {
|
|
assert_equals(expected_data[i], output_data[i], `expected_data[${i}]`);
|
|
}
|
|
|
|
frame.close();
|
|
}, 'Test transfering buffers to VideoFrame with uneven samples');
|
|
|
|
promise_test(async t => {
|
|
const rgb_plane = [
|
|
0xBA, 0xDF, 0x00, 0xD0, 0xBA, 0xDF, 0x01, 0xD0, 0xBA, 0xDF, 0x02, 0xD0,
|
|
0xBA, 0xDF, 0x03, 0xD0
|
|
];
|
|
let data = new Uint8Array(rgb_plane);
|
|
let detached_buffer = new ArrayBuffer(123);
|
|
|
|
// Detach `detached_buffer`
|
|
structuredClone({x: detached_buffer}, {transfer: [detached_buffer]});
|
|
|
|
let init = {
|
|
format: 'RGBA',
|
|
timestamp: 1234,
|
|
codedWidth: 2,
|
|
codedHeight: 2,
|
|
visibleRect: {x: 0, y: 0, width: 2, height: 2},
|
|
transfer: [data.buffer, detached_buffer]
|
|
};
|
|
|
|
try {
|
|
new VideoFrame(data, init);
|
|
} catch (error) {
|
|
assert_equals(error.name, 'DataCloneError', 'error.name');
|
|
}
|
|
// `data.buffer` didn't get detached
|
|
assert_equals(data.length, 16, 'data.length');
|
|
}, 'Test transfering detached buffer to VideoFrame');
|
|
|
|
|
|
promise_test(async t => {
|
|
const rgb_plane = [
|
|
0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
|
|
0xEE, 0xEE, 0xEE, 0xEE
|
|
];
|
|
const padding_size = 6;
|
|
let arraybuffer = new ArrayBuffer(padding_size + 16 /* pixels */);
|
|
let data = new Uint8Array(arraybuffer, padding_size);
|
|
data.set(rgb_plane);
|
|
|
|
let init = {
|
|
format: 'RGBA',
|
|
timestamp: 1234,
|
|
codedWidth: 2,
|
|
codedHeight: 2,
|
|
visibleRect: {x: 0, y: 0, width: 2, height: 2},
|
|
transfer: [arraybuffer]
|
|
};
|
|
|
|
let frame = new VideoFrame(data, init);
|
|
assert_equals(data.length, 0, 'data.length after detach');
|
|
assert_equals(arraybuffer.byteLength, 0, 'arraybuffer after detach');
|
|
|
|
const options = {
|
|
rect: {x: 0, y: 0, width: init.codedWidth, height: init.codedHeight}
|
|
};
|
|
let size = frame.allocationSize(options);
|
|
let output_data = new Uint8Array(size);
|
|
let layout = await frame.copyTo(output_data, options);
|
|
for (let i = 0; i < size; i++) {
|
|
assert_equals(output_data[i], 0xEE, `output_data[${i}]`);
|
|
}
|
|
}, 'Test transfering view of an ArrayBuffer to VideoFrame');
|
|
|
|
promise_test(async t => {
|
|
const rgb_plane = [
|
|
0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
|
|
0xEE, 0xEE, 0xEE, 0xEE
|
|
];
|
|
const padding_size = 6;
|
|
let arraybuffer = new ArrayBuffer(padding_size + 16 /* pixels */);
|
|
let data = new Uint8Array(arraybuffer, padding_size);
|
|
data.set(rgb_plane);
|
|
|
|
let init = {
|
|
format: 'RGBA',
|
|
timestamp: 1234,
|
|
codedWidth: 2,
|
|
codedHeight: 2,
|
|
visibleRect: {x: 0, y: 0, width: 2, height: 2},
|
|
transfer: [arraybuffer, arraybuffer]
|
|
};
|
|
|
|
try {
|
|
new VideoFrame(data, init);
|
|
} catch (error) {
|
|
assert_equals(error.name, 'DataCloneError', 'error.name');
|
|
}
|
|
// `data.buffer` didn't get detached
|
|
assert_equals(data.length, 16, 'data.length');
|
|
}, 'Test transfering same array buffer twice');
|
|
|
|
promise_test(async t => {
|
|
const bytes = [ 0xBA, 0xDF, 0x00, 0xD0, 0xBA, 0xDF, 0x01, 0xD0, 0xBA, 0xDF ];
|
|
let data = new Uint8Array(bytes);
|
|
let unused_buffer = new ArrayBuffer(123);
|
|
let init = {
|
|
type: 'key',
|
|
timestamp: 0,
|
|
data: data,
|
|
transfer: [data.buffer, unused_buffer]
|
|
};
|
|
|
|
assert_equals(data.length, 10, 'data.length');
|
|
assert_equals(unused_buffer.byteLength, 123, 'unused_buffer.byteLength');
|
|
|
|
let chunk = new EncodedAudioChunk(init);
|
|
assert_equals(data.length, 0, 'data.length after detach');
|
|
assert_equals(unused_buffer.byteLength, 0, 'unused_buffer after detach');
|
|
|
|
let output_data = new Uint8Array(chunk.byteLength);
|
|
chunk.copyTo(output_data);
|
|
let expected_data = new Uint8Array(bytes);
|
|
assert_equals(expected_data.length, chunk.byteLength, 'expected_data size');
|
|
for (let i = 0; i < chunk.byteLength; i++) {
|
|
assert_equals(expected_data[i], output_data[i], `expected_data[${i}]`);
|
|
}
|
|
}, 'Test transfering ArrayBuffer to EncodedAudioChunk');
|
|
|
|
promise_test(async t => {
|
|
const bytes = [ 0xBA, 0xDF, 0x00, 0xD0, 0xBA, 0xDF, 0x01, 0xD0, 0xBA, 0xDF ];
|
|
let data = new Uint8Array(bytes);
|
|
let unused_buffer = new ArrayBuffer(123);
|
|
let init = {
|
|
type: 'key',
|
|
timestamp: 0,
|
|
data: data,
|
|
transfer: [data.buffer, unused_buffer]
|
|
};
|
|
|
|
assert_equals(data.length, 10, 'data.length');
|
|
assert_equals(unused_buffer.byteLength, 123, 'unused_buffer.byteLength');
|
|
|
|
let chunk = new EncodedVideoChunk(init);
|
|
assert_equals(data.length, 0, 'data.length after detach');
|
|
assert_equals(unused_buffer.byteLength, 0, 'unused_buffer after detach');
|
|
|
|
let output_data = new Uint8Array(chunk.byteLength);
|
|
chunk.copyTo(output_data);
|
|
let expected_data = new Uint8Array(bytes);
|
|
assert_equals(expected_data.length, chunk.byteLength, 'expected_data size');
|
|
for (let i = 0; i < chunk.byteLength; i++) {
|
|
assert_equals(expected_data[i], output_data[i], `expected_data[${i}]`);
|
|
}
|
|
}, 'Test transfering ArrayBuffer to EncodedVideoChunk');
|
|
|
|
promise_test(async t => {
|
|
const bytes = [0xBA, 0xDF, 0x00, 0xD0, 0xBA, 0xDF, 0x01, 0xD0, 0xBA, 0xDF];
|
|
let data = new Uint8Array(bytes);
|
|
let unused_buffer = new ArrayBuffer(123);
|
|
let init = {
|
|
type: 'key',
|
|
timestamp: 0,
|
|
numberOfFrames: data.length,
|
|
numberOfChannels: 1,
|
|
sampleRate: 10000,
|
|
format: 'u8',
|
|
data: data,
|
|
transfer: [data.buffer, unused_buffer]
|
|
};
|
|
|
|
assert_equals(data.length, 10, 'data.length');
|
|
assert_equals(unused_buffer.byteLength, 123, 'unused_buffer.byteLength');
|
|
|
|
let audio_data = new AudioData(init);
|
|
assert_equals(data.length, 0, 'data.length after detach');
|
|
assert_equals(unused_buffer.byteLength, 0, 'unused_buffer after detach');
|
|
|
|
let readback_data = new Uint8Array(bytes.length);
|
|
audio_data.copyTo(readback_data, {planeIndex: 0, format: 'u8'});
|
|
let expected_data = new Uint8Array(bytes);
|
|
for (let i = 0; i < expected_data.length; i++) {
|
|
assert_equals(expected_data[i], readback_data[i], `expected_data[${i}]`);
|
|
}
|
|
}, 'Test transfering ArrayBuffer to AudioData');
|
|
|
|
promise_test(async t => {
|
|
let sample_rate = 48000;
|
|
let total_duration_s = 1;
|
|
let data_count = 10;
|
|
let chunks = [];
|
|
|
|
let encoder_init = {
|
|
error: t.unreached_func('Encoder error'),
|
|
output: (chunk, metadata) => {
|
|
chunks.push(chunk);
|
|
}
|
|
};
|
|
let encoder = new AudioEncoder(encoder_init);
|
|
let config = {
|
|
codec: 'opus',
|
|
sampleRate: sample_rate,
|
|
numberOfChannels: 2,
|
|
bitrate: 256000, // 256kbit
|
|
};
|
|
encoder.configure(config);
|
|
|
|
let timestamp_us = 0;
|
|
const data_duration_s = total_duration_s / data_count;
|
|
const frames = data_duration_s * config.sampleRate;
|
|
for (let i = 0; i < data_count; i++) {
|
|
let buffer = new Float32Array(frames * config.numberOfChannels);
|
|
let data = new AudioData({
|
|
timestamp: timestamp_us,
|
|
data: buffer,
|
|
numberOfChannels: config.numberOfChannels,
|
|
numberOfFrames: frames,
|
|
sampleRate: config.sampleRate,
|
|
format: 'f32-planar',
|
|
transfer: [buffer.buffer]
|
|
});
|
|
timestamp_us += data_duration_s * 1_000_000;
|
|
assert_equals(buffer.length, 0, 'buffer.length after detach');
|
|
encoder.encode(data);
|
|
}
|
|
await encoder.flush();
|
|
encoder.close();
|
|
assert_greater_than(chunks.length, 0);
|
|
}, 'Encoding from AudioData with transferred buffer');
|
|
|
|
|
|
promise_test(async t => {
|
|
let unused_buffer = new ArrayBuffer(123);
|
|
let support = await ImageDecoder.isTypeSupported('image/png');
|
|
assert_implements_optional(
|
|
support, 'Optional codec image/png not supported.');
|
|
let buffer = await fetch('four-colors.png').then(response => {
|
|
return response.arrayBuffer();
|
|
});
|
|
|
|
let decoder = new ImageDecoder(
|
|
{data: buffer, type: 'image/png', transfer: [buffer, unused_buffer]});
|
|
assert_equals(buffer.byteLength, 0, 'buffer.byteLength after detach');
|
|
assert_equals(unused_buffer.byteLength, 0, 'unused_buffer after detach');
|
|
|
|
let result = await decoder.decode();
|
|
assert_equals(result.image.displayWidth, 320);
|
|
assert_equals(result.image.displayHeight, 240);
|
|
}, 'Test transfering ArrayBuffer to ImageDecoder.');
|