Skip to content

video: introduction of STM32 VENC driver for H264 hardware video compression #92884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

hfruchet-st
Copy link
Contributor

This PR introduces H264 hardware video compression thanks to VENC peripheral of STM32N6.

A new stm32 video encoder driver has been introduced which relies on vc8000nanoe software stack [1].
This is a first basic porting to enable H264 encoding use-case.
RAM memory resources required by VENC encoding process are allocated in external PSRAM, camera frames
captured by DCMIPP and encoded by VENC are also allocated in external PSRAM.
The video encoder driver currently lack of controls to configure the encoding process, default configuration
targets H264 1080p 2Mb/s constant bitrate.

In order to test, the tcpserversink video sample has been enhanced to support video compression in order to stream small H264 compressed video chunks instead of big raw uncompressed images.

To build sample: (flash using ST-Link and boot with FSBL [2])

zephyr$> west build -p -b stm32n6570_dk//fsbl --shield st_b_cams_imx_mb1854 samples/drivers/video/tcpserversink

The default configuration allows to capture and stream 1080p camera content from STM32N6 which can be received, decoded and displayed by an host PC using a GStreamer command line:

host$> gst-launch-1.0 tcpclientsrc host=192.0.2.1 port=5000 ! queue ! decodebin ! queue ! fpsdisplaysink sync=false

Tests have been made using ethernet over USB between STM32N6 and host PC thanks to the temporary last 2 commits.
When using ethernet over USB, set the ethernet interface through USB before starting the GStreamer command line:

host$> sudo ifconfig enx00005e005301 192.0.2.2

To find the right interface, search for "enx" in kernel log

host$> dmesg | grep enx
host$> [1316045.847337] cdc_ether 3-6.3.2:1.0 **enx00005e005301**: renamed from eth0

[1] zephyrproject-rtos/hal_stm32#295
[2] https://docs.zephyrproject.org/latest/boards/st/stm32n6570_dk/doc/index.html

hfruchet-st and others added 17 commits July 9, 2025 10:58
Video buffers being often quite big, it might not be possible to
allocate them from the default heap. For that reason, rely on the
mem sw attr heap allocator in order to design from where to
allocate buffers using which attributes.

Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
Add MEM_SW_ATTR on the PSRAM memory in order to have it
become accessible via the mem_attr_heap framework.
On this device since we need to allocate a rather large
framebuffer, we can do that on the PSRAM memory.

Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
Video encoder requires non-cacheable memory.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Add YUV420 semi-planar pixel format (NV12).

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Add YUV420 semi-planar pixel format (NV12).

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Addition of description for the STM32 Video encoder (VENC).

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
The STM32 video encoder (VENC) peripheral is a hardware
accelerator allowing to compress RGB/YUV frames into
H264 video bitstream chunks.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Add node describing the venc in stm32n6.dtsi

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Enable video encoder on stm32n6570_dk discovery board.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Sync with video capture sample.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Add video compression support to lowerize network bandwidth.

To visualise camera content on host PC, use GStreamer command line:
$> gst-launch-1.0 tcpclientsrc host=<board ip address> port=5000 ! decodebin ! autovideosink sync=false

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Add YUV420 semi-planar support (NV12).
This is the video encoder prefered pixel format.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Allow to configure the number of allocated capture frames.
This allows to make tradeof between framerate versus memory usage.
2 buffers allows to capture while sending data (optimal framerate).
1 buffer allows to reduce memory usage but capture framerate is lower.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Add configuration files for the stm32n6570_dk board.

This enables streaming over ethernet of the images captured by
MB1854 camera module compressed in 1920x1088 H264 video bitstream.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Ethernet over USB support.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Disable ethernet phy support to use ethernet over USB.

Signed-off-by: Hugues Fruchet <hugues.fruchet@foss.st.com>
Copy link

github-actions bot commented Jul 9, 2025

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
zephyr-isp 🆕 None (Added) master N/A

DNM label due to: 1 added project and 1 unreachable repo

Note: This message is automatically posted and updated by the Manifest GitHub Action.

Copy link

sonarqubecloud bot commented Jul 9, 2025

@avolmat-st avolmat-st self-requested a review July 9, 2025 11:12
@@ -58,6 +58,20 @@ config VIDEO_I2C_RETRY_NUM
The default is to not retry. Board configuration files or user project can then
use the number of retries that matches their situation.

config VIDEO_BUFFER_USE_MEM_ATTR_HEAP
bool "Use mem attr api for video buffer"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool "Use mem attr api for video buffer"
bool "Allocate video buffer from mem_attr heap"

+ maybe this should depends on MEM_ATTR_HEAP

default n

config VIDEO_BUFFER_MEM_SW_ATTRIBUTE
int "Mem SW attribute for video buffer"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int "Mem SW attribute for video buffer"
int "Heap allocations attribute"

Comment on lines +70 to +73
Mem SW attribute for video buffer:
1: ATTR_SW_ALLOC_CACHE
2: ATTR_SW_ALLOC_NON_CACHE
4: ATTR_SW_ALLOC_DMA
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be best to avoid duplicating information from the header.
Proposal:

Suggested change
Mem SW attribute for video buffer:
1: ATTR_SW_ALLOC_CACHE
2: ATTR_SW_ALLOC_NON_CACHE
4: ATTR_SW_ALLOC_DMA
Attribute to request when performing allocations from mem_attr heap.
Refer to include/zephyr/dt-bindings/memory-attr/memory-attr-sw.h for
the list of allowed values (one of ATTR_SW_*).
For example, if you want to use ATTR_SW_ALLOC_CACHE defined as:
#define ATTR_SW_ALLOC_CACHE BIT(0)
This symbol should be set equal to 1 (equal to (1 << 0)).

Comment on lines +33 to +35
#define VIDEO_COMMON_HEAP_ALLOC(align, size, timeout) \
mem_attr_heap_aligned_alloc((CONFIG_VIDEO_BUFFER_MEM_SW_ATTRIBUTE << \
DT_MEM_SW_ATTR_SHIFT), align, size)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define VIDEO_COMMON_HEAP_ALLOC(align, size, timeout) \
mem_attr_heap_aligned_alloc((CONFIG_VIDEO_BUFFER_MEM_SW_ATTRIBUTE << \
DT_MEM_SW_ATTR_SHIFT), align, size)
#define VIDEO_COMMON_HEAP_ALLOC(align, size, timeout) \
mem_attr_heap_aligned_alloc(DT_MEM_SW(CONFIG_VIDEO_BUFFER_MEM_SW_ATTRIBUTE), \
align, size)

Comment on lines +58 to +60
#if defined(CONFIG_VIDEO_BUFFER_USE_MEM_ATTR_HEAP)
mem_attr_heap_pool_init();
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: should check that return value is 0 or -EALREADY

{
/* VENC HW REset */
__HAL_RCC_VENC_FORCE_RESET();
k_sleep(K_MSEC(1));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe k_busy_wait with a lower delay (if upper bound for tRESET is known and <<< 1ms).

Although polling a "is IP under reset" bit would be better. (Ideally, we would even call reset_line_toggle with info from DT, but driver doesn't perform polling...)

Comment on lines +710 to +711
if (ret)
return -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ret)
return -1;
if (ret) {
return -1;
}

or even ret < 0 and propagate ret

}
LOG_DBG("output=%p\n", output);

if (!(data->frame_nb % 30) || data->resync) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this 30 is framerate dependent, it should come from a macro.

static int video_stm32_venc_set_stream(const struct device *dev, bool enable,
enum video_buf_type type)
{
struct video_stm32_venc_data *data = dev->data;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct video_stm32_venc_data *data = dev->data;
ARG_UNUSED(type);
struct video_stm32_venc_data *data = dev->data;

ISR_DIRECT_DECLARE(stm32_venc_isr)
{
VENC_EWL_TypeDef *enc = &ewl_instance;
u32 hw_handshake_status = READ_BIT(VENC_REG(BASE_HEncInstantInput >> 2U), (1U << 29U));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No HW define for (1 << 29)? (Nit: should be 1U << 29)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants