How to display video captured by OS08A20 camera via HDMI with TorizonOS

Hello,
Could you please tell me how to display video captured by the OS08A20 camera via HDMI with TorizonOS?

■Environment

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


Displaying OS08A20 Camera Video via HDMI on Torizon OS

Overview

To display video from your OS08A20 camera via HDMI on your i.MX95 Evaluation kit with Torizon OS, you’ll need to set up both the camera capture and HDMI display using containers and GStreamer pipelines(1)(2).

Required Setup

1. Weston Container for HDMI Display

First, launch the Weston compositor container to enable HDMI display output(2):

# docker container run -d --name=weston --net=host \
    --cap-add CAP_SYS_TTY_CONFIG \
    -v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
    --device-cgroup-rule="c 4:* rmw" --device-cgroup-rule="c 253:* rmw" \
    --device-cgroup-rule="c 13:* rmw" --device-cgroup-rule="c 226:* rmw" \
    --device-cgroup-rule="c 10:223 rmw" --device-cgroup-rule="c 199:0 rmw" \
    --device-cgroup-rule="c 10:* rmw" \
    torizon/weston-imx95:4 \
    --developer

(2)

2. Camera Device Discovery

Identify your camera’s video device node(2)(3):

# ls /dev/video*
# v4l2-ctl --list-devices

(2)(3)

This will show available video devices and help you identify which /dev/videoX corresponds to your OS08A20 camera(2)(3).

3. Container for Camera Access

Create a container with access to the camera device and display capabilities(2):

# docker run --rm -it -v /tmp:/tmp -v /var/run/dbus:/var/run/dbus -v /dev:/dev -v /sys:/sys \
    --device /dev/<video-device> \
    --device-cgroup-rule='c 226:* rmw' --device-cgroup-rule='c 199:* rmw' \
    <your-dockerhub-username>/<container-name>

(2)

GStreamer Pipeline for Video Display

Basic Pipeline Structure

Use GStreamer to create a pipeline from camera to HDMI display(1)(3):

## gst-launch-1.0 <videosrc> ! <capsfilter> ! <videosink>

(1)(3)

Specific Pipeline Example

## gst-launch-1.0 v4l2src device=</dev/video*> ! <capsfilter> ! fpsdisplaysink video-sink=waylandsink

(2)

For your OS08A20 camera, the pipeline would look like:

# gst-launch-1.0 v4l2src device='/dev/videoX' ! "video/x-raw, format=YUY2, framerate=30/1, width=1920, height=1080" ! fpsdisplaysink video-sink=waylandsink sync=false

(3)

Key Components Explained

  • v4l2src: Captures video from Video4Linux devices(1)(3)
  • capsfilter: Defines video properties like resolution and framerate(1)(3)
  • waylandsink: Displays video on the Wayland display server (Weston) connected to HDMI(1)(3)
  • fpsdisplaysink: Shows current and average frame rates while displaying video(3)

Troubleshooting Tips

  1. Device Tree Overlays: Ensure proper device tree overlays are applied for your OS08A20 camera(4)
  2. Driver Compatibility: Verify the camera driver is compatible with your Torizon OS version(4)
  3. Kernel Logs: Check dmesg for camera-related error messages(4)
  4. Video Device Registration: Use v4l2-ctl --list-devices to confirm the camera is recognized(4)

Hardware Access Requirements

Your container needs specific bind mounts and device access(2):

  • /dev: Access to camera devices
  • /tmp: Interaction with Weston GUI
  • /sys: Kernel subsystem access
  • /var/run/dbus: System services access

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

@ToradexAI

  1. The v4l2-ctl command is not available either inside or outside the container.

  2. For the placeholders "your-dockerhub-username" and "container-name" in the following command, what should be specified?

# docker run --rm -it -v /tmp:/tmp -v /var/run/dbus:/var/run/dbus -v /dev:/dev -v /sys:/sys \
    --device /dev/<video-device> \
    --device-cgroup-rule='c 226:* rmw' --device-cgroup-rule='c 199:* rmw' \
    <your-dockerhub-username>/<container-name>

@ToradexAI

I started the container (Weston) using the command below.

docker container run -d --name=weston --net=host \
–cap-add CAP_SYS_TTY_CONFIG \
-v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
–device /dev/video0 --device /dev/video14 --device /dev/video2 --device /dev/video25 --device /dev/video30 --device /dev/video36 --device /dev/video41 --device /dev/video47 --device /dev/video52 --device /dev/video58 --device /dev/video9 \
–device /dev/video1 --device /dev/video15 --device /dev/video20 --device /dev/video26 --device /dev/video31 --device /dev/video37 --device /dev/video42 --device /dev/video48 --device /dev/video53 --device /dev/video59 \
–device /dev/video10 --device /dev/video16 --device /dev/video21 --device /dev/video27 --device /dev/video32 --device /dev/video38 --device /dev/video43 --device /dev/video49 --device /dev/video54 --device /dev/video6 \
–device /dev/video11 --device /dev/video17 --device /dev/video22 --device /dev/video28 --device /dev/video33 --device /dev/video39 --device /dev/video44 --device /dev/video5 --device /dev/video55 --device /dev/video60 \
–device /dev/video12 --device /dev/video18 --device /dev/video23 --device /dev/video29 --device /dev/video34 --device /dev/video4 --device /dev/video45 --device /dev/video50 --device /dev/video56 --device /dev/video7 \
–device /dev/video13 --device /dev/video19 --device /dev/video24 --device /dev/video3 --device /dev/video35 --device /dev/video40 --device /dev/video46 --device /dev/video51 --device /dev/video57 --device /dev/video8 \
–device-cgroup-rule=“c 4:* rmw” --device-cgroup-rule=“c 253:* rmw” \
–device-cgroup-rule=“c 13:* rmw” --device-cgroup-rule=“c 226:* rmw” \
–device-cgroup-rule=“c 10:223 rmw” --device-cgroup-rule=“c 199:0 rmw” \
–device-cgroup-rule=“c 10:* rmw” \
torizon/weston-imx95:4 \
–developer – --use-pixman

Inside the container, I installed GStreamer and v4l-utils.

apt-get -y update && apt-get install -y --no-install-recommends \
libgstreamer1.0-0 \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-tools \
v4l-utils

When I executed the following command inside the container, the log shown below appeared, and I was unable to display the image captured by the camera.

gst-launch-1.0 v4l2src device=‘/dev/video0’ ! “video/x-raw, format=YUY2, framerate=30/1, width=1920, height=1080” ! fpsdisplaysink video-sink=waylandsink sync=false

Setting pipeline to PAUSED …

(gst-launch-1.0:8246): GStreamer-Wayland-WARNING **: 08:37:26.773: Could not bind to zwp_linux_dmabuf_v1
Pipeline is live and does not need PREROLL …
Pipeline is PREROLLED …
Setting pipeline to PLAYING …
New clock: GstSystemClock
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data stream error.
Additional debug info:
../libs/gst/base/gstbasesrc.c(3132): gst_base_src_loop (): /GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
streaming stopped, reason not-negotiated (-4)
Execution ended after 0:00:00.000776198
Setting pipeline to NULL …
Freeing pipeline …

Addressing Your Issues

1. Container Image for Camera Access

For the container placeholders, you need to use a pre-built GStreamer container with camera support(1). Based on the Torizon samples repository, you should use:

# Clone the torizon-samples repository first
$ cd ~
$ git clone --branch bookworm https://github.com/toradex/torizon-samples.git
$ cd ~/torizon-samples/gstreamer/bash/simple-pipeline

(1)

Then build the container for iMX95:

$ docker build --build-arg BASE_NAME=wayland-base-vivante --build-arg IMAGE_ARCH=linux/arm64/v8 -t <your-dockerhub-username>/gst_example .

(1)

So your command would be:

# docker run --rm -it -v /tmp:/tmp -v /var/run/dbus:/var/run/dbus -v /dev:/dev -v /sys:/sys \
    --device /dev/<video-device> \
    --device-cgroup-rule='c 226:* rmw' --device-cgroup-rule='c 199:* rmw' \
    <your-dockerhub-username>/gst_example

(1)

2. Identifying the Correct Video Device

Since v4l2-ctl is available in your container now, use it to identify which video device corresponds to your OS08A20 camera(1)(2):

## v4l2-ctl --list-devices

(1)(2)

Then check each device to find the capture device(2):

## v4l2-ctl --device /dev/video0 -D

(2)

Look for devices with “Video Capture” capability in the output(2).

3. Fixing the Pipeline Negotiation Error

The “not-negotiated” error indicates the camera doesn’t support the format/resolution you specified. Try these approaches:

Step 1: Check supported formats for your camera device(2):

# v4l2-ctl --device=/dev/video0 --list-formats-ext

(2)

Step 2: Use a simpler pipeline without strict format constraints(1)(2):

## gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! waylandsink

(1)(2)

Step 3: If that works, gradually add format specifications based on what your camera actually supports(2):

# gst-launch-1.0 v4l2src device='/dev/video0' ! "video/x-raw, format=YUY2, framerate=5/1, width=640, height=480" ! waylandsink

(2)

4. Alternative Pipeline Structure

Try this basic pipeline structure first(1):

## gst-launch-1.0 v4l2src device=</dev/video*> ! <capsfilter> ! fpsdisplaysink video-sink=waylandsink

(1)

5. Troubleshooting Steps

  1. Test each video device systematically - With 60+ video devices, you need to identify which one is your actual camera(1)(2)
  2. Check device capabilities - Use v4l2-ctl -D on each device to find the capture device(2)
  3. Start with minimal pipeline - Begin with just v4l2src ! waylandsink before adding format constraints(2)
  4. Verify camera driver - Ensure your OS08A20 camera driver is properly loaded and the device tree overlay is applied(3)

The key issue is likely that /dev/video0 may not be your actual camera device, or the format specifications don’t match what your OS08A20 camera supports.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

@ToradexAI

I was able to start the Weston container and the GStreamer container using the commands below.

For weston container:

docker container run -d --name=weston --net=host
–cap-add CAP_SYS_TTY_CONFIG
-v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/
–device-cgroup-rule=“c 4:* rmw” --device-cgroup-rule=“c 253:* rmw”
–device-cgroup-rule=“c 13:* rmw” --device-cgroup-rule=“c 226:* rmw”
–device-cgroup-rule=“c 10:223 rmw” --device-cgroup-rule=“c 199:0 rmw”
–device-cgroup-rule=“c 10:* rmw”
–privileged torizon/weston-imx95:4
–developer – --use-pixman

For GStreamer container:

docker build --build-arg BASE_NAME=wayland-base-vivante
–build-arg IMAGE_ARCH=linux/arm64/v8 -t torizon/gst_example .
docker run --rm -it -v /tmp:/tmp -v /var/run/dbus:/var/run/dbus -v /dev:/dev -v /sys:/sys
–device /dev/video0
–device-cgroup-rule=‘c 226:* rmw’ --device-cgroup-rule=‘c 199:* rmw’
–entrypoint “bash” --privileged torizon/gst_example

However, when I try to play a pipeline in the GStreamer container, I get the following error and playback fails.

using the commands below.

gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! waylandsink sync=false

Log is below.

root@a9b43f992cd4:/# gst-launch-1.0 v4l2src device=/dev/video0 ! waylandsink sync=falseSetting pipeline to PAUSED …
(gst-launch-1.0:48): GStreamer-Wayland-WARNING **: 01:45:01.718: Could not bind to zwp_linux_dmabuf_v1
Pipeline is live and does not need PREROLL …
Pipeline is PREROLLED …Setting pipeline to PLAYING …
New clock: GstSystemClock
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Failed to allocate required memory.
Additional debug info:
../sys/v4l2/gstv4l2src.c(976): gst_v4l2src_decide_allocation ():/GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
Buffer pool activation failed
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data stream error.
Execution ended after 0:00:00.029612666
Additional debug info:
../libs/gst/base/gstbasesrc.c(3132): gst_base_src_loop ():/GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
streaming stopped, reason not-negotiated (-4)
Setting pipeline to NULL …Freeing pipeline …

For reference, the test signal was able to play successfully.

using the commands below.

gst-launch-1.0 videotestsrc ! videoconvert ! waylandsink sync=false

Diagnosing the Memory Allocation Error

The error “Failed to allocate required memory” and “Buffer pool activation failed” indicates a memory allocation issue with the V4L2 source element(1)(2). This is a common problem when working with multiple cameras or insufficient memory buffers.

1. Verify Camera Device Capabilities

First, check if /dev/video0 is actually your OS08A20 camera and what formats it supports(3)(4):

# v4l2-ctl --device=/dev/video0 -D
# v4l2-ctl --device=/dev/video0 --list-formats-ext

(3)(4)

Look for devices with “Video Capture” capability in the output(4).

2. Memory Buffer Configuration

The memory allocation error suggests the V4L2 buffer pool cannot be activated. Try reducing the memory requirements by specifying smaller buffer sizes(1):

# gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=10 ! videoconvert ! waylandsink sync=false

(1)

3. Alternative Pipeline Approaches

Try these progressive troubleshooting steps:

Step 1: Test with explicit format constraints(3)(4):

# gst-launch-1.0 v4l2src device='/dev/video0' ! "video/x-raw, format=YUY2, framerate=5/1, width=640, height=480" ! waylandsink

(3)(4)

Step 2: If that fails, try without videoconvert(3):

# gst-launch-1.0 v4l2src device=/dev/video0 ! waylandsink sync=false

(3)

Step 3: Use a simpler sink for testing(5):

# gst-launch-1.0 v4l2src device=/dev/video0 ! autovideosink

(5)

4. Container Memory and Device Access

The issue might be related to container memory limits or device access. Try running the container with additional memory and device permissions(1)(2):

# docker run --rm -it -v /tmp:/tmp -v /var/run/dbus:/var/run/dbus -v /dev:/dev -v /sys:/sys \
    --device /dev/video0 \
    --device-cgroup-rule='c 226:* rmw' --device-cgroup-rule='c 199:* rmw' \
    --privileged --memory=1g --memory-swap=2g \
    torizon/gst_example

(1)(2)

5. Check for USB Bandwidth Issues

Similar to the medical device example, you might be experiencing USB bandwidth limitations(1). The documentation shows this error pattern:

[10768.346378] usb 1-1.3: Not enough bandwidth for new device state.
[10768.346391] usb 1-1.3: Not enough bandwidth for altsetting 11

(1)

Check your kernel logs for similar messages:

# dmesg | grep -i bandwidth
# dmesg | grep -i usb

6. Debugging with GST_DEBUG

Enable GStreamer debugging to get more detailed information(3):

# export GST_DEBUG=2
# gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! waylandsink sync=false

(3)

7. Verify Camera Driver and Device Tree

Since the test signal works but the camera doesn’t, ensure your OS08A20 camera driver is properly loaded and the device tree overlay is correctly applied(4). The camera module needs proper hardware setup and driver support(4).

The successful videotestsrc pipeline confirms that your Weston display and container setup are working correctly - the issue is specifically with camera access and memory allocation.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.