lp6m’s blog

いろいろかきます

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