openvidu-test-e2e: decode AV1 recordings one frame at a time

av1TrackEgressTest's L3T3 case failed in every CI run on the mediasoup
engine: "Every presented packet must decode to one frame" (174 of 178,
171 of 175). The recordings are valid. The egress recorded part of the
track on S1, below the top spatial layer of the sequence header. Run
with frame threading (ffmpeg's default), dav1d outputs no picture for
some temporal units of that part, since Matroska has no temporal
delimiters to close a unit. The 4 frames missing in each file were T2
frames of the S1 part.

assertHealthyVideoRecording now runs libdav1d with -max_frame_delay 1,
which decodes one frame at a time, as WebRTC receivers do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pull/926/merge
pabloFuente 2026-11-02 12:16:01 +01:00
parent 1e3be671e0
commit dd7696e7c6
1 changed files with 6 additions and 2 deletions

View File

@ -1233,12 +1233,16 @@ public class AbstractOpenViduTestappE2eTest extends OpenViduTestE2e {
// Decode every frame: no errors, the picture moves (Chrome's fake camera changes // Decode every frame: no errors, the picture moves (Chrome's fake camera changes
// on every frame) and reaches the published size. VP9 goes through libvpx, the // on every frame) and reaches the published size. VP9 goes through libvpx, the
// decoder of browsers and GStreamer: FFmpeg's own shows only the base layer of a // decoder of browsers and GStreamer: FFmpeg's own shows only the base layer of a
// VP9 SVC superframe. AV1 goes through dav1d: FFmpeg's own needs hardware // VP9 SVC superframe. AV1 goes through dav1d: FFmpeg's own needs hardware. It
// decodes one frame at a time, as WebRTC receivers do: with frame threading, a
// temporal unit of an SVC track recorded below the top spatial layer of its
// sequence header sometimes outputs no picture, since Matroska has no temporal
// delimiters to close the unit (4 T2 frames of the S1 part of an L3T3 track)
List<String> command = new ArrayList<>(List.of("ffmpeg", "-nostdin", "-loglevel", "level+info")); List<String> command = new ArrayList<>(List.of("ffmpeg", "-nostdin", "-loglevel", "level+info"));
if ("vp9".equals(codec)) { if ("vp9".equals(codec)) {
command.addAll(List.of("-c:v", "libvpx-vp9")); command.addAll(List.of("-c:v", "libvpx-vp9"));
} else if ("av1".equals(codec)) { } else if ("av1".equals(codec)) {
command.addAll(List.of("-c:v", "libdav1d")); command.addAll(List.of("-c:v", "libdav1d", "-max_frame_delay", "1"));
} }
command.addAll(List.of("-i", file.toString(), "-map", "0:v", "-vf", "showinfo", "-fps_mode", "passthrough", command.addAll(List.of("-i", file.toString(), "-map", "0:v", "-vf", "showinfo", "-fps_mode", "passthrough",
"-enc_time_base", "demux", "-f", "null", "-")); "-enc_time_base", "demux", "-f", "null", "-"));