The camera works on the board, then goes silent the moment it runs in a container. That gap is rarely a sensor fault: it is a device-visibility problem with a fixed sequence of fixes. This walkthrough is for engineers bringing a MIPI CSI camera up in Docker-style containers on an embedded board. You will pass the right device files in, prove frames arrive, size the link and the buffer ring, and decide when a USB camera simply removes the problem.
What a container needs to see a CSI camera
A container sees devices, not cameras. For CSI capture, four things must all be true, and all of them live on the host:
- the
/dev/video*character device the receiver driver creates for capture - the
/dev/media*media controller node that holds the pipeline graph - the sensor and receiver kernel modules loaded on the host kernel
- read permission on those nodes for the user inside the container
Miss one and the application inside sees nothing, usually without an error naming the missing piece. Recent platform releases for embedded AI boards treat CSI capture, ISP and hardware encoders as supported container features; older releases route the camera through host-only services that never appear inside. Read the platform release notes before spending an hour on mounts: if CSI in containers is not a listed feature, no device flag will conjure it, and the fix is a board image upgrade or the USB route at the end of this guide.
Bring the camera up on the host first
The container inherits whatever state the host pipeline is in, so prove the host side before any container work:
ls /dev/video* /dev/media*
v4l2-ctl -d /dev/video0 --list-formats-ext
media-ctl -d /dev/media0 -p
Three checks, in order. The device files exist and belong to the sensor you wired. The receiver lists the mode you want: if the mode is missing on the host, the container will not add it, so start with the checklist for MIPI CSI camera resolution limits. The media graph shows the sensor linked to the receiver with the route active. Then capture 30 frames on the host and read back the frame count and the negotiated format. A camera that drops frames on the host drops them faster in a container, because the container adds scheduling hops.
Pass the devices into the container
- Record both node types. A CSI camera owns a video node and usually a media node. Write both down, and re-check after every hardware change: node numbers move when another camera or capture application starts, the failure described in why camera device nodes disappear when a second application starts.
- Configure the media graph on the host. Link enabling, routing and bus format live in the media controller. Set them once with the host tools and keep the script in version control; the container reuses that state.
-
Start the container with both nodes. Docker-style runtimes take a device flag per file:
--device /dev/video0 --device /dev/media0. Passing only the video node when the driver needs its media node is the classic silent failure; the walkthrough on passing V4L2 media nodes, not just /dev/video0, shows the full mapping. - Grant access by numeric group. Add the host video group's numeric ID as a supplementary group at run time instead of rebuilding the image; the permission checks for video and media nodes list what to look for.
-
Keep the mount narrow. In production, pass named device files. A full
/devmount works on the bench and hands the container every device on the board. - List the nodes inside the container. Before running any application, confirm both files exist and are readable by the container user. Thirty seconds here saves the first hour of debugging.
Prove frames inside and fix the pixel format
Run the same fixed-count capture inside the container:
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=30 ! fakesink
Two results matter. First, frames arrive in the negotiated format: if the first frames come out grey, green or striped, format negotiation inside the image differs from the host, and the grey-image-at-runtime isolation guide walks the split. Fix it by negotiating the format explicitly on both sides instead of trusting defaults, because capture libraries disagree about defaults. Second, frames arrive at the negotiated rate: 30 frames at 30 fps takes 1.0 s, so a 2 s run means the delivered rate has halved, and the next section is your suspect.
Size the link and the buffer pool
Worked example, 1080p30 in YUV 4:2:2 at 2 bytes per pixel:
1920 × 1080 × 2 × 8 × 30 = 995,328,000 bit/s ≈ 0.99 Gbit/s
Packed 10-bit raw at 1.25 bytes per pixel gives 1920 × 1080 × 1.25 × 8 × 30 = 622,080,000 bit/s ≈ 0.62 Gbit/s. Both figures exclude packet overhead, so treat them as floors.
Typical embedded receivers terminate MIPI D-PHY data lanes at 1.5 Gbit/s each. One lane carries the 0.99 Gbit/s YUV stream at 66% utilization: legal, but a second virtual channel or the overhead eats the rest. Four lanes provide 6 Gbit/s raw, and the same stream sits at 17% utilization with room to spare. This arithmetic also predicts a halved frame rate: when the measured rate drops to roughly half, a lane or a mode fell back.
Frame size also sets the buffer ring. At 4,147,200 bytes per frame, a four-buffer ring holds about 16.6 MB. Give the ring at least four buffers, since three is a common default and a scheduler hiccup while the pipeline spins up will drop frames at two.
Three failures that cost a day
No frames only inside the container. The media node was not passed, or the graph was never configured on the host. Most reports that the container is broken end here; go back to steps 1 and 2.
Runs for a while, then the stream dies. Usually a receiver timeout rather than a container bug. The write-up on why a CSI camera stream stops after hours walks the watchdog behavior and the recovery.
Encoding or ISP work lands on the CPU and the board throttles. The accelerator is a device like the camera: pass its device files too, and ship the matching library version in the image. The article on GStreamer hardware decoder availability explains why one viewer works while another silently falls back to software.
When to skip CSI and add a USB camera
If the platform cannot pass CSI into containers, or one camera image must run on the board and on a bench PC during development, stop fighting the receiver and use USB3. The container runtime passes a USB camera through a standard device declaration with no media graph and no vendor stack involved; the walkthrough on passing a USB camera into containers with a CDI spec shows the file. If cable distance rather than containers is the constraint, a CSI camera Ethernet extension kit carries the signal without a new driver. For the interface trade itself, the comparison of CSI versus USB camera connections on industrial controllers sets out when each one wins.
All three of the parts below are USB3 board-level cameras from the board-level cameras category, and each appears to a container as an ordinary USB device. For motion work, start here:
- Sensor format
- 1/1.8"
- Lens mount
- C-mount
- Interface
- USB3
- Resolution
- 5 MP
The LS-BCM-0003 captures 120 fps at 3.1 MP with a global shutter. For static scenes and tight builds:
- Sensor format
- 1/1.8"
- Interface
- USB3
- Sensor format
- 1/2.7"
- Lens mount
- C-mount
The MV-CB060-10UM-B is a 6 MP bare board for custom housings; the LS-BCM-0047 is a 1.3 MP USB module on a C-mount. Before swapping sensor families mid-project, run the board camera evaluation checklist so mount, format and driver questions surface early. The camera finder filters both interface families by sensor, resolution and shutter.
Checks before you commit
- Host capture holds the negotiated rate for a 60-second run. Container tuning cannot rescue a marginal host pipeline.
- Both node types are visible inside the container. List them from inside, not from memory.
- The container user reads the nodes without root. Root masks a permissions failure until it bites in production.
- Delivered rate holds while the application starts. A four-buffer ring at 1080p absorbs the start-up hiccup; a two-buffer ring does not.
- Hardware encode stays hardware. Steady-state CPU use tells you immediately when an accelerator fell back.
- One USB fallback is proven. A tested USB3 module keeps the schedule when a platform refuses CSI passthrough.
If the camera choice is still open, the camera configurator walks sensor, shutter and mount options, and the systems topic page collects the rest of the container and bring-up fixes. Contact us with the board and the mode you need, and we will help spec the camera side.
Questions
Why does my CSI camera work on the host but show no frames in the container?
In nearly every case a device file is missing inside the container, not a camera fault. Capture needs both the video node and the media controller node; with only the video node passed in, many receiver drivers cannot reconfigure their links and deliver nothing rather than an error. List the device files inside the container first, before reinstalling anything or touching the pipeline.
How much bandwidth does a 1080p30 CSI-2 stream need?
About 995 Mbit/s for 1920 × 1080 at 30 fps in YUV 4:2:2: 1920 × 1080 × 2 bytes × 8 bits × 30 = 995,328,000 bit/s. Packed 10-bit raw comes to roughly 622 Mbit/s. A single D-PHY lane at a typical 1.5 Gbit/s carries the YUV stream at 66% utilization; four lanes cut that to 17%.
Can the board vendor's camera libraries run inside the container image?
Only when the image carries those libraries and their runtime dependencies at the same major versions as the host kernel modules. Version drift fails in ways that look like hardware faults. The dependable split is to keep the vendor stack and media configuration on the host and hand the container plain V4L2 devices it reads like any other capture source.
Do I have to rebuild the image to add the video group?
No. Read the video group's numeric ID on the host and add it as a supplementary group with a run-time flag when the container starts. Nothing in the image changes, which also keeps one image portable across boards that number the video group differently.
When is USB the better interface for an embedded camera?
Three cases: the platform release cannot pass CSI capture into containers at all; the same camera must run on a bench PC during development and on the board in production; or the sensor you need ships only as a USB module. A USB3 board camera then appears to every container as an ordinary USB device.


