blob: 36e6a4b1139bc83ea85c45abc5a8bb308bede010 [file] [edit]
<!DOCTYPE html>
<html>
<head>
<title>WebCodecs HEVC HDR (10-bit) decoding</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
</head>
<body>
<script>
const HDR_CODEC = "hev1.2.4.L30.90";
// HEVC Main 10 profile, 32x32, 4:2:0 10-bit, single Annex B keyframe (VPS/SPS/PPS/IDR).
// The SPS VUI signals BT.2020 primaries, SMPTE ST 2084 (PQ) transfer, BT.2020 non-constant luminance matrix, and limited (video) range.
const hevcHdrData = new Uint8Array([
0, 0, 0, 1, 64, 1, 12, 1, 255, 255, 2, 32, 0, 0, 3, 0, 144, 0, 0, 3, 0, 0, 3, 0, 30, 149, 148, 9,
0, 0, 0, 1, 66, 1, 1, 2, 32, 0, 0, 3, 0, 144, 0, 0, 3, 0, 0, 3, 0, 30, 160, 66, 8, 77, 150, 86, 84,
164, 194, 240, 22, 161, 34, 1, 32, 128, 0, 0, 3, 0, 128, 0, 0, 3, 0, 132,
0, 0, 0, 1, 68, 1, 192, 113, 129, 18,
0, 0, 1, 40, 1, 172, 22, 96, 190, 167, 216, 86, 226, 79, 21, 87
]);
promise_test(async () => {
assert_implements(window.VideoDecoder, "VideoDecoder is supported");
const support = await VideoDecoder.isConfigSupported({ codec: HDR_CODEC, codedWidth: 32, codedHeight: 32 });
assert_true(support.supported, "HEVC Main 10 profile is supported");
}, "HEVC Main 10 isConfigSupported");
promise_test(async (t) => {
const frames = [];
const decoder = new VideoDecoder({
output: frame => frames.push(frame),
error: e => assert_unreached(`decode error: ${e.message}`),
});
decoder.configure({ codec: HDR_CODEC, codedWidth: 32, codedHeight: 32 });
decoder.decode(new EncodedVideoChunk({ type: "key", timestamp: 0, data: hevcHdrData }));
await decoder.flush();
assert_equals(frames.length, 1, "one frame decoded");
const frame = frames[0];
assert_equals(frame.codedWidth, 32, "width");
assert_equals(frame.codedHeight, 32, "height");
assert_equals(frame.colorSpace.primaries, "bt2020", "primaries from bitstream");
assert_equals(frame.colorSpace.transfer, "pq", "transfer from bitstream (SMPTE ST 2084)");
assert_equals(frame.colorSpace.matrix, "bt2020-ncl", "matrix from bitstream");
assert_false(frame.colorSpace.fullRange, "limited range from bitstream");
// 10-bit 4:2:0 cannot currently be represented by a VideoPixelFormat value.
assert_equals(frame.format, null, "format is null for unrepresentable 10-bit content");
assert_true(!window.internals?.is10bitsVideoFrame || internals.is10bitsVideoFrame(frame), "frame is actually 10 bits");
const rgba = new Uint8Array(frame.allocationSize({format: "RGBA"}));
await promise_rejects_dom(t, 'NotSupportedError', frame.copyTo(rgba));
promise_test(async t => {
t.add_cleanup(() => frame.close());
await frame.copyTo(rgba, {format: "RGBA"});
}, "copyTo with RGBA works on VideoFrame with null format");
}, "HEVC Main 10 (BT.2020/PQ) decoding surfaces bitstream colorSpace and null format");
</script>
</body>
</html>