Skip to content

Commit 4a74d3e

Browse files
committed
samples: subsys: Add libMP video examples
Add video examples for libMP which includes two pipelines: - camera source and display sink - camera source, video transform and display sink Signed-off-by: Phi Bang Nguyen <[email protected]> Signed-off-by: Trung Hieu Le <[email protected]>
1 parent d169712 commit 4a74d3e

File tree

10 files changed

+363
-0
lines changed

10 files changed

+363
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CMAKE_MINIMUM_REQUIRED (VERSION 3.20.0)
2+
3+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
4+
5+
project(video_example)
6+
7+
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/camera_display.c)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
.. zephyr:code-sample:: video_examples/camera_display
2+
:name: Camera Display Example
3+
4+
A sample pipeline composed of two elements: a camera source and a display sink.
5+
6+
Description
7+
***********
8+
9+
|--[Camera source]--|--->---|--[Display sink]--|
10+
11+
This example demonstrates a pipeline consisting of two elements: source and sink.
12+
The source element, which acts as a capture device, generates video frames and pushes
13+
them to the sink element, which serves as a display device to render the content on screen.
14+
15+
Requirements
16+
************
17+
18+
* A board with input camera support
19+
* A board with output display support
20+
* Sufficient RAM for video buffering
21+
22+
This sample has been tested on the following boards:
23+
* native_sim/native/64
24+
* mimxrt1170_evk@B/mimxrt1176/cm7
25+
26+
Building and Running
27+
********************
28+
29+
For :zephyr:board:`native_sim`, build the sample with the following command:
30+
31+
.. zephyr-app-commands::
32+
:zephyr-app: samples/subsys/libmp/video_examples/camera_display
33+
:board: native_sim/native/64
34+
:goals: build
35+
:snippets: video-sw-generator
36+
:compact:
37+
38+
For :zephyr:board:`mimxrt1170_evk`, build the sample with the following command:
39+
40+
.. zephyr-app-commands::
41+
:zephyr-app: samples/subsys/libmp/video_examples/camera_display
42+
:board: mimxrt1170_evk/mimxrt1176/cm7
43+
:shield: nxp_btb44_ov5640,rk055hdmipi4ma0
44+
:goals: build
45+
:compact:
46+
47+
Wiring
48+
******
49+
50+
On :zephyr:board:`native_sim`, no wiring is needed since it uses a software video generator
51+
as source, however for the display output you need to ensure that your host system supports
52+
SDL2 to emulate the display.
53+
54+
55+
On :zephyr:board:`mimxrt1170_evk`, the OV5640 camera module should be plugged into the J2
56+
camera connector, the display module RK055HDMIPI4MA0 should be plugged into the J48 MIPI LCD connector.
57+
An additional USB cable is needed to connect USB debug port (J11) on the board to the host PC.
58+
59+
60+
Sample Output
61+
*************
62+
63+
The application will start the video pipeline and display the camera frames on the screen.
64+
Check for any error messages during initialization:
65+
66+
.. code-block:: console
67+
68+
*** Booting Zephyr OS build ***
69+
[00:00:00.321,000] <inf> mp_zdisp_sink: Display device: display-controller@40804000
70+
[00:00:00.373,000] <inf> mp_zvid_buffer_pool: Started streaming
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=3686800
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/video-controls.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/logging/log.h>
10+
11+
#include <mp.h>
12+
13+
LOG_MODULE_REGISTER(main);
14+
15+
#define LOG_LEVEL LOG_LEVEL_DBG
16+
17+
int main()
18+
{
19+
int ret;
20+
21+
/* Initialize built-in elements and plugins */
22+
mp_init();
23+
24+
/* Create elements */
25+
MpElement *source = mp_element_factory_create("zvid_src", "camsrc");
26+
if (source == NULL) {
27+
LOG_ERR("Failed to create camsrc element");
28+
return 1;
29+
}
30+
31+
MpElement *sink = mp_element_factory_create("zdisp_sink", "dispsink");
32+
if (sink == NULL) {
33+
LOG_ERR("Failed to create dispsink element");
34+
return 1;
35+
}
36+
37+
/* Set elements' properties */
38+
ret = mp_object_set_properties(MP_OBJECT(source), PROP_NUM_BUFS, 2, VIDEO_CID_HFLIP, 1,
39+
PROP_LIST_END);
40+
if (ret < 0) {
41+
return ret;
42+
}
43+
44+
/* Create a new pipeline */
45+
MpElement *pipeline = mp_pipeline_new("cam_disp");
46+
if (pipeline == NULL) {
47+
LOG_ERR("Failed to create pipeline");
48+
return 1;
49+
}
50+
51+
/* Add elements to the pipeline - order does not matter */
52+
if (mp_bin_add(MP_BIN(pipeline), source, sink, NULL) == false) {
53+
LOG_ERR("Failed to add elements");
54+
return 1;
55+
}
56+
57+
/* Link elements together - order does matter */
58+
if (mp_element_link(source, sink, NULL) == false) {
59+
LOG_ERR("Failed to link elements");
60+
return 1;
61+
}
62+
63+
/* Start playing */
64+
if (mp_element_set_state(pipeline, MP_STATE_PLAYING) != MP_STATE_CHANGE_SUCCESS) {
65+
LOG_ERR("Failed to start pipeline");
66+
return 1;
67+
}
68+
69+
/* Handle message from the pipeline */
70+
MpBus *bus = mp_element_get_bus(pipeline);
71+
/* Wait until an Error or an EOS - blocking */
72+
MpMessage *msg = mp_bus_pop_msg(bus, MP_MESSAGE_ERROR | MP_MESSAGE_EOS);
73+
if (msg != NULL) {
74+
switch (MP_MESSAGE_TYPE(msg)) {
75+
case MP_MESSAGE_ERROR:
76+
LOG_INF("Received ERROR from %s", msg->src->name);
77+
break;
78+
case MP_MESSAGE_EOS:
79+
LOG_INF("Received EOS from %s", msg->src->name);
80+
break;
81+
default:
82+
LOG_ERR("Unexpected message received from %s", msg->src->name);
83+
break;
84+
}
85+
}
86+
87+
/* TODO: Stop pipeline and free allocated ressources */
88+
89+
return 0;
90+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CONFIG_LOG=y
2+
3+
CONFIG_MP=y
4+
CONFIG_MP_PLUGIN_ZVID=y
5+
CONFIG_MP_PLUGIN_ZDISP=y
6+
7+
CONFIG_VIDEO=y
8+
CONFIG_DISPLAY=y
9+
10+
CONFIG_SHELL=y
11+
CONFIG_DEVICE_SHELL=y
12+
13+
CONFIG_HEAP_MEM_POOL_SIZE=10000
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CMAKE_MINIMUM_REQUIRED (VERSION 3.20.0)
2+
3+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
4+
5+
project(video_example)
6+
7+
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/camera_transform_display.c)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
.. zephyr:code-sample:: video_examples/camera_transform_display
2+
:name: Camera Transform Display Example
3+
4+
A sample pipeline composed of three elements: a camera source, a video transform, and a display sink.
5+
6+
Description
7+
***********
8+
|--[Source element]--|-->--[Transform element]--|-->--[Sink element]--|
9+
10+
This example demonstrates a pipeline consisting of three elements: source, transform, and sink.
11+
The source element, which acts as a capture device, generates video frames and pushes them to
12+
the transform element. The transform element then processes these frames and forwards them to
13+
the sink element, which serves as a display device to render the content on screen.
14+
15+
Requirements
16+
************
17+
18+
* A board with input camera support
19+
* A board with output display support
20+
* Sufficient RAM for video buffering
21+
22+
This sample has been tested on the following boards:
23+
* mimxrt1170_evk@B/mimxrt1176/cm7
24+
25+
Building and Running
26+
********************
27+
28+
For :zephyr:board:`mimxrt1170_evk`, build this sample application with the following commands:
29+
30+
.. zephyr-app-commands::
31+
:zephyr-app: samples/subsys/libmp/video_examples/camera_transform_display
32+
:board: mimxrt1170_evk/mimxrt1176/cm7
33+
:shield: nxp_btb44_ov5640,rk055hdmipi4ma0
34+
:goals: build flash
35+
:compact:
36+
37+
Wiring
38+
******
39+
On :zephyr:board:`mimxrt1170_evk`, the OV5640 camera module should be plugged into the J2
40+
camera connector, the display module RK055HDMIPI4MA0 should be plugged into the J48 MIPI LCD connector.
41+
An additional USB cable is needed to connect USB debug port (J11) on the board to the host PC.
42+
43+
44+
Sample Output
45+
*************
46+
47+
.. code-block:: console
48+
49+
*** Booting Zephyr OS build ***
50+
[00:00:00.321,000] <inf> mp_zdisp_sink: Display device: display-controller@40804000
51+
[00:00:00.373,000] <inf> mp_zvid_buffer_pool: Started streaming
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=3686800
2+
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=3
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/video-controls.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/logging/log.h>
10+
11+
#include <mp.h>
12+
13+
LOG_MODULE_REGISTER(main);
14+
15+
#define LOG_LEVEL LOG_LEVEL_DBG
16+
17+
int main()
18+
{
19+
int ret;
20+
21+
/* Initialize built-in elements and plugins */
22+
mp_init();
23+
24+
/* Create elements */
25+
MpElement *source = mp_element_factory_create("zvid_src", "camsrc");
26+
if (source == NULL) {
27+
LOG_ERR("Failed to create camsrc element");
28+
return 0;
29+
}
30+
31+
MpElement *transform = mp_element_factory_create("zvid_transform", "vtransform");
32+
if (transform == NULL) {
33+
LOG_ERR("Failed to create vtransform element");
34+
return 0;
35+
}
36+
37+
MpElement *sink = mp_element_factory_create("zdisp_sink", "dispsink");
38+
if (sink == NULL) {
39+
LOG_ERR("Failed to create dispsink element");
40+
return 0;
41+
}
42+
43+
/* Set elements' properties */
44+
ret = mp_object_set_properties(MP_OBJECT(source), PROP_NUM_BUFS, 3, VIDEO_CID_HFLIP, 1,
45+
PROP_LIST_END);
46+
if (ret < 0) {
47+
return ret;
48+
}
49+
50+
static const struct device *const pxp_dev = DEVICE_DT_GET(DT_NODELABEL(pxp));
51+
52+
if (!device_is_ready(pxp_dev)) {
53+
LOG_ERR("%s: pxp device is not ready", pxp_dev->name);
54+
return -ENODEV;
55+
}
56+
57+
ret = mp_object_set_properties(MP_OBJECT(transform), PROP_DEVICE, pxp_dev, VIDEO_CID_ROTATE,
58+
90, PROP_LIST_END);
59+
if (ret < 0) {
60+
return ret;
61+
}
62+
63+
/* Create a new pipeline */
64+
MpElement *pipeline = mp_pipeline_new("cam_transform_disp");
65+
if (pipeline == NULL) {
66+
LOG_ERR("Failed to create pipeline");
67+
return 0;
68+
}
69+
70+
/* Add elements to the pipeline - order does not matter */
71+
if (mp_bin_add(MP_BIN(pipeline), source, transform, sink, NULL) == false) {
72+
LOG_ERR("Failed to add elements");
73+
return 0;
74+
}
75+
76+
/* Link elements together - order does matter */
77+
if (mp_element_link(source, transform, sink, NULL) == false) {
78+
LOG_ERR("Failed to link elements");
79+
return 0;
80+
}
81+
82+
/* Start playing */
83+
if (mp_element_set_state(pipeline, MP_STATE_PLAYING) != MP_STATE_CHANGE_SUCCESS) {
84+
LOG_ERR("Failed to start pipeline");
85+
return 0;
86+
}
87+
88+
/* Handle message from the pipeline */
89+
MpBus *bus = mp_element_get_bus(pipeline);
90+
/* Wait until an Error or an EOS - blocking */
91+
MpMessage *msg = mp_bus_pop_msg(bus, MP_MESSAGE_ERROR | MP_MESSAGE_EOS);
92+
if (msg != NULL) {
93+
switch (MP_MESSAGE_TYPE(msg)) {
94+
case MP_MESSAGE_ERROR:
95+
LOG_INF("Received ERROR from %s", msg->src->name);
96+
break;
97+
case MP_MESSAGE_EOS:
98+
LOG_INF("Received EOS from %s", msg->src->name);
99+
break;
100+
default:
101+
LOG_ERR("Unexpected message received from %s", msg->src->name);
102+
break;
103+
}
104+
}
105+
106+
/* TODO: Stop pipeline and free allocated ressources */
107+
108+
return 0;
109+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CONFIG_LOG=y
2+
3+
CONFIG_MP=y
4+
CONFIG_MP_PLUGIN_ZVID=y
5+
CONFIG_MP_PLUGIN_ZDISP=y
6+
7+
CONFIG_VIDEO=y
8+
CONFIG_DISPLAY=y
9+
10+
CONFIG_SHELL=y
11+
CONFIG_DEVICE_SHELL=y
12+
13+
CONFIG_HEAP_MEM_POOL_SIZE=12000

0 commit comments

Comments
 (0)