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

オープン
#7,691 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
1〜2日
初心者へのやさしさ
54/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
c
領域
embedded-iot

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

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

主要言語
C
スター
13.3k
フォーク
5.5k
平均マージ
1日 4時間
マージ済み PR(30日)
21

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

raspberrypi/linux のほかの issue

raspberrypi/linux の issue をすべて見る

似ている issue

C の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。