Ubuntu on ZYBO Z7-20からPCam 5Cの映像を取得したい(成功)
前回Ubuntu on ZYBO Z7-20からPCam 5Cの映像を取得したい(失敗) - lp6m’s blogの続き。成功したのでまとめておく。
やったこと
前回なぜかyavtaコマンドで画像の取得ができなかった。
Xilinx Forumに質問した。
https://forums.xilinx.com/t5/Embedded-Linux/can-t-get-image-from-PCam-5C-on-Ubuntu-running-on-ZYBO-Z7-20/m-p/882879#M28057
どうやら以下のコマンドでは画像の取得ができた。なぜyavtaだとダメなのかは不明。
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=YUYV --stream-mmap --stream-count=1 --stream-to=test.raw
とりあえずこれで取得できるので、v4l2-ctlコマンドの実装を参考にC++コードを記述する。
コードは以下。
Get image from PCam 5C on Ubuntu running on ZYBO-Z7-20 · GitHub
Ubuntu on ZYBOでapt-get upgrade, apt-get update, apt-get install g++ gccしておく。
特に外部ライブラリを使用しないのでg++ cam.ccでビルドできる。PcamはUbuntu起動前に接続しておく。
以下のおまじないコマンドを叩く
sudo media-ctl -d /dev/media0 -V '"ov5640 2-003c":0 [fmt:UYVY/'1920x1080'@1/'15' field:none]' sudo media-ctl -d /dev/media0 -V '"43c60000.mipi_csi2_rx_subsystem":0 [fmt:UYVY/'1920x1080' field:none]'
$ ./a.out bus_info : platform:video_cap:0 card : video_cap output 0 driver : xilinx-vipp version : 264448 reqbuf.count : 3 buf.length : 1 buf.m.offset : 3195409312 buf.m.planes[j].length : 4147200 buffers[i].start[j] : 0xb687e000 buf.length : 1 buf.m.offset : 3195409312 buf.m.planes[j].length : 4147200 buffers[i].start[j] : 0xb6489000 buf.length : 1 buf.m.offset : 3195409312 buf.m.planes[j].length : 4147200 buffers[i].start[j] : 0xb6094000 r : 0 store image in array.... write data...
画像が取得できた!
得られたYUYV形式のcamdata.datファイルは以下のPythonコードでpng画像に変換できる。
Convert Raw YUYV image from PCam 5C to png · GitHub
python test.py camdata.dat out.png
(Pythonコード内のRGBへの変換が間違っているらしく、緑っぽい画像が出力されるかも・・)
勉強したこと
- 上に書いたおまじないコマンドは何なのか
これは、V4L2 SubDeviceそれぞれに使用するフォーマットを教えている。SubDeviceに設定されたフォーマットは以下のコマンドで確認できる。
$media-ctl /dev/video0 -p Media controller API version 4.9.0 Media device information ------------------------ driver xilinx-video model Xilinx Video Composite Device serial bus info hw revision 0x0 driver version 4.9.0 Device topology - entity 1: video_cap output 0 (1 pad, 1 link) type Node subtype V4L flags 0 device node name /dev/video0 pad0: Sink <- "43c60000.mipi_csi2_rx_subsystem":0 [ENABLED] - entity 5: ov5640 2-003c (1 pad, 1 link) type V4L2 subdev subtype Sensor flags 0 device node name /dev/v4l-subdev0 pad0: Source [fmt:UYVY/1920x1080 field:none] -> "43c60000.mipi_csi2_rx_subsystem":1 [ENABLED] - entity 7: 43c60000.mipi_csi2_rx_subsystem (2 pads, 2 links) type V4L2 subdev subtype Unknown flags 0 device node name /dev/v4l-subdev1 pad0: Source [fmt:UYVY/1920x1080 field:none] -> "video_cap output 0":0 [ENABLED] pad1: Sink [fmt:UYVY/1920x1080 field:none] <- "ov5640 2-003c":0 [ENABLED]
V4L2 SubDevice参考:https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/dev-subdev.html
きちんとPCam(OV5640) -> MIPI_CSI2_RX_SubSystem -> video_capにデータが流れるようになっていることがわかる。
この接続はPetaLinuxプロジェクトのデバイスツリー(project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi)内でremote-endpointで指定されている。
以下、system-user.dtsi一部抜粋
&axi_iic_0 { ... ov5640: camera@3c { compatible = "ovti,ov5640"; ... port { ov5640_to_mipi_csi2: endpoint { remote-endpoint = <&mipi_csi2_from_ov5640>; ... }; }; }; }; &amba_pl { video_cap { compatible = "xlnx,video"; dmas = <&v_frmbuf_wr_0 0>; ... ports { ... port@0 { ... vcap_in: endpoint { remote-endpoint = <&mipi_csi2_out>; }; }; }; }; }; &mipi_csi2_rx_subsystem_0 { compatible = "xlnx,mipi-csi2-rx-subsystem-2.0"; ... ports { ... port@0 { reg = <0>; xlnx,video-format = <XVIP_VF_YUV_422>; xlnx,video-width = <8>; mipi_csi2_out: endpoint { remote-endpoint = <&vcap_in>; }; }; port@1 { reg = <1>; xlnx,video-format = <XVIP_VF_YUV_422>; xlnx,video-width = <8>; mipi_csi2_from_ov5640: endpoint { ... remote-endpoint = <&ov5640_to_mipi_csi2>; }; }; }; };
これができたのが8月末。
第8回 相磯秀夫杯 FPGAデザインコンテストではこれを使用した。
FPGAでは何の画像処理も行っていない状態で、ソフトウェアに頑張らせた。
次はFrame Buffer Write IPをVDMAに置き換えて、HLSコアを挿入する。
VDMAに置き換えるところまでは昨日できた。
ブログが書くのが下手で、わかってる人しかわからない記事になってしまった気がするけど。。