OpenCV Raspicam Ubuntu 24 Server

I’m trying to run a streaming webserver on raspberry Pi

I’m encountering difficulties running the Raspicam on Ubuntu 24.04.4 LTS Server

I got the raspicam working by compiling libcamera from source, then using MJPG webserver streaming. latency is good at less than 150ms but is CPU heavy. it’s 350mA idle, and 700mA when streaming.. So ?m sure the pipeline can work.

I ought to be using the hardware h264 encoder and stream h264

I attempted to do it with OpenCV. My plan is to use the V4L2 linux driver without libcamera, and open the media sources with opencv. Get a stream from /dev/video0 feed it to the transcoder /dev/video10 take the frames and send the stream this way.

(.venv) sona@rpi4-orso-sdbh:~/HowTo-Ubuntu24S-Raspicam-Webserver-Streaming$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12
        /dev/video18
        /dev/video31
        /dev/media3

bcm2835-isp (platform:bcm2835-isp):
        /dev/video13
        /dev/video14
        /dev/video15
        /dev/video16
        /dev/video20
        /dev/video21
        /dev/video22
        /dev/video23
        /dev/media1
        /dev/media4

unicam (platform:fe801000.csi):
        /dev/video0
        /dev/media2

rpivid (platform:rpivid):
        /dev/video19
        /dev/media0

OpenCV does open the camera, but I only get black frames, and I don’t understand why…

"""
uv pip install opencv-python-headless
python demo-opencv-snap-still.py
"""

import subprocess
import cv2
import numpy as np

DEVICE = "/dev/video0"
#DEVICE = "/dev/media0"
NUM_FRAMES = 10

print(f"\n=== Inspecting {DEVICE} ===\n")

# --- 1. Device info ---------------------------------------------------------
def print_device_info(dev):
    print("Device info:")
    try:
        out = subprocess.check_output(
            ["v4l2-ctl", "-d", dev, "--info"],
            stderr=subprocess.STDOUT
        ).decode()
        print(out)
    except Exception as e:
        print("  Could not read device info:", e)

# --- 2. Supported resolutions -----------------------------------------------
def print_resolutions(dev):
    print("Supported formats & resolutions:")
    try:
        out = subprocess.check_output(
            ["v4l2-ctl", "-d", dev, "--list-formats-ext"],
            stderr=subprocess.STDOUT
        ).decode()
        print(out)
    except Exception as e:
        print("  Could not list resolutions:", e)

# --- 3. OpenCV capture + brightness test ------------------------------------
def test_capture(dev):
    print(f"\nOpening {dev} with OpenCV...\n")
    cap = cv2.VideoCapture(dev)

    if not cap.isOpened():
        print("ERROR: OpenCV cannot open device")
        return

    # --- Show what OpenCV actually selected ---
    w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
    fmt = "".join([chr((fourcc >> 8*i) & 0xFF) for i in range(4)])

    print(f"OpenCV selected resolution: {int(w)}x{int(h)}")
    print(f"OpenCV selected pixel format: {fmt}")

    brightness_values = []
    last_frame = None

    for i in range(NUM_FRAMES):
        ret, frame = cap.read()
        if not ret:
            print(f"Frame {i}: FAILED")
            continue

        print("Frame shape:", frame.shape, "dtype:", frame.dtype)
        print("First 32 bytes:", frame.flatten()[:32])


        last_frame = frame

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        brightness = float(np.mean(gray))
        brightness_values.append(brightness)

        print(f"Frame {i}: brightness={brightness:.2f}")

    cap.release()

    if brightness_values:
        avg = sum(brightness_values) / len(brightness_values)
        print(f"\nAverage brightness: {avg:.2f}")
    else:
        print("No valid frames captured.")

    if last_frame is not None:
        cv2.imwrite("test.jpg", last_frame)
        print("Saved test.jpg")


# --- Run all diagnostics ----------------------------------------------------
print_device_info(DEVICE)
print_resolutions(DEVICE)
test_capture(DEVICE)
(.venv) sona@rpi4-orso-sdl:~/HowTo-Ubuntu24S-Raspicam-Webserver-Streaming$ python demo-opencv-snap-still.py

=== Inspecting /dev/video0 ===

Device info:
Driver Info:
        Driver name      : unicam
        Card type        : unicam
        Bus info         : platform:fe801000.csi
        Driver version   : 6.8.12
        Capabilities     : 0xa5a00001
                Video Capture
                Metadata Capture
                I/O MC
                Read/Write
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x25200001
                Video Capture
                I/O MC
                Read/Write
                Streaming
                Extended Pix Format
Media Driver Info:
        Driver name      : unicam
        Model            : unicam
        Serial           : 
        Bus info         : platform:fe801000.csi
        Media version    : 6.8.12
        Hardware revision: 0x00000000 (0)
        Driver version   : 6.8.12
Interface Info:
        ID               : 0x03000005
        Type             : V4L Video
Entity Info:
        ID               : 0x00000003 (3)
        Name             : unicam-image
        Function         : V4L2 I/O
        Flags            : default
        Pad 0x01000004   : 0: Sink
          Link 0x02000007: from remote pad 0x1000002 of entity 'ov5647 10-0036' (Camera Sensor): Data, Enabled, Immutable

Supported formats & resolutions:
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [1]: 'UYVY' (UYVY 4:2:2)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [2]: 'YVYU' (YVYU 4:2:2)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [3]: 'VYUY' (VYUY 4:2:2)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [4]: 'RGBP' (16-bit RGB 5-6-5)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [5]: 'RGBR' (16-bit RGB 5-6-5 BE)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [6]: 'RGBO' (16-bit A/XRGB 1-5-5-5)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [7]: 'RGBQ' (16-bit A/XRGB 1-5-5-5 BE)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [8]: 'RGB3' (24-bit RGB 8-8-8)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [9]: 'BGR3' (24-bit BGR 8-8-8)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [10]: 'RGB4' (32-bit A/XRGB 8-8-8-8)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [11]: 'BA81' (8-bit Bayer BGBG/GRGR)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [12]: 'GBRG' (8-bit Bayer GBGB/RGRG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [13]: 'GRBG' (8-bit Bayer GRGR/BGBG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [14]: 'RGGB' (8-bit Bayer RGRG/GBGB)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [15]: 'pBAA' (10-bit Bayer BGBG/GRGR Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [16]: 'BG10' (10-bit Bayer BGBG/GRGR)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [17]: 'pGAA' (10-bit Bayer GBGB/RGRG Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [18]: 'GB10' (10-bit Bayer GBGB/RGRG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [19]: 'pgAA' (10-bit Bayer GRGR/BGBG Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [20]: 'BA10' (10-bit Bayer GRGR/BGBG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [21]: 'pRAA' (10-bit Bayer RGRG/GBGB Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [22]: 'RG10' (10-bit Bayer RGRG/GBGB)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [23]: 'pBCC' (12-bit Bayer BGBG/GRGR Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [24]: 'BG12' (12-bit Bayer BGBG/GRGR)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [25]: 'pGCC' (12-bit Bayer GBGB/RGRG Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [26]: 'GB12' (12-bit Bayer GBGB/RGRG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [27]: 'pgCC' (12-bit Bayer GRGR/BGBG Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [28]: 'BA12' (12-bit Bayer GRGR/BGBG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [29]: 'pRCC' (12-bit Bayer RGRG/GBGB Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [30]: 'RG12' (12-bit Bayer RGRG/GBGB)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [31]: 'pBEE' (14-bit Bayer BGBG/GRGR Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [32]: 'BG14' (14-bit Bayer BGBG/GRGR)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [33]: 'pGEE' (14-bit Bayer GBGB/RGRG Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [34]: 'GB14' (14-bit Bayer GBGB/RGRG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [35]: 'pgEE' (14-bit Bayer GRGR/BGBG Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [36]: 'GR14' (14-bit Bayer GRGR/BGBG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [37]: 'pREE' (14-bit Bayer RGRG/GBGB Packed)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [38]: 'RG14' (14-bit Bayer RGRG/GBGB)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [39]: 'BYR2' (16-bit Bayer BGBG/GRGR)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [40]: 'GB16' (16-bit Bayer GBGB/RGRG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [41]: 'GR16' (16-bit Bayer GRGR/BGBG)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [42]: 'RG16' (16-bit Bayer RGRG/GBGB)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [43]: 'GREY' (8-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [44]: 'Y10P' (10-bit Greyscale (MIPI Packed))
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [45]: 'Y10 ' (10-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [46]: 'Y12P' (12-bit Greyscale (MIPI Packed))
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [47]: 'Y12 ' (12-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [48]: 'Y14P' (14-bit Greyscale (MIPI Packed))
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [49]: 'Y14 ' (14-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1
        [50]: 'Y16 ' (16-bit Greyscale)
                Size: Stepwise 16x16 - 16376x16376 with step 1/1


Opening /dev/video0 with OpenCV...

OpenCV selected resolution: 640x480
OpenCV selected pixel format: BGR3
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 0: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 1: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 2: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 3: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 4: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 5: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 6: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 7: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 8: brightness=0.00
Frame shape: (480, 640, 3) dtype: uint8
First 32 bytes: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Frame 9: brightness=0.00

Average brightness: 0.00
Saved test.jpg

I added some diagnostics, and it seems to be imx219 V4L2 but I only grab black, and I don’t understand why.

I’d like help understand what I’m doing wrong here.

The RPI ecosystem decided to shun V4L. you won’t be able to get that camera working with V4L. They are betting fully on libcamera.

This is independent of OpenCV.

OpenCV in fact CANNOT help you accelerate any compression. It is not made for that. It’s made for computer vision.

You’d be better served asking questions about this project on a Raspberry Pi forum. There you will find people who know how to sling video on a raspberry pi.

1 Like

Thanks for answering, I’ll look for other solution

I was into ubuntu for tier 1 ROS2 support

But support for lots of Pi stuff is lacking

I guess I should try Raspberry Pi Os that has good support for libcamera and picamera 2 and use a docker for ROS2.