commit 3de7a3b689c92aac4b7ae27904161b7c1a1ec87f
parent 610c158027a5ad65c74edb13396c2064a6586906
Author: Dale Curtis <dalecurtis@chromium.org>
Date: Mon, 10 Nov 2025 22:18:20 +0000
Bug 1998771 [wpt PR 55919] - [WebCodecs] Route interlaced H.264 content to the software decoder, a=testonly
Automatic update from web-platform-tests
[WebCodecs] Route interlaced H.264 content to the software decoder
None of our hardware decoders support interlaced decoding, so we
should route this content to the software decoder.
The wrinkle is that there's no information in the codec string
which would tell us that the content is interlaced. For AVC content
we can peek at the description, but for annex-b content we won't
know until the first decode() call.
Given how rare this content is, it's not worth holding all annex-b
configure() calls until the first decode().
As such, this fix only works for AVC formatted content, annex-b
content will continue to throw a decoding error; though I've
promoted the DVLOG to a DLOG to help identify this case more
quickly in the future.
Bug: 456919096
Change-Id: I8a5578e3abdf6a018316931f883796d84f080d8b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7115500
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Eugene Zemtsov <eugene@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1541313}
--
wpt-commits: ba6d2f9a0c3bbe8fa7f28df932f4de31cf19d91a
wpt-pr: 55919
Diffstat:
4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/testing/web-platform/tests/webcodecs/README.md b/testing/web-platform/tests/webcodecs/README.md
@@ -101,6 +101,11 @@ Used a [custom tool](https://storage.googleapis.com/dalecurtis/avif2mp4.html) to
ffmpeg -f lavfi -i testsrc=rate=10:n=1 -t 1 -pix_fmt yuv420p -vcodec h264 -tune zerolatency h264.mp4
```
+### h264_interlaced.mp4
+```
+ffmpeg -f lavfi -i testsrc=rate=10:n=1 -t 1 -vcodec h264 -vf "setfield=tff,format=yuv420p" -flags +ilme+ildct -top 1 h264_interlaced.mp4
+```
+
### h264_sei.mp4
Similar to the construction of `h264.mp4`, but produces a file where the 5th
frame is an SEI recovery point with a `recovery_frame_cnt=0`.
diff --git a/testing/web-platform/tests/webcodecs/h264_interlaced.mp4 b/testing/web-platform/tests/webcodecs/h264_interlaced.mp4
Binary files differ.
diff --git a/testing/web-platform/tests/webcodecs/videoDecoder-codec-specific-setup.js b/testing/web-platform/tests/webcodecs/videoDecoder-codec-specific-setup.js
@@ -166,6 +166,28 @@ const H265_ANNEXB_DATA = {
]
};
+// Note: We only test AVC format since with AnnexB there's not enough
+// information ahead of the first decode() call to determine if the content is
+// interlaced or not.
+const H264_INTERLACED_AVC_DATA = {
+ src: 'h264_interlaced.mp4',
+ config: {
+ codec: 'avc1.64000b',
+ description: {offset: 7501, size: 47},
+ codedWidth: 320,
+ codedHeight: 240,
+ displayAspectWidth: 320,
+ displayAspectHeight: 240,
+ },
+ chunks: [
+ {offset: 48, size: 4091}, {offset: 4139, size: 949},
+ {offset: 5088, size: 260}, {offset: 5348, size: 134},
+ {offset: 5482, size: 111}, {offset: 5593, size: 660},
+ {offset: 6253, size: 197}, {offset: 6450, size: 96},
+ {offset: 6546, size: 159}, {offset: 6705, size: 277}
+ ]
+};
+
// Allows mutating `callbacks` after constructing the VideoDecoder, wraps calls
// in t.step().
function createVideoDecoder(t, callbacks) {
@@ -229,6 +251,7 @@ promise_setup(async () => {
'?vp9': VP9_DATA,
'?h264_avc': H264_AVC_DATA,
'?h264_sei_avc': H264_SEI_AVC_DATA,
+ '?h264_interlaced_avc': H264_INTERLACED_AVC_DATA,
'?h264_annexb': H264_ANNEXB_DATA,
'?h264_sei_annexb': H264_SEI_ANNEXB_DATA,
'?h265_hevc': H265_HEVC_DATA,
diff --git a/testing/web-platform/tests/webcodecs/videoDecoder-interlaced-h264.https.any.js b/testing/web-platform/tests/webcodecs/videoDecoder-interlaced-h264.https.any.js
@@ -0,0 +1,22 @@
+// META: global=window,dedicatedworker
+// META: script=videoDecoder-codec-specific-setup.js
+// META: variant=?h264_interlaced_avc
+
+promise_test(async t => {
+ await checkImplements();
+
+ const callbacks = {};
+ const decoder = createVideoDecoder(t, callbacks);
+ decoder.configure(CONFIG);
+ decoder.decode(CHUNKS[0]);
+
+ let outputs = 0;
+ callbacks.output = frame => {
+ outputs++;
+ assert_equals(frame.timestamp, 0, 'timestamp');
+ frame.close();
+ };
+
+ await decoder.flush();
+ assert_equals(outputs, 1, 'outputs');
+}, 'Test decoding h.264 interlaced content');