v4l2 を Raspberry Pi Zero 2 Wで動かそうとしたら苦戦

(※2022/9/24 追記: libcameraのv4l2-compat.を効かせるようにすればうまくいくようです。WebRTC momoを動かしてみた話↓

syurecat.hatenablog.com

)

ちょっとよくわからないところが多いのですが、書かないと忘れるので書きます。

現象としては"とあるv4l2を使っているアプリケーション"がピクセルフォーマットを間違って設定して うまく動かないといったことでした。

RaspiOS(Bullseye)でLegacy cameraはDisable カメラは非公式のPibiger製のIMX219(素直に公式のやつを使っとくと良い?)

~/cameracheck $ uname -a
Linux raspberrypi 5.15.32-v7+ #1538 SMP Thu Mar 31 19:38:48 BST 2022 armv7l GNU/Linux

libcameraでカメラ情報は

~/cameracheck $ libcamera-hello --list-cameras
Available cameras
-----------------
0 : imx219 [3280x2464] (/base/soc/i2c0mux/i2c@1/imx219@10)
    Modes: 'SRGGB10_CSI2P' : 640x480 [206.65 fps - (1000, 752)/1280x960 crop]
                             1640x1232 [41.85 fps - (0, 0)/3280x2464 crop]
                             1920x1080 [47.57 fps - (680, 692)/1920x1080 crop]
                             3280x2464 [21.19 fps - (0, 0)/3280x2464 crop]
           'SRGGB8' : 640x480 [206.65 fps - (1000, 752)/1280x960 crop]
                      1640x1232 [41.85 fps - (0, 0)/3280x2464 crop]
                      1920x1080 [47.57 fps - (680, 692)/1920x1080 crop]
                      3280x2464 [21.19 fps - (0, 0)/3280x2464 crop]

libcameraはちゃんと動作する。

libcamera-still -r -o test.jpg --width 640 --height 480

ここからv4l2を使ってみようとするがピクセルフォーマット一覧を出すとずらっと並んでしまう。

~/cameracheck $ v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
        [1]: 'UYVY' (UYVY 4:2:2)
       ...
        [11]: 'BA81' (8-bit Bayer BGBG/GRGR)
        ...
        [43]: 'Y12 ' (12-bit Greyscale)
        [44]: 'Y14P' (14-bit Greyscale (MIPI Packed))
        [45]: 'Y14 ' (14-bit Greyscale)

これがトラブルの元らしく、これらが全部使えるというわけではないようだ(なにかのネゴシエーションで使えるようになる?)

V4L2 streaming - Raspberry Pi Forums

おとなしく、libcameraを使えということらしいが、それ以外のv4l2を使ってるレガシーのアプリケーションで、このリストを真に受けて一番先頭のYUYVをセットしてしまうアプリケーションではうまく動かないようです。

更に厄介なのはこの値はstatefulでセットすると次も使われるというところです。 なので、

libcamera-still -r -o test.jpg --width 640 --height 480

で正しい値をセットしてもらってからだとうまく動きました。 結局、使えるピクセルフォーマットはPixel Format : 'BA81' (8-bit Bayer BGBG/GRGR)らしい。

~/cameracheck $ v4l2-ctl -d /dev/video0 --all
Driver Info:
        Driver name      : unicam
        Card type        : unicam
        Bus info         : platform:3f801000.csi
        Driver version   : 5.15.32
        Capabilities     : 0xa5a00001
                Video Capture
                Metadata Capture
                Read/Write
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x25200001
                Video Capture
                Read/Write
                Streaming
                Extended Pix Format
Media Driver Info:
        Driver name      : unicam
        Model            : unicam
        Serial           : 
        Bus info         : platform:3f801000.csi
        Media version    : 5.15.32
        Hardware revision: 0x00000000 (0)
        Driver version   : 5.15.32
Interface Info:
        ID               : 0x03000006
        Type             : V4L Video
Entity Info:
        ID               : 0x00000004 (4)
        Name             : unicam-image
        Function         : V4L2 I/O
        Flags         : default
        Pad 0x01000005   : 0: Sink
          Link 0x02000008: from remote pad 0x1000002 of entity 'imx219 10-0010': Data, Enabled, Immutable
Priority: 2
Video input : 0 (unicam-image: ok)
Format Video Capture:
        Width/Height      : 3280/2464
        Pixel Format      : 'BA81' (8-bit Bayer BGBG/GRGR)
        Field             : None
        Bytes per Line    : 3296
        Size Image        : 8121344
        Colorspace        : Raw
        Transfer Function : Default (maps to None)
        YCbCr/HSV Encoding: Default (maps to ITU-R 601)
        Quantization      : Default (maps to Full Range)
        Flags    

v4l2を動かすコードは下記のようなサンプルコードがあり、ここからV4L2_BUF_TYPE_VIDEO_CAPTUREでrawのファイルを書き出すことに成功しました。

v4l2 capture example · GitHub

プログラムを書かないまでも正しい設定ならば

$ v4l2-ctl --stream-mmap=3 --stream-to=testrec.raw

でrawが取れる。

→参考 www.prototype00.com

ffmpegの扱いにも難がありそうだがこれはまた別の話...。

宿題

V4L2 streaming - Raspberry Pi Forums で引用されている記事 と libcameraの実装(https://git.libcamera.org/libcamera/libcamera.git/)を見ると何が起きているかわかりそう。 メディアパイプラインの考え方