How do I integrate IMX specific plugins for gstreamer in a docker container?

Hello!
I’ve been following the provided examples for video processing using gstreamer pipelines. Problem is my CPU is getting overloaded and I want to offload this a bit to the integrated VPU. I can’t seem to find any information on how to do that without rebuilding the whole image with yocto and adding the recipe for three packages: imx-gpu-g2d imx-gpu-viv gstreamer1.0-plugins-imx imx-gst1.0-plugin.

Is there an easier way to do it inside a container?
Thanks in advance!

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

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


Hello!

Yes, there are ways to utilize the VPU (Video Processing Unit) for hardware-accelerated video processing inside containers on Toradex modules, without having to rebuild the whole image with Yocto. The support and ease of use, however, will depend on your specific Toradex module and the Torizon OS version you are using.

Running GStreamer with VPU in Containers

Torizon provides container images and Dockerfiles that include GStreamer and the relevant plugins for accessing the VPU hardware from userspace within the container. Here’s how you can get started:

  1. Use or Build a GStreamer Container
    Toradex offers sample Dockerfiles that install the full set of GStreamer plugins for multimedia work (see example here). This approach typically works for most video pipelines:

    FROM torizon/wayland-base-vivante:2
    RUN apt-get -y update && apt-get install -y --no-install-recommends \
         gstreamer1.0-plugins-good \
         gstreamer1.0-plugins-bad \
         gstreamer1.0-plugins-ugly \
         gstreamer1.0-plugins-base \
         gstreamer1.0-libav \
         v4l-utils \
         && apt-get clean && apt-get autoremove && rm -rf /var/lib/apt/lists/*
    
  2. Select the Correct Hardware Encoder
    Depending on your module, the hardware-accelerated elements are different. For example:

    • i.MX8: v4l2h264enc*
    • i.MX8M Mini/Plus and i.MX6: vpuenc_h264*

    So, your pipeline might look like this (replace with the correct encoder for your module):

    gst-launch-1.0 videotestsrc ! videoconvert ! v4l2h264enc ! rtph264pay config-interval=1 pt=96 ! udpsink host=<host-ip> port=5000
    

    More details and examples are provided here.

  3. Check Available GStreamer Plugins
    Inside your running container, you can inspect which encoders are available:

    gst-inspect-1.0 | grep -e "encoder"
    

    This will tell you if the VPU encoders are present and accessible.

Torizon OS Version Considerations

Summary

You do not need to rebuild your BSP or add Yocto recipes just to use VPU encoding in containers; install the needed GStreamer plugins in your container, use the hardware-accelerated pipeline elements (v4l2h264enc or vpuenc_h264), and confirm functionality with gst-inspect-1.0. If using Torizon OS 7.x, check on the current plugin/container status as support is actively developing.

For full details and examples, check:

Let me know if you need an example Dockerfile or further clarification!

Best regards,
Toradex AI Assistant.

@ToradexAI
But what packages install the needed vpuenc_h264 gst plugin? The sources listed mention it but none show how to install it. Neither there is an example dockerfile.

Thanks for your response.

Please remember to tick the “Solution” checkbox below if my response solves your question. If you have follow-up questions, just continue to tag me using @ToradexAI in your new posts.

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


Hello!

Thank you for your follow-up question. At the moment, the hardware-accelerated VPU GStreamer plugins, like vpuenc_h264, are not available as installable packages in the standard Debian containers used on Torizon OS. This is a known limitation, especially on Torizon OS 7.x—the required packages (such as gstreamer1.0-plugins-imx or imx-gst1.0-plugin) are not included in the public Debian repositories and thus cannot be directly installed inside containers using apt.

On older BSP (Yocto-based) images or Torizon OS 6.x, it was possible to use proof-of-concept containers with the VPU plugins, but these are not officially maintained and may not work on Torizon OS 7.x. There is an ongoing effort to provide official containerized support for VPU hardware acceleration, but there is currently no published timeline or supported package set for this.

So, to summarize:

  • There is currently no easy way to install the vpuenc_h264 plugin inside a Torizon Debian container by using apt or similar tools.

  • Building a custom Yocto image remains the only (but more involved) way to get these plugins until official VPU-enabled containers are provided for recent Torizon OS versions.

  • As a workaround, only software-encoded plugins (like x264enc) are readily available and installable inside containers:

    apt-get update && apt-get install -y gstreamer1.0-plugins-ugly
    

If you want to check what’s available inside your container, run:

gst-inspect-1.0 | grep -e "encoder"

For more details, please see:

If you have further questions or need guidance for software encoding, let me know!

Best regards,
Toradex AI Assistant.

@ToradexAI Given I’m on torizon 6, how do I use these proof-of-concept containers?

Thanks for your response.

Please remember to tick the “Solution” checkbox below if my response solves your question. If you have follow-up questions, just continue to tag me using @ToradexAI in your new posts.

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


Hello!

On Torizon OS 6.x, you can experiment with hardware-accelerated video encoding/decoding by using the proof-of-concept (PoC) VPU container example provided by Toradex. Here is how you can get started:


1. Clone the Sample Repository

Toradex provides the VPU PoC container example in their torizon-samples repository (specifically under vpu/generic/vpuGeneric).

git clone https://github.com/toradex/torizon-samples.git
cd torizon-samples/vpu/generic/vpuGeneric

2. Update the Dockerfile

Before building, make sure to edit the example Dockerfile:

  • Change the line at the top that sets the BASE_VERSION from 3 to 3.3:
    ARG BASE_VERSION=3.3
    

3. Build the Container

You can now build the container locally with Docker:

docker build -t my-vpu-container .

If you are using TorizonCore Builder and deploying remotely, adapt the workflow to your environment.


4. Run the Container

Start the container using Docker, ensuring you grant access to video devices and required resources:

docker run --rm -it \
    --device=/dev/video0 \
    --device=/dev/vpu \
    -v /tmp:/tmp \
    my-vpu-container

The exact devices to expose (/dev/videoN, /dev/vpu) might vary by module.


5. Use Hardware-Accelerated Pipelines

Once inside the container, use the GStreamer VPUs plugins, such as vpuenc_h264, in your pipeline. For example:

gst-launch-1.0 videotestsrc ! imxvideoconvert_g2d ! vpuenc_h264 ! fakesink

Additional Notes and Limitations

  • This example is a proof-of-concept—it may not be fully production-ready nor officially maintained.
  • The container includes a frozen (older) Debian snapshot to match GStreamer versions.
  • Only select modules (e.g., Verdin iMX8MM, Verdin iMX8MP, Apalis iMX8) were tested; compatibility with others may vary.
  • These PoC containers are not compatible with Torizon OS 7.x.

References

If you need more help adjusting the pipeline or Dockerfile, feel free to ask!

Best regards,
Toradex AI Assistant.

Hi @gabriel.ayres

ToradexAI has all the answers.

For reference, you can check this project.


More specifically, you can check the Dockerfile.

Hello @allan.tx!
When I check the devices it seems that the driver for the vpu wasnt instantiated as theres no /dev/vpu. I’m running an iMX8M Plus. What am I missing here? Shouldn’t my TorizonOS image at least see it?

Thanks a bunch!

(Pinging @ToradexAI as well)

Thanks for your response.

Please remember to tick the “Solution” checkbox below if my response solves your question. If you have follow-up questions, just continue to tag me using @ToradexAI in your new posts.

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


Hello!

This is a good observation, and it is an important detail when working with the VPU on the i.MX8M Plus and similar modules.

On i.MX8M family devices (including the i.MX8M Plus), the VPU hardware is typically accessed through the V4L2 (Video4Linux2) subsystem, and device nodes appear as /dev/video* (e.g., /dev/video0, /dev/video1, etc.)—not as /dev/vpu. The /dev/vpu node exists on some older SoCs (like some i.MX6/7 variants), but on i.MX8M Plus it is normal not to see a /dev/vpu device.

Here’s how to verify VPU-related devices and functionality for the i.MX8M Plus:

  1. List video devices:

    ls -la /dev/video*
    

    On i.MX8M Plus running Torizon OS 6, you should see at least /dev/video0 (and possibly others, like /dev/video1, /dev/video2, etc.). These may correspond to camera, VPU encode, and VPU decode hardware blocks.

  2. Check VPU driver status:
    The drivers for the VPU should be loaded automatically by the kernel if your module and BSP support it. There is no manual driver to load for the VPU.

  3. Find which /dev/video is the VPU:*
    To map which device node provides VPU encode/decode, you can run:

    v4l2-ctl --list-devices
    

    Look for nodes like “imx-dpu”, “Hantro G1”, or similar.

  4. Test GStreamer VPU encoding:
    You can test hardware-accelerated h.264 encoding with:

    gst-launch-1.0 videotestsrc ! v4l2h264enc ! h264parse ! fakesink
    

    If the pipeline runs and uses little CPU, your VPU is indeed in use.

  5. Docker Container Access:
    If running inside a container, make sure you pass the /dev/videoN device (not /dev/vpu) using the --device flag, and that you run with sufficient privileges.

  6. Check for missing VPU nodes:
    If there are no /dev/video* devices (or if v4l2h264enc does not work), there may be a kernel config issue or an incompatibility with your Torizon OS version. Ensure your Torizon OS version matches one of the validated ones for your module.

For more steps and best practices regarding hardware access in Torizon containers:

And for example VPU pipelines with GStreamer on i.MX8:

Summary:
On i.MX8M Plus, not having /dev/vpu is expected. The VPU functionality is available via /dev/video* nodes and accessed through V4L2 GStreamer plugins like v4l2h264enc.

If you still have issues or cannot see any video device nodes, please let me know what you see when you run:

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

Best regards,
Toradex AI Assistant.

Upon starting the pipeline as directed in the articles it seems not to be able to use the VPU.

Running the following pipeline
gst-launch-1.0 videotestsrc ! videoconvert ! vpuenc_h264 ! fakesink

I’m getting

====== VPUENC: 4.7.2 build on Aug 14 2025 13:00:11. ======
        wrapper: 3.0.0 (VPUWRAPPER_ARM64_LINUX Build on Aug 14 2025 12:59:33)
        vpulib: 1.1.1
        firmware: 1.1.1.0
ERROR: from element /GstPipeline:pipeline0/vpuenc_h264:vpuenc_h264-0: Could not initialize supporting library.
Additional debug info:
../gst-libs/gst/video/gstvideoencoder.c(1804): gst_video_encoder_change_state (): /GstPipeline:pipeline0/vpuenc_h264:vpuenc_h264-0:
Failed to start encoder

Checking v4l2-ctl --list devices also returns an error that /dev/video0 is busy.

Am I missing something here?

@allan.tx @ToradexAI

Thanks for your response.

Please remember to tick the “Solution” checkbox below if my response solves your question. If you have follow-up questions, just continue to tag me using @ToradexAI in your new posts.

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


Based on the error messages you’re seeing, this appears to be a known issue with the vpuenc_h264 element on certain BSP versions and configurations. The error “Could not initialize supporting library” indicates that the VPU hardware encoder is having trouble initializing(1).

There are a few approaches to try:

1. Use v4l2h264enc instead of vpuenc_h264

For BSP 7 and some configurations, the recommended approach is to use v4l2h264enc instead of vpuenc_h264(1). Try this pipeline:

gst-launch-1.0 videotestsrc ! videoconvert ! v4l2h264enc ! fakesink

2. Check for device conflicts

Since you mentioned /dev/video0 is busy, there might be another process using the video device. Check what’s using it:

lsof /dev/video*

3. Try alternative pipeline configurations

Based on the official documentation, you can also try these encoding pipelines(2):

gst-launch-1.0 videotestsrc num-buffers=300 ! video/x-raw, width=1920, height=1080, framerate=60/1 ! videoconvert ! vpuenc_h264 ! video/x-h264 ! h264parse ! qtmux ! filesink location=videotestsrc.mp4

Or use the encodebin element which automatically creates an encoding pipeline(2):

gst-launch-1.0 videotestsrc num-buffers=300 ! video/x-raw, width=1920, height=1080, framerate=60/1 ! encodebin ! filesink location=videotestsrc.mp4

4. Debug the VPU initialization

You can get more debugging information by setting the GST_DEBUG environment variable(2):

export GST_DEBUG=2

5. Verify VPU availability

Check if the VPU-related GStreamer elements are properly installed and available:

gst-inspect-1.0 | grep vpu
gst-inspect-1.0 | grep h264enc

This issue appears to be related to the VPU driver initialization problems that have been reported on various BSP versions(1). The community discussion indicates that switching to v4l2h264enc often resolves these initialization issues.

Hi @gabriel.ayres

I just tested it and it’s working.

Video


Run command

  1. Copy the docker-compose.yml
  2. Run this in the module
    docker compose run --service-ports --rm vpugeneric bash
    
  3. Run this in the container
    a. mkdir video
    b. vpuenc_h264
    gst-launch-1.0 videotestsrc num-buffers=300 \
        ! video/x-raw, width=640, height=480 \
        ! vpuenc_h264 \
        ! filesink location=video/test.h264
    
    c. x264enc
    gst-launch-1.0 videotestsrc num-buffers=300 \
        ! video/x-raw, width=640, height=480 \
        ! x264enc \
        ! filesink location=video/test_sw.h264
    
    d. no encoder
    gst-launch-1.0 videotestsrc num-buffers=300 \
        ! video/x-raw, width=640, height=480 \
        ! filesink location=video/test.raw
    

Reference

Run compose

Build containers

Oh, that works. I missed the many bindings and cgroup rules in the compose. Thanks a lot for the help @allan.tx!