| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>WebCodecs AV1 HDR decoding with colorSpace overrides</title> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <script> |
| const HDR_CODEC = "av01.0.04M.08"; |
| let av1Data; |
| |
| promise_test(async () => { |
| assert_implements(window.VideoDecoder, "VideoDecoder is supported"); |
| const config = { codec: HDR_CODEC, codedWidth: 320, codedHeight: 240 }; |
| const support = await VideoDecoder.isConfigSupported(config); |
| assert_true(support.supported, "AV1 (8-bit) is supported"); |
| }, "AV1 isConfigSupported"); |
| |
| promise_test(async () => { |
| // AV1 main profile, level 4.0, Main tier, 8-bit. The bitstream itself carries BT709, video range. |
| const response = await fetch("av1-sdr.bin"); |
| const buffer = await response.arrayBuffer(); |
| // Need to strip the 32-byte IVF file header + 12-byte frame header. |
| av1Data = new Uint8Array(buffer).slice(44); |
| }, "Setup"); |
| |
| async function decodeWithOverride(colorSpace) { |
| const frames = []; |
| const decoder = new VideoDecoder({ |
| output: f => frames.push(f), |
| error: e => assert_unreached(`decode error: ${e.message}`), |
| }); |
| const config = { codec: HDR_CODEC, codedWidth: 320, codedHeight: 240 }; |
| if (colorSpace) |
| config.colorSpace = colorSpace; |
| decoder.configure(config); |
| decoder.decode(new EncodedVideoChunk({ type: "key", timestamp: 0, data: av1Data })); |
| await decoder.flush(); |
| assert_equals(frames.length, 1, "one frame decoded"); |
| return frames[0]; |
| } |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride(); |
| assert_equals(f.colorSpace.primaries, "bt709", "primaries from bitstream"); |
| assert_equals(f.colorSpace.matrix, "bt709", "matrix from bitstream"); |
| assert_false(f.colorSpace.fullRange, "video range from bitstream"); |
| f.close(); |
| }, "AV1 (no override): bitstream colorSpace surfaces"); |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride({ primaries: "smpte170m" }); |
| assert_equals(f.colorSpace.primaries, "smpte170m", "primaries overridden"); |
| assert_equals(f.colorSpace.matrix, "bt709", "matrix preserved from bitstream"); |
| f.close(); |
| }, "AV1 colorSpace override: primaries"); |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride({ matrix: "bt470bg" }); |
| assert_equals(f.colorSpace.primaries, "bt709", "primaries preserved from bitstream"); |
| assert_equals(f.colorSpace.matrix, "bt470bg", "matrix overridden"); |
| f.close(); |
| }, "AV1 colorSpace override: matrix"); |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride({ transfer: "pq" }); |
| assert_equals(f.colorSpace.primaries, "bt709", "primaries preserved from bitstream"); |
| assert_equals(f.colorSpace.matrix, "bt709", "matrix preserved from bitstream"); |
| assert_equals(f.colorSpace.transfer, "pq", "transfer overridden to PQ"); |
| f.close(); |
| }, "AV1 colorSpace override: transfer (pq)"); |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride({ fullRange: true }); |
| assert_equals(f.colorSpace.primaries, "bt709", "primaries preserved from bitstream"); |
| assert_equals(f.colorSpace.matrix, "bt709", "matrix preserved from bitstream"); |
| assert_true(f.colorSpace.fullRange, "range overridden to full"); |
| f.close(); |
| }, "AV1 colorSpace override: fullRange (true)"); |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride({ fullRange: false }); |
| assert_equals(f.colorSpace.primaries, "bt709", "primaries preserved from bitstream"); |
| assert_equals(f.colorSpace.matrix, "bt709", "matrix preserved from bitstream"); |
| assert_false(f.colorSpace.fullRange, "range overridden to video"); |
| f.close(); |
| }, "AV1 colorSpace override: fullRange (false)"); |
| |
| promise_test(async () => { |
| const f = await decodeWithOverride({ fullRange: false, transfer: "pq", matrix: "bt470bg", primaries: "smpte170m" }); |
| assert_equals(f.colorSpace.primaries, "smpte170m", "primaries overriden"); |
| assert_equals(f.colorSpace.matrix, "bt470bg", "matrix overriden"); |
| assert_equals(f.colorSpace.transfer, "pq", "transfer overriden"); |
| assert_false(f.colorSpace.fullRange, "range overridden to video"); |
| f.close(); |
| }, "AV1 colorSpace full override"); |
| </script> |
| </body> |
| </html> |