しゅれログ

備忘録です。

社内勉強会に参加した

なにげに大きめな企業の勉強会は人生初だった。いろんな部署から全員知らん人。 前もって2章ほど前もって本を読んでおいて 質問を聞く or それにまつわる雑談 or 脱線 みたいな感じでした。ガチガチの資料とか準備していかなくてもいいのが良い。 次、私が主催するならこんなかんじにしよう。

『[試して理解]Linuxのしくみ』(1-3章の感想)

 [試して理解]Linuxのしくみ ―実験と図解で学ぶOS、仮想マシン、コンテナの基礎知識【増補改訂版】 を読み直している。前のやつは昔に読んでいた。会社で勉強会をするというので読み直した。

1章は概要、2章, 3章はプロセス関連の知識。

端末とかプロセスとかなんとなーくやっているfgとかnohupとかdaemonとか性能とか、を、ちゃんと言語化してくれていて自分の中でも整理された感じがした。 フォーク、プロセスグループの概念はちゃんと知らなかった。 シグナル周りは昔、苦労した記憶があるのを思い出した。 「慣習としてSIGHUPが設定読み直すシグナルとして使われている」知らなかった。

勉強会はあまり参加経験はないけどペースメーカーになって良さげ。

tensorflow.js 楽しい 入門

ブラウザで画像読ませて推論できる。 久し振りにReact/TypeScript書いた。

github.com

Github PagesにDeployした。

from web camera https://heya-naohiro.github.io/apps_tensorflowjs/

from picture https://heya-naohiro.github.io/apps_tensorflowjs/mobilenet

買ったので入門します。↓

Raspberry Pi Zero 2 WでWebRTC momoを動かしてみる

環境:RaspiOS Bullseye ( legacy cameraはdisable )

カメラ:

前回、libcamera経由でv4l2が使えるようになったようなので、 (前回: libcameraのv4l2 compatibleを通してraw streamを取得 - しゅれログ

今回はWebRTCのOSSである「momo」を動かしてみる。

github.com

これはlibcameraが言うところのNative V4L2 ApplicationのひとつであるのでV4L2 Compat.を効かせると 動くようになるはず。( Documentation — libcamera)

あらかじめ、libcameraをインストールしてあり(ソースからビルドした) 環境変数bashrcに

export LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/v4l2-compat.so

を設定。

それより先はmomoのReadmeに記載のとおりである。

@raspberrypi:~/momo/momo $ ./momo --no-audio-device test
[5:24:58.823385711] [2070]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3777-69ae75b0
[5:24:58.893045982] [2071]  WARN RPI raspberrypi.cpp:1252 Mismatch between Unicam and CamHelper for embedded data usage!
[5:24:58.894332078] [2071]  INFO RPI raspberrypi.cpp:1368 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media0
[5:24:58.949636126] [2070]  INFO Camera camera.cpp:1029 configuring streams: (0) 640x480-YUV420
[5:24:58.950713055] [2071]  INFO RPI raspberrypi.cpp:759 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 640x480-SBGGR10_1X10 - Selected unicam format: 640x480-pBAA
[5:24:58.954716812] [2070]  INFO Camera camera.cpp:1029 configuring streams: (0) 640x480-YUV420
[5:24:58.955501865] [2071]  INFO RPI raspberrypi.cpp:759 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 640x480-SBGGR10_1X10 - Selected unicam format: 640x480-pBAA

IPアドレス:8080/html/test.htmlにアクセスしてConnect

H264でConnectしてるときのCPU使用率は40%程度(1論理CPUに対して、ということであるが)

raspberrypi:~ $ lscpu
Architecture:                    armv7l
Byte Order:                      Little Endian
CPU(s):                          4
...
top - 22:08:34 up  5:29,  3 users,  load average: 0.38, 0.28, 0.11
Tasks: 133 total,   1 running, 132 sleeping,   0 stopped,   0 zombie
%Cpu(s):  8.5 us,  2.1 sy,  0.0 ni, 89.4 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem :    364.7 total,    137.6 free,     87.7 used,    139.4 buff/cache
MiB Swap:   1024.0 total,   1007.7 free,     16.2 used.    225.7 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                      
 2070 heyanao+  20   0  174416  27948  14336 S  39.9   7.5   1:41.70 momo                                                         
  230 root       0 -20       0      0      0 I   1.3   0.0   2:03.06 kworker/u9:1-brcmf_wq/mmc1:0001:1                            
 2116 heyanao+  20   0   25144   9400   8216 R   1.3   2.5   0:00.43 top                                                          
   75 root       1 -19       0      0      0 S   1.0   0.0   0:58.30 vchiq-slot/0                                                 
 2095 root      20   0       0      0      0 I   0.7   0.0   0:00.80 kworker/0:0-events                                           
  177 root      10 -10       0      0      0 S   0.3   0.0   0:14.76 SMIO                                                         
  227 root      20   0       0      0      0 S   0.3   0.0   0:08.29 brcmf_wdog/mmc1                                              
 2114 root      20   0       0      0      0 I   0.3   0.0   0:00.03 kworker/2:1-events

繋いでないときは30%程度でした。

libcameraのv4l2 compatibleを通してraw streamを取得

環境: Raspi Zero 2 W / RaspiOS Bullseye / disable legacy mode

v4l2-ctlで使えるフォーマット一覧を出すとずらっと出るが、すべて使えるわけではない。

~/cameracheck $ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [1]: 'UYVY' (UYVY 4:2:2)
        ....
        [43]: 'Y12 ' (12-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [44]: 'Y14P' (14-bit Greyscale (MIPI Packed))
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [45]: 'Y14 ' (14-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1

libcameraにv4l2 compatibleの機能があり、そこを通すと下記のようにうまいことやってくれるっぽい

Documentation — libcamera

使うにはLD_PRELOADを使う

export LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/v4l2-compat.so

絞られる

~/cameracheck $  v4l2-ctl -d /dev/video0 --list-formats
[1:38:27.462853673] [6401]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3777-69ae75b0
[1:38:27.500574932] [6402]  WARN RPI raspberrypi.cpp:1252 Mismatch between Unicam and CamHelper for embedded data usage!
[1:38:27.501922072] [6402]  INFO RPI raspberrypi.cpp:1368 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media0
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'NV21' (Y/CrCb 4:2:0)
        [1]: 'YU12' (Planar YUV 4:2:0)
        [2]: 'NV12' (Y/CbCr 4:2:0)
        [3]: 'YV12' (Planar YVU 4:2:0)
        [4]: 'XB24' (32-bit RGBX 8-8-8-8)
        [5]: 'RGB3' (24-bit RGB 8-8-8)
        [6]: 'BGR3' (24-bit BGR 8-8-8)
        [7]: 'XR24' (32-bit BGRX 8-8-8-8)
        [8]: 'RGBP' (16-bit RGB 5-6-5)
        [9]: 'YVYU' (YVYU 4:2:2)
        [10]: 'YUYV' (YUYV 4:2:2)
        [11]: 'VYUY' (VYUY 4:2:2)
        [12]: 'UYVY' (UYVY 4:2:2)
~/cameracheck $ 

↓事前にpixcel formatを設定しても無駄。コマンドごとに設定は外されるらしい。(コマンドとしては正しい姿とも言える)

raspberrypi:~/cameracheck $  v4l2-ctl --set-fmt-video=width=1296,height=972,pixelformat=10
[1:17:19.099511110] [6020]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3777-69ae75b0
[1:17:19.152740124] [6021]  WARN RPI raspberrypi.cpp:1252 Mismatch between Unicam and CamHelper for embedded data usage!
[1:17:19.154276740] [6021]  INFO RPI raspberrypi.cpp:1368 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media0
[1:17:19.157278514] [6020]  INFO Camera camera.cpp:1029 configuring streams: (0) 1296x972-YUYV
[1:17:19.158532838] [6021]  INFO RPI raspberrypi.cpp:759 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 1640x1232-SBGGR10_1X10 - Selected unicam format: 1640x1232-pBAA
raspberrypi:~/cameracheck $ 

ストリームを撮って ffmepgでjpegにする

raspberrypi:~/cameracheck $ v4l2-ctl --stream-mmap=3 --stream-to=testrec.raw --stream-count=1 (★ここでフォーマットを設定したら正しく設定されるようだ)
[1:18:30.718666516] [6084]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3777-69ae75b0
[1:18:30.771650791] [6085]  WARN RPI raspberrypi.cpp:1252 Mismatch between Unicam and CamHelper for embedded data usage!
[1:18:30.772933657] [6085]  INFO RPI raspberrypi.cpp:1368 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media0
★↓800x600-NV12がConfigureされている(一番上にあるから?)
[1:18:30.816269692] [6084]  INFO Camera camera.cpp:1029 configuring streams: (0) 800x600-NV12
[1:18:30.817259537] [6085]  INFO RPI raspberrypi.cpp:759 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 1640x1232-SBGGR10_1X10 - Selected unicam format: 1640x1232-pBAA
<
raspberrypi:~/cameracheck $ ffmpeg -f image2 -c:v rawvideo -pix_fmt nv12 -s:v 800x600 -i testrec.raw image-%04d.jpg
ffmpeg version N-108133-gf976ed7fcf Copyright (c) 2000-2022 the FFmpeg developers
  built with gcc 10 (Raspbian 10.2.1-6+rpi1)
  configuration: --prefix=/home/heyanaohiro/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/heyanaohiro/ffmpeg_build/include --extra-ldflags=-L/home/heyanaohiro/ffmpeg_build/lib --extra-libs='-lpthread -lm' --ld=g++ --bindir=/home/heyanaohiro/bin --enable-gpl --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libx264 --enable-libx265
  libavutil      57. 36.101 / 57. 36.101
  libavcodec     59. 43.100 / 59. 43.100
  libavformat    59. 31.100 / 59. 31.100
  libavdevice    59.  8.101 / 59.  8.101
  libavfilter     8. 49.100 /  8. 49.100
  libswscale      6.  8.112 /  6.  8.112
  libswresample   4.  9.100 /  4.  9.100
  libpostproc    56.  7.100 / 56.  7.100
Input #0, image2, from 'testrec.raw':
  Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: rawvideo (NV12 / 0x3231564E), nv12, 800x600, 25 fps, 25 tbr, 25 tbn
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> mjpeg (native))
Press [q] to stop, [?] for help
[swscaler @ 0x2f93380] [swscaler @ 0x2f9c620] deprecated pixel format used, make sure you did set range correctly
[swscaler @ 0x2f93380] [swscaler @ 0x2fc6ab0] deprecated pixel format used, make sure you did set range correctly
[swscaler @ 0x2f93380] [swscaler @ 0x2ff13f0] deprecated pixel format used, make sure you did set range correctly
[swscaler @ 0x2f93380] [swscaler @ 0x301bd30] deprecated pixel format used, make sure you did set range correctly
[swscaler @ 0x2f93380] [swscaler @ 0x30467e0] deprecated pixel format used, make sure you did set range correctly
Output #0, image2, to 'image-%04d.jpg':
  Metadata:
    encoder         : Lavf59.31.100
  Stream #0:0: Video: mjpeg, yuvj420p(pc, progressive), 800x600, q=2-31, 200 kb/s, 25 fps, 25 tbn
    Metadata:
      encoder         : Lavc59.43.100 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A
frame=    1 fps=0.0 q=5.9 Lsize=N/A time=00:00:00.00 bitrate=N/A speed=   0x    0x    
video:28kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
~/cameracheck $ 

下記のようなコマンド(h264_v4l2m2m)も上手くいく気配があるので謎が解けていきそうだが、今日のところは終わり

ffmpeg -f rawvideo -pix_fmt yuv420p -video_size 640x480 -framerate 30 -i 'testrec.raw' -f mp4 -c:v h264_v4l2m2m -b:v 300k 'testrec.mp4'

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/)を見ると何が起きているかわかりそう。 メディアパイプラインの考え方

久々に物理出社した

所用があって、久々に物理出社した。

朝電車に乗って会社についたのは9:30過ぎ

朝の電車はそこそこ空いていて快適だった

台風が関東のはるか北、日本海を進行中、関東では夏はまだ終わって無い、ただただ蒸し暑い一日だった。 いや、会社はクーラーが効いてたが。行き帰りはとにかく蒸し暑かった。

リアルでの会話はなかなか貴重だった。

いつもより疲れた。