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

Ouverte
#7,691 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
1-2 jours
Accessibilité débutants
54/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
c
Domaine
embedded-iot

Piste de recherche

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.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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

Langage dominant
C
Étoiles
13.3k
Forks
5.5k
Merge moyen
1 j 4 h
PR mergées (30 j)
21

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de raspberrypi/linux

Toutes les issues de raspberrypi/linux

Issues similaires

Plus d'issues C

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.