bcm2835-codec: V4L2_DEC_CMD_START does not resume after a source change

Aperta
#7,691 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
1-2 giorni
Idoneità per principianti
54/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c
Ambito
embedded-iot

Direzione di ricerca

Start with handle_fmt_changed() and vidioc_decoder_cmd() in the bcm2835-codec driver, then compare their MMAL port handling with bcm2835_codec_stop_streaming() and start_streaming(). Reproduce with the colourspace-change H.264 clips and inspect CAPTURE buffer callbacks after V4L2_DEC_CMD_START. Done means START resumes decoding and CAPTURE buffers return after a source change without requiring STREAMOFF/STREAMON.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Device: Raspberry Pi 4 Mod. B

Describe the bug

bcm2835-codec signals V4L2_EVENT_SOURCE_CHANGE for a colourspace-only
change, but then only resumes if the client restarts the CAPTURE queue.
VIDIOC_DECODER_CMD with V4L2_DEC_CMD_START returns 0 and has no effect, so
a client that takes that route decodes nothing further: no frames, no error.

The Memory-to-Memory Stateful Video Decoder Interface says both routes must
work. From "Dynamic Resolution Change":

A source change triggers an implicit decoder drain, similar to the explicit
Drain sequence. The decoder is stopped after it completes. The decoding
process must be resumed with either a pair of calls to VIDIOC_STREAMOFF()
and VIDIOC_STREAMON() on the CAPTURE queue, or a call to
VIDIOC_DECODER_CMD() with the V4L2_DEC_CMD_START command.

The same section lists colourspace as a trigger for the sequence:

  • colorspace of the bitstream has been changed, but it doesn't require
    buffer reallocation.

So this is a documented event, and START is a documented way to resume it.
Only the STREAMOFF/STREAMON route works here.

Where it goes wrong

handle_fmt_changed() updates the cached format, sets
vq->last_buffer_dequeued = true and queues the event. It never disables the
MMAL port, so the firmware keeps the CAPTURE buffers it holds, correctly
awaiting reconfiguration.

vidioc_decoder_cmd() then handles START as:

case V4L2_DEC_CMD_START:
        dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
                                 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
        vb2_clear_last_buffer_dequeued(dst_vq);
        break;

That clears a vb2 flag and nothing else. Nothing is sent to the VPU, so the
port is never reconfigured and the held buffers are never returned. Only
bcm2835_codec_stop_streaming() reaches vchiq_mmal_port_disable(), which is
what flushes them back.

This is the same in rpi-6.6.y and rpi-6.12.y.

Steps to reproduce the behaviour

Two H.264 clips, identical apart from a VUI colour description:

ffmpeg -f lavfi -i testsrc=size=720x480:rate=25:duration=5        -c:v libx264 -pix_fmt yuv420p nocolour.mp4
ffmpeg -f lavfi -i testsrc=size=720x480:rate=25:duration=5        -c:v libx264 -pix_fmt yuv420p -colorspace smpte170m        -color_primaries smpte170m -color_trc bt709 colour.mp4

ffmpeg -c:v h264_v4l2m2m -i nocolour.mp4 -f null -   # 125 frames
ffmpeg -c:v h264_v4l2m2m -i colour.mp4   -f null -   # hangs, 0 frames, no error

ffmpeg takes the START route here, which is why it stalls. Software decoding
of the same clip yields 125 frames, as does h264_v4l2m2m on a build modified
to restart the CAPTURE queue instead.

System

Raspberry Pi 4 Model B Rev 1.5
Linux tuna 7.0.0-1020-raspi #20-Ubuntu SMP PREEMPT_DYNAMIC aarch64
Ubuntu 26.04
firmware ce768004a1c9657e60b33b0cc413d8e07320cb0d (clean) (release), Feb 11 2026
linux-firmware-raspi 14-0ubuntu1.1
bcm2835-codec 0.0.1, srcversion 1C8557E93B0AF380EF2C781
ffmpeg 8.0.1-3ubuntu2

Logs

bcm2835-codec at debug=3, around the event:

handle_fmt_changed: Format changed: buff size min 529920, rec 529920, buff num min 1, rec 1
handle_fmt_changed: Format changed to 736x480, crop 720x480, colourspace 31303659
handle_fmt_changed: Format was 736x480, crop 720x480
handle_fmt_changed: interlace mode 0, v4l2 field 1
vidioc_decoder_cmd, cmd 0
device_run: off we go
device_run: Submitted ip buffer len 577, pts 320000, flags 000c
device_run: Submitted src 00000000cf261895, dst 0000000000000000

Buffer size, buffer count, coded size and crop are unchanged; only the
colourspace differs (0x31303659 = Y601). After the change there are 0
op_buffer_cb messages and 288 ip_buffer_cb messages: input is consumed and
returned, and no CAPTURE buffer ever comes back. Every device_run afterwards
carries dst 0000000000000000.

The matching ioctl trace:

10:44:10.134619  ioctl(4, VIDIOC_DQEVENT)                      = 0
10:44:10.134776  ioctl(4, VIDIOC_G_FMT,  {CAPTURE_MPLANE, ...}) = 0
10:44:10.134999  ioctl(4, VIDIOC_DECODER_CMD)                   = 0
10:44:10.135173  ioctl(4, VIDIOC_DQBUF,  {CAPTURE_MPLANE}) = -1 EAGAIN

All 20 CAPTURE buffers were queued before the event; none is returned after it,
and V4L2_BUF_FLAG_LAST never appears.

Additional context

Verified against the running module rather than the source tree. Disassembling
bcm2835-codec.ko (srcversion 1C8557E93B0AF380EF2C781), the external calls
are:

vidioc_decoder_cmd:        __ubsan_handle_load_invalid_value, _printk,
                           v4l2_m2m_get_vq, vchiq_mmal_submit_buffer
handle_fmt_changed.isra.0: __stack_chk_fail, __ubsan_handle_out_of_bounds,
                           _printk, v4l2_event_queue_fh, v4l2_m2m_get_vq,
                           vchiq_mmal_port_parameter_get

The only vchiq_mmal_* call in vidioc_decoder_cmd is
vchiq_mmal_submit_buffer, which belongs to the V4L2_DEC_CMD_STOP branch
that submits the EOS buffer. Since vchiq_mmal_* are exported by a separate
module (bcm2835-mmal-vchiq), any call to one must appear as a relocation, so
no code path from START can reach the VPU in this binary.

A possible fix is for the START case to perform the port reconfiguration that
bcm2835_codec_stop_streaming()/start_streaming() already do: disable the
MMAL port so held buffers are flushed back, then re-enable it with the updated
format. I have not written that patch and have not tested it.

Reported while investigating an FFmpeg issue:
https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24887

Lingua principale
C
Stelle
13.3k
Fork
5.5k
Merge medio
1g 4h
PR unite (30g)
21

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di raspberrypi/linux

Tutte le issue di raspberrypi/linux

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.