This project is part 1 of a N part series of projects, where we will explore how to integrate Raspberry Pi cameras on Zynq-UltraScale+ boards.
- Part 1 : RPI Camera Fun with Zynq-UltraScale+ : RPI Cam V2
- Part 2 : RPI Camera Fun with Zynq-UltraScale+ : RPI Cam V3, HQ, AI
- Part 3 : RPI Camera Fun with Zynq-UltraScale+ : White Balance
- Part 4 : RPI Camera Fun with Zynq-UltraScale+ : Porting LIBCAMERA
During this series, I will be targeting the following hardware setup:
- Tria UltraZed-7EV Starter Kit (SOM + Carrier Card)
- Opsero RPI Camera FMC
- Raspberry Pi cameras
The featured design will also support Hailo-8 AI acceleration with the following optional hardware:
- Opsero M.2 Stack FMC
- Hailo-8 AI Acceleration module
The motivation of this series of projects is to enable users to leverage Raspberry Pi's wonderful portfolio of cameras and supporting software, on Zynq-UltraScale+ hardware.
Introduction - Part IThis project provides guidance on where to start to leverage existing work that has been done to integrate Raspberry Pi cameras to Zynq-UltraScale+ based hardware.
After a brief introduction of Raspberry Pi's camera portfolio:
- Raspberry Pi Camera Overview
I will start our journey with the following two Zynq-UltraScale+ resources:
- KV260 Vision AI Starter Kit (KV260)
- Opsero Raspberry Pi Camera FMC
I will then describe how to build and execute the Opsero Raspberry Pi Camera FMC design:
- Building the Design
- Setup up the Hardware
- Executing the Design
I will take a deep dive into the capture and display pipelines, in order to provide a better understanding of what's going on under the hood with the provided demos:
- Linux Capture Pipelines 101
- Linux Display Pipelines 101
Finally, I will modify the design just to show how easy it is:
- Modifying the Design
This is a loaded agenda, so let's get started !
Raspberry Pi Camera OverviewBefore considering which Zynq-UltraScale+ reference design to use, we need to select one of the Raspberry Pi camera modules for our application.
The following cameras are available from Raspberry Pi.
Raspberry Pi also has variations of their camera modules for:
- without IR filter : Camera V2 NoIR, Camera V3 NoIR
- wider field of fiew : Camera V3 Wide
For this project, we will select the Camera V2 module for the simple reason that it is the one supported by the reference designs we are considering:
We will look at how to add support for the other camera modules in the next project in this series.
KV260 Design OverviewThe first Zynq-UltraScale+ reference design that was made available for Raspberry Pi cameras was done specifically for the KV260 as a Vitis platform:
- kv260_ispMipiRx_rpiMipiRx_DP
This platform is used by the NLP-SmartVision application, so I would refer to the documentation for that app for more details:
One detail that I want to highlight is how the capture pipeline for the Raspberry Pi camera is implemented.
This Vitis platform actually contained two MIPI capture pipelines, as shown below:
For the Raspberry Pi camera's capture pipline (rpiMipiRx), we can see that the Image Signal Processing (ISP) pipeline is implemented in HLS, and is supported by a linux kernel driver.
As part of this design's legacy, we can now find the linux driver for the IMX219 sensor in AMD's linux kernel repository:
Opsero Raspberry Pi Camera FMCJeff Johnson (Opsero) also created several Zynq-UltraScale+ reference designs for Raspberry Pi cameras, supporting several FMC carriers:
I have chosen to use Jeff's UltraZed-EV reference design as my starting point for this series for several reasons:
- excellent reference designs
- excellent documentation
- the UltraZed-EV is one of our development boards
- includes support for video encoding/decoding (VCU)
- includes support for Hailo-8
The next sections will provide a deep dive into the capture pipelines and display pipeline.
Building the DesignThere is nothing I need to add to this topic, since Jeff has done an excellent job in describing how to rebuild his reference design:
Once done, you will have an SD card image, which you can program to a micro-SD card.
Setting up the HardwareThe following two images illustrate the hardware setup with the required RPI Camera FMC and Raspberry Pi V2 camera modules. The first (optional) setup also includes the additional M.2 Stack FMC + Hailo-8 option.
I arranged the four (4) Raspberry Pi V2 camera modules as shown in the following images:
I quickly gathered random objects to create the following scene:
After booting the SD image, running the demos is as simple as running either of the following two scripts:
- displaycams.sh : quad-camera video passthrough
- hailodemo.sh : quad-camera yolov5 demonstration with Hailo-8
The passthrough demo can be launched as follows:
# displaycams.sh
The displaycams.sh script performs the following:
- set the resolution of the monitor to 1920x1080 with the "modetest" utility
- initialize the capture pipeline to output 960x540 YUYV with the "v4l2-ctl" & "media-ctl" utilities
- launch the four passthrough pipelines with "gstreamer"
CHALLENGE 1 : Can you guess why the bottom two captured video streams and different than the top two captured video streams ?
The Hailo-8 demo can be launched as follows:
# hailodemo.sh
The hailodemo.sh script performs the following:
- set the monitor to its maximum supported resolution with the "modetest" utility
- initialize the capture pipeline to output 1280x720 YUYV with the "v4l2-ctl" & "media-ctl" utilities
- launch the four detection pipelines with "gstreamer"
CHALLENGE 2 : Can you guess why I was not able to see the entire content ?
A lot is going on behind the scenes when these scripts are launched. The following sections will give a brief overview of the capture and display pipelines, and how these are accessed in Linux.
Linux Capture Pipelines 101This design has four capture pipelines, each with the following architecture implemented in the programmable logic (PL):
Each MIPI capture pipeline has the following implementation details:
- MIPI CSI-2 RX input : 2 lanes, 456Mbps line rate, RAW10 format
- Pixel Per Clock (PPC) : 1
- Max Resolution : 1920x1232
In Linux, these capture pipelines are made accessible via the Video for Linux v2 (V4L2) framework.
Drivers are implemented in the kernel space for the following devices:
- media : /dev/media*
- video : /dev/video*
- sub-dev : /dev/v4l2-subdev*
In order to understand how these kernel driver map to our capture pipeline, we can use the V4L2 based utilities.
We will start by installing a few missing packages:
# dnf install v4l-utils
# dnf install media-ctl
# dnf install yavta
# dnf install graphviz
We can start by querying the V4L2 devices on our system:
root@uzev-hailo-2024-1:~# v4l2-ctl --list-devices
Xilinx Video Composite Device (platform:vcap_mipi_0_v_proc):
/dev/media0
vcap_mipi_0_v_proc output 0 (platform:vcap_mipi_0_v_proc:0):
/dev/video0
Xilinx Video Composite Device (platform:vcap_mipi_1_v_proc):
/dev/media1
vcap_mipi_1_v_proc output 0 (platform:vcap_mipi_1_v_proc:0):
/dev/video1
Xilinx Video Composite Device (platform:vcap_mipi_2_v_proc):
/dev/media2
vcap_mipi_2_v_proc output 0 (platform:vcap_mipi_2_v_proc:0):
/dev/video2
Xilinx Video Composite Device (platform:vcap_mipi_3_v_proc):
/dev/media3
vcap_mipi_3_v_proc output 0 (platform:vcap_mipi_3_v_proc:0):
/dev/video3
We can see that each of the four capture pipelines has a Media device (/dev/media*) and Video device (/dev/video*) associated with it.
We can further query the capture pipelines as follows:
media-ctl --print-dot -d /dev/media0 > dev_media_0_graph.dot
media-ctl --print-dot -d /dev/media1 > dev_media_1_graph.dot
media-ctl --print-dot -d /dev/media2 > dev_media_2_graph.dot
media-ctl --print-dot -d /dev/media3 > dev_media_3_graph.dot
dot -Tpng dev_media_0_graph.dot > dev_media_0_graph.png
dot -Tpng dev_media_1_graph.dot > dev_media_1_graph.png
dot -Tpng dev_media_2_graph.dot > dev_media_2_graph.png
dot -Tpng dev_media_3_graph.dot > dev_media_3_graph.png
This will create a visual representation of the capture pipelines:
We can see that each of the four capture pipelines has a Media device (/dev/media*), a Video device (/dev/video*), as well as four V4L Sub-Devices (/dev/v4l-subdev*) associated with it.
These map to the actual hardware as follows:
We can use another utility, "yavta" to interact with these capture pipelines.
We start by calling "init_cams.sh", which will configure the V4L2 capture pipelines (to the 1920x1080 resolution, and YUYV format).
root@uzev-hailo-2024-1:~# init_cams.sh
-------------------------------------------------
Capture pipeline init: RPi cam -> Scaler -> DDR
-------------------------------------------------
Configuring all video capture pipelines to:
- RPi Camera output : 1920 x 1080
- Scaler (VPSS) output : 1920 x 1080 YUY2
Video Mixer found here:
- a0000000.v_mix
Detected and configured the following cameras on RPi Camera FMC:
- CAM0: /dev/media0 = /dev/video0
- CAM1: /dev/media1 = /dev/video1
- CAM2: /dev/media2 = /dev/video2
- CAM3: /dev/media3 = /dev/video3
root@uzev-hailo-2024-1:~#
Here are the details for the first capture pipeline:
Next, let's capture one (raw) image from each capture pipeline (outputs to frame-000000.bin), then convert it to a viewable format with "ffmpeg".
# yavta-F /dev/video0 -n 1 -c1 -s 1920x1080 -f YUYV
# ffmpeg-f rawvideo-s 1920x1080 -pix_fmtyuyv422 -iframe-000000.bin cam0.png
This will capture the following four images:
CHALLENGE 3 : Can the Capture Pipelines be configured for RGB output (versus YUYV output) ? If yes, how ?
Linux Display Pipelines 101This design implements a sophisticated display pipeline.
By default, the Zynq-UltraScale+ provides a DisplayPort controller, with two layers:
- graphics : RGB layer with alpha (BGRA)
- video : real-time video layer supporting many formats (BGR, YUV, etc...)
Since the reference design has multiple video sources, we want more video layers, which is why Jeff included the Video Mixer. This core adds the following layers:
- graphics : RGB layer with alpha (BGRA)
- video : four (4) layers with YUYV format
In Linux, this display pipeline is made accessible via DRM (Direct Rendering Manager) and KMS (Kernel Mode Setting).
We can query the DRM implementation for our design with the "modetest" command:
root@uzev-hailo-2024-1:~# modetest -M xlnx
Encoders:
id crtc type possible crtcs possible clones
59 46 TMDS 0x00000003 0x00000001
Connectors:
id encoder status name size (mm) modes encoders
60 59 connected DP-1 610x350 25 59
modes:
index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
#0 1920x1080 60.00 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: driver
#1 1920x1080 59.94 1920 2008 2052 2200 1080 1084 1089 1125 148352 flags: phsync, pvsync; type: driver
#2 1680x1050 59.95 1680 1784 1960 2240 1050 1053 1059 1089 146250 flags: nhsync, pvsync; type: driver
#3 1600x900 60.00 1600 1624 1704 1800 900 901 904 1000 108000 flags: phsync, pvsync; type: driver
#4 1280x1024 75.02 1280 1296 1440 1688 1024 1025 1028 1066 135000 flags: phsync, pvsync; type: driver
#5 1280x1024 60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: phsync, pvsync; type: driver
#6 1440x900 59.89 1440 1520 1672 1904 900 903 909 934 106500 flags: nhsync, pvsync; type: driver
#7 1280x800 59.81 1280 1352 1480 1680 800 803 809 831 83500 flags: nhsync, pvsync; type: driver
#8 1152x864 75.00 1152 1216 1344 1600 864 865 868 900 108000 flags: phsync, pvsync; type: driver
#9 1280x720 60.00 1280 1390 1430 1650 720 725 730 750 74250 flags: phsync, pvsync; type: driver
#10 1280x720 59.94 1280 1390 1430 1650 720 725 730 750 74176 flags: phsync, pvsync; type: driver
#11 1024x768 75.03 1024 1040 1136 1312 768 769 772 800 78750 flags: phsync, pvsync; type: driver
#12 1024x768 70.07 1024 1048 1184 1328 768 771 777 806 75000 flags: nhsync, nvsync; type: driver
#13 1024x768 60.00 1024 1048 1184 1344 768 771 777 806 65000 flags: nhsync, nvsync; type: driver
#14 832x624 74.55 832 864 928 1152 624 625 628 667 57284 flags: nhsync, nvsync; type: driver
#15 800x600 75.00 800 816 896 1056 600 601 604 625 49500 flags: phsync, pvsync; type: driver
#16 800x600 72.19 800 856 976 1040 600 637 643 666 50000 flags: phsync, pvsync; type: driver
#17 800x600 60.32 800 840 968 1056 600 601 605 628 40000 flags: phsync, pvsync; type: driver
#18 800x600 56.25 800 824 896 1024 600 601 603 625 36000 flags: phsync, pvsync; type: driver
#19 640x480 75.00 640 656 720 840 480 481 484 500 31500 flags: nhsync, nvsync; type: driver
#20 640x480 72.81 640 664 704 832 480 489 492 520 31500 flags: nhsync, nvsync; type: driver
#21 640x480 66.67 640 704 768 864 480 483 486 525 30240 flags: nhsync, nvsync; type: driver
#22 640x480 60.00 640 656 752 800 480 490 492 525 25200 flags: nhsync, nvsync; type: driver
#23 640x480 59.94 640 656 752 800 480 490 492 525 25175 flags: nhsync, nvsync; type: driver
#24 720x400 70.08 720 738 846 900 400 412 414 449 28320 flags: nhsync, pvsync; type: driver
props:
1 EDID:
flags: immutable blob
blobs:
value:
00ffffffffffff004c2d4d0c4a534d30
231a0104b53d23783a5fb1a2574fa228
0f5054bfef80714f810081c08180a9c0
b300950001014dd000a0f0703e803020
35005f592100001a000000fd00384b1e
873c000a202020202020000000fc0055
3238453539300a2020202020000000ff
00485450483830383434330a20200159
02030ef041102309070783010000023a
801871382d40582c45005f592100001e
565e00a0a0a02950302035005f592100
001a04740030f2705a80b0588a005f59
2100001e000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000052
2 DPMS:
flags: enum
enums: On=0 Standby=1 Suspend=2 Off=3
value: 0
5 link-status:
flags: enum
enums: Good=0 Bad=1
value: 0
6 non-desktop:
flags: immutable range
values: 0 1
value: 0
4 TILE:
flags: immutable blob
blobs:
value:
61 sync:
flags: range
values: 0 1
value: 0
62 bpc:
flags: enum
enums: 6BPC=6 8BPC=8 10BPC=10 12BPC=12
value: 8
CRTCs:
id fb pos size
46 0 (0,0) (1920x1080)
#0 1920x1080 60.00 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: driver
props:
25 VRR_ENABLED:
flags: range
values: 0 1
value: 0
58 0 (0,0) (0x0)
#0 nan 0 0 0 0 0 0 0 0 0 flags: ; type:
props:
25 VRR_ENABLED:
flags: range
values: 0 1
value: 0
49 output_color:
flags: enum
enums: rgb=0 ycrcb444=1 ycrcb422=2 yonly=3
value: 0
50 bg_c0:
flags: range
values: 0 4095
value: 0
51 bg_c1:
flags: range
values: 0 4095
value: 0
52 bg_c2:
flags: range
values: 0 4095
value: 0
Planes:
id crtc fb CRTC x,y x,y gamma size possible crtcs
34 0 0 0,0 0,0 0 0x00000001
formats: YUYV
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 0
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000100000018000000
01000000200000005955595600000000
01000000000000000000000000000000
0000000000000000
in_formats blob decoded:
YUYV: LINEAR
36 0 0 0,0 0,0 0 0x00000001
formats: YUYV
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 0
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000100000018000000
01000000200000005955595600000000
01000000000000000000000000000000
0000000000000000
in_formats blob decoded:
YUYV: LINEAR
38 0 0 0,0 0,0 0 0x00000001
formats: YUYV
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 0
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000100000018000000
01000000200000005955595600000000
01000000000000000000000000000000
0000000000000000
in_formats blob decoded:
YUYV: LINEAR
40 0 0 0,0 0,0 0 0x00000001
formats: YUYV
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 0
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000100000018000000
01000000200000005955595600000000
01000000000000000000000000000000
0000000000000000
in_formats blob decoded:
YUYV: LINEAR
42 0 0 0,0 0,0 0 0x00000001
formats: AR24
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 0
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000100000018000000
01000000200000004152323400000000
01000000000000000000000000000000
0000000000000000
in_formats blob decoded:
AR24: LINEAR
33 alpha:
flags: range
values: 0 256
value: 256
44 0 0 0,0 0,0 0 0x00000001
formats: NV16
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 1
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000100000018000000
01000000200000004e56313600000000
01000000000000000000000000000000
0000000000000000
in_formats blob decoded:
NV16: LINEAR
54 0 0 0,0 0,0 0 0x00000002
formats: VYUY UYVY YUYV YVYU YU16 YV16 YU24 YV24 NV16 NV61 GREY Y10 BG24 RG24 XB24 XR24 XB30 XR30 YU12 YV12 NV12 NV21 XV15 XV20 X403
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 0
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000001900000018000000
01000000800000005659555955595659
59555956595659555955313659563136
59553234595632344e5631364e563631
47524559593130204247323452473234
58423234585232345842333058523330
59553132595631324e5631324e563231
58563135585632305834303300000000
ffffff01000000000000000000000000
0000000000000000
in_formats blob decoded:
VYUY: LINEAR
UYVY: LINEAR
YUYV: LINEAR
YVYU: LINEAR
YU16: LINEAR
YV16: LINEAR
YU24: LINEAR
YV24: LINEAR
NV16: LINEAR
NV61: LINEAR
GREY: LINEAR
Y10: LINEAR
BG24: LINEAR
RG24: LINEAR
XB24: LINEAR
XR24: LINEAR
XB30: LINEAR
XR30: LINEAR
YU12: LINEAR
YV12: LINEAR
NV12: LINEAR
NV21: LINEAR
XV15: LINEAR
XV20: LINEAR
X403: LINEAR
53 tpg:
flags: range
values: 0 1
value: 0
56 0 0 0,0 0,0 0 0x00000002
formats: AB24 AR24 RA24 BA24 BG24 RG24 RA15 BA15 RA12 BA12 RG16 BG16
props:
9 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 1
31 IN_FORMATS:
flags: immutable blob
blobs:
value:
01000000000000000c00000018000000
01000000480000004142323441523234
52413234424132344247323452473234
52413135424131355241313242413132
5247313642473136ff0f000000000000
00000000000000000000000000000000
in_formats blob decoded:
AB24: LINEAR
AR24: LINEAR
RA24: LINEAR
BA24: LINEAR
BG24: LINEAR
RG24: LINEAR
RA15: LINEAR
BA15: LINEAR
RA12: LINEAR
BA12: LINEAR
RG16: LINEAR
BG16: LINEAR
47 alpha:
flags: range
values: 0 255
value: 0
48 g_alpha_en:
flags: range
values: 0 1
value: 1
Frame buffers:
id size pitch
root@uzev-hailo-2024-1:~#
This generates a very long (at first, incomprehensible) description of our display pipeline.
We can summarize it as follows:
- Encoders : 59 (type TMDS)
- Connectors : 60 (name DP-1, status connected)
- CRTCs : 46 & 58
- Planes : 34, 36, 38, 40 (format YUYV), 42 (format AR24), 44 (format NV16), 54, 56
We can visualize this with the following representation:
The DRM framework has abstracted the hardware using the following representation:
- DRM driver : video layers & mixers, called CRTC in DRM framework
- DRM encoder : represents the interface to the monitor (ie. TMDS)
- DRM connector : represents for monitor
Another view of the DRM framework for our design, with an emphasis on the video layers, can be represented as shown below:
We can imagine each layer being a transparent glass. When inactive, it will let the content from the previous (left) layers pass to the next layers. If it is active (or a portion of it is active, via alpha blending or render rectangles), it will pass its own content to the next (right) layers. The following examples will illustrate this.
We can use the "modetest" utility to interact with the display pipeline:
Theoretically, we can use modetest with the DP Controller (CRTC 58). However, I have not been able to achieve this as shown below:
This does work with a DP only design, so there is something that is missing in my comprehension of this complex display pipeline.
I will concentrate on the Video Mixer (CRTC 46) for the rest of this section.
We can start by configuring the monitor to a specific resolution, as shown below:
The monitor will become blue, which is the default background color for the Video Mixer.
We can also start generating video content, as shown below, for the first YUYV layer (layer 34) of the video mixer (CRTC 46):
This will display a diagonal bar pattern on the top left quadrant of the monitor.
We can do the equivalent for fourth YUYV layer (layer 40) of the video mixer (CRTC 46):
We can also generate content to the display pipeline using GStreamer, as the demo scipts have done previously.
The following diagrams illustrate how video was displayed by Gstreamer using the DRM framework:
CHALLENGE 4 : Is it possible to display RGB content in our Display Pipeline ? If yes, how ?
Modifying the DesignJeff has even taken the time to document how to modify the reference design:
I will take the bait, and attempt to modify his design. I have chosen the following use case as an example of what users may want to modify:
- add support for BGR color format
The MIPI capture pipelines already support this color format, so there is nothing to do there. Recall that the display pipeline's video mixer has one (1) BGRA layer for graphics, and four (4) YUYV overlays for real-time video.
Start by opening the Vivado project, located in the following directory:
zynqmp-hailo-ai/Vivado/uzev/uzev.xpr
# vivado uzev.xpr &
NOTE : You may want to make a copy of the original design first, and/or work with a renamed copy of the original design.
Double click on the "rpi_i (rpi.bd)" IP Integrator block design, and navigate to the display_pipeline sub-system.
First, modify the Video Mixer to add four (4) additional layers for BGR format:
Next, add four (4) additional slave interfaces to the AXI interconnect:
Finally, make the connections to the new ports, as shown below:
Click on "Generate the Bitstream", and wait for the build to complete.
These modifications have minimal impact on the resource utilization for the design, as shown in the following figures:
Next, re-generate the XSA archive in the Tcl Console with the following command:
write_hw_platform -fixed -include_bit uzev.xsa
Next, we want to import these hardware changes to our petalinux project, located in the following directory:
zynqmp-hailo-ai/Petalinux/uzev
# petalinux-config --silentconfig --get-hw-description=../../Vivado/uzev/uzev.xsa
Normally, we would need to update our device tree content, but in this case, the automatically generated content for the Video Mixer is correct, so no further modifications are needed.
Re-build the petalinux project, re-generate the SD image, and boot the new design on the UltraZed-EV board.
It is important to understand that we have now changed our display pipeline to the following:
Notice that the IDs for the components have changed:
- Video Mixer : CRTC 54
- DisplayPort Controller : CRTC 66, Layers 52, 62
- Encoder : 67
- Connector : 68
This needs to be reflected in the following scripts:
- init_cams.sh
- displaycams.sh
- hailodemo.sh
Specifically for the "displaycams.sh" script:
/usr/bin/displaycams.sh
We need to change the connector and CRTC IDs for the modetest command:
...
#-------------------------------------------------------------------------------
# Setup the display pipeline
#-------------------------------------------------------------------------------
# Initialize the display pipeline
#echo | modetest -M xlnx -D ${VMIX} -s 60@46:${DISP_RES}@NV16
echo | modetest -M xlnx -D ${VMIX} -s 68@54:${DISP_RES}@NV16
...
Let's make a copy of this script, and rename it with the "_yuyv" suffix.
root@uzev-hailo-2024-1:~# cp /usr/bin/displaycams.sh ./displaycams_yuyv.sh
root@uzev-hailo-2024-1:~#
Let's make a separate copy, and this time rename it with the "_bgr" suffix.
root@uzev-hailo-2024-1:~# cp /usr/bin/displaycams.sh ./displaycams_bgr.sh
root@uzev-hailo-2024-1:~#
In the "_bgr" version of the script, lets define the BGR format in the "format_dict" dictionnary, and change the planes (overlays) we are using for the kmssink output options:
...
# This dictionary associates GStreamer pixel formats with those used with media-ctl
declare -A format_dict
format_dict["NV12"]="VYYUYY8_1X24"
format_dict["YUY2"]="UYVY8_1X16"
format_dict["BGR"]="RBG888_1X24"
...
# Output format of the RPi camera pipelines (use a GStreamer pixel format from the dict above)
#OUT_FORMAT=YUY2
OUT_FORMAT=BGR
...
# Screen quadrants: TOP-LEFT, TOP-RIGHT, BOTTOM-LEFT, BOTTOM-RIGHT
quadrants_yuyv=(
"plane-id=34 render-rectangle=\"<0,0,${OUT_RES_W},${OUT_RES_H}>\""
"plane-id=36 render-rectangle=\"<${OUT_RES_W},0,${OUT_RES_W},${OUT_RES_H}>\""
"plane-id=38 render-rectangle=\"<0,${OUT_RES_H},${OUT_RES_W},${OUT_RES_H}>\""
"plane-id=40 render-rectangle=\"<${OUT_RES_W},${OUT_RES_H},${OUT_RES_W},${OUT_RES_H}>\""
)
quadrants_bgr=(
"plane-id=44 render-rectangle=\"<0,0,${OUT_RES_W},${OUT_RES_H}>\""
"plane-id=46 render-rectangle=\"<${OUT_RES_W},0,${OUT_RES_W},${OUT_RES_H}>\""
"plane-id=48 render-rectangle=\"<0,${OUT_RES_H},${OUT_RES_W},${OUT_RES_H}>\""
"plane-id=50 render-rectangle=\"<${OUT_RES_W},${OUT_RES_H},${OUT_RES_W},${OUT_RES_H}>\""
)
...
# For each connected camera, add pipeline to gstreamer command
for media in "${!media_to_video_mapping[@]}"; do
# Append the specific command for the current iteration to the full command
full_command+=" v4l2src device=${media_to_video_mapping[$media]} io-mode=mmap"
#full_command+=" ! video/x-raw, width=${OUT_RES_W}, height=${OUT_RES_H}, format=YUY2, framerate=${FRM_RATE}/1"
full_command+=" ! video/x-raw, width=${OUT_RES_W}, height=${OUT_RES_H}, format=BGR, framerate=${FRM_RATE}/1"
full_command+=" ! kmssink bus-id=${VMIX} ${quadrants_bgr[$index]} show-preroll-frame=false sync=false can-scale=false"
((index++))
done
...
If your are looking to use Raspberry Pi cameras with a Zynq-UltraScale+ based design, I hope that you found this project helpful.
Are you currently using the Raspberry Pi cameras in your embedded projects ? If yes, which platform are you using ?
If you were able to answer the 4 challenge questions, please share your responses in the comments below...
Known IssuesThe following issues are currently unresolved:
- Not able to control DP Controller Planes & CRTC (not critical)
I want to thank Jeff Johnson (Opsero) for his excellent reference design, as well as his fabulous portfolio of FMC hardware:
- [Opsero] RPI Camera FMC
- [Opsero] M.2 M-key Stack FMC
I also want to thank Gianluca Filippini (EBV) for his pioneering work with the Hailo-8 AI Accelerator module, and bringing this marvel to my attention. His feedback, guidance, and insight have been invaluable.
- [Hailo] Hailo-8 AI Acceleration module
- 2024/12/23 - Initial Version
- [Raspberry Pi] RPI Camera Portfolio
- [AMD] Kria AI Vision Kit - NLP-SmartVision app
- [Opsero] RPI Camera FMC Reference Design
- [Ospero] RPI Camera FMC Reference Design - Building
- [Ospero] RPI Camera FMC Reference Design - Modifying
- [AMD/Xilinx] DRM KMS Driver
- [AMD/Xilinx] Video Mixer - Linux Driver
- [AMD/Xilinx] ZynqMP DisplayPort Controller - Linux Driver
Comments