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に置き換えるところまでは昨日できた。
ブログが書くのが下手で、わかってる人しかわからない記事になってしまった気がするけど。。