diff --git a/daemon/src/decoder.c b/daemon/src/decoder.c index e91eb35..a43d6ab 100644 --- a/daemon/src/decoder.c +++ b/daemon/src/decoder.c @@ -132,6 +132,32 @@ static int decoder_open_codec(struct daedalus_decoder *dec, uint32_t codec_id, ctx = fm->avcodec_alloc_context3(codec); if (!ctx) return -ENOMEM; + + /* + * H.264-only: force libavcodec to emit frames in DECODE order + * (one frame per send_packet, no internal display-order reorder + * queue). V4L2 stateless decoder protocol expects each OUTPUT + * bitstream packet to produce one CAPTURE buffer with that + * packet's slice-decoded pixels — regardless of display order. + * ffmpeg-vaapi's H.264 decoder (which is what consumes our + * CAPTURE buffers via libva-v4l2-request-fourier) does its own + * POC-based display reorder upstream, so producing decode-order + * output is correct. + * + * AV_CODEC_FLAG_LOW_DELAY forces `low_delay = 1` inside + * libavcodec's H.264 decoder — `h264_select_output_frame` emits + * the just-decoded picture immediately instead of holding it + * for the display-order DPB output queue. DPB management for + * reference frames (short_ref / long_ref) is unaffected; B-frame + * decoding correctness is preserved. + * + * Closes daedalus-v4l2#11 part (2). Skipped for VP9 / AV1 — + * those formats don't internally reorder, so the flag would be + * a no-op but adds no value. + */ + if (codec_id == DAEDALUS_CODEC_H264) + ctx->flags |= AV_CODEC_FLAG_LOW_DELAY; + rc = fm->avcodec_open2(ctx, codec, NULL); if (rc < 0) { log_err("decoder: avcodec_open2 failed: %d", rc);