ISP Usage on Dragon Q6A

Hi, has anyone successfully porting support of QIMSDK or some short of that on RadxaOS for usage of ISP or qimmfsrc?

It is necessary for porting those into RadxaOS inorder to efficiently using all Vision-capabilities on QCS6490 SoC.

Hi Thanh_nguy_n_lam
I’m working on exactly this on a Radxa Dragon Q6A (QCS6490 / SOC ID=498), running RadxaOS Ubuntu 24.04 with kernel 6.18.2-3-qcom.

Quick status on where I am:

I managed to get dual camera streaming working simultaneously — IMX415 (8MP, CAM1 port) and IMX477 Raspberry Pi HQ cam (12MP, CAM2 port) — both streaming MJPEG at 30fps stable over HTTP using libcamera v0.7.0 with EGL/GPU debayer on the Adreno 635. Colors are correct, pipeline is solid.

For FastRPC I had to apply a device tree overlay (fastrpc-adsp-mem.dtbo) and fix adsprpcd with a custom debugconfig to keep ADSP and CDSP stable. ADSP and CDSP are both running fine now.

Currently I’m debugging H264 hardware encoding via Venus (qcom-venus, /dev/video18). The encoder initializes correctly, controls set fine (bitrate, gop, profile), buffers allocated — but I’m still chasing an issue where encoded frames don’t come out yet. Getting there.

Drivers in use:

  • qcom-venus (V4L2 M2M H264 encoder)
  • qcom-camss (MIPI CSI pipeline: csiphy → csid → VFE)
  • imx477 / imx415 (sensor drivers)
  • libcamera simple pipeline with EGL GPU debayer
  • FastRPC + adsprpcd for DSP comms

I haven’t touched QIMSDK / qimmfsrc — going the libcamera + V4L2 route for now, which works but you’re right it doesn’t natively exploit the Titan ISP the way the Qualcomm SDK would.

I’ll push everything to a public GitHub repo soon (libcamera-http-streamer for Radxa Q6A). Will post the link here when it’s up, might save others a lot of time.

Also wanted to share some numbers on the MJPEG side since that part is fully working.

With my libcamera-http-streamer on the Q6A:

  • 640x480 @ 30fps stable, latency ~15-60ms end-to-end (camera to browser)
  • 1280x720 @ 30fps, latency 90 ms
  • Both cameras simultaneously, no frame drops, CPU stays reasonable thanks to EGL/GPU debayer on Adreno 635
  • Stream served over HTTP multipart (standard MJPEG), works directly in browser, VLC, OpenCV, anything

The pipeline is: libcamera (Viewfinder role) → XRGB8888 via GPU debayer → NV12 conversion → libjpeg → HTTP. No GStreamer dependency, self-contained.

If anyone wants to test it on a Q6A, I can send the sources + the device tree overlays + the adsprpcd fix. Just DM me. I’ll clean it up and push a proper public repo soon but happy to share as-is in the meantime.

Note: this is built specifically around the qcom-camss + libcamera simple pipeline on RadxaOS, not a generic solution — but the FastRPC/DTBO fixes should transfer to any QCS6490 board.

Thank you for your suggestion! I actually managed to find my own approach. Instead of using Libcamera, I went with a manual setup using media-ctl + V4L2 native, which I integrated directly into a new backend for my computer vision programming DSL called VisionPipe. You can check it out here: github.com/tlamngu/vision-pipe.

My current pipeline is straightforward: V4L2 → VisionPipe directly, and it’s performing really well:

  • Camera: IMX219 × 2

  • Resolution: 1640×1232 @ 60 FPS

  • Debayering & color transformation handled on CPU (my GPU implementation only reached ~15 FPS, so CPU was the better choice for now)

Performance (of 2x IMX219 capture at 1640x1232)

[Throughput] -----------------------------------------------------------------------
[Throughput]  Pipeline                  calls   calls/s    avg ms    min ms    max ms
[Throughput]  -----------------------------------------------------------------------
[Throughput]  setup                         1       0.0     96.84     96.84     96.84
[Throughput]  fork:capture_left          4427      60.0     16.69      6.85     53.53
[Throughput]  fork:capture_right         4441      60.0     16.64      4.26     65.84
[Throughput]  display                    5815      82.9     10.53      0.02    283.36
[Throughput]  brightness_adjustment      2182      29.0      6.80      0.02    585.31
[Throughput]  fork:ipc:frame_l           4181      57.0      6.02      0.00     23.56
[Throughput]  fork:ipc:frame_r           4431      59.0      5.51      0.00     19.22
[Throughput]  main                      44993     632.5      1.62      1.05    212.08

[Latency] -----------------------------------------------------------------------
[Latency]  Pipeline                  calls    p50 ms    p95 ms    p99 ms    max ms
[Latency]  -----------------------------------------------------------------------
[Latency]  setup                         1     96.00     96.00     96.00     96.84
[Latency]  fork:capture_left          4427     24.00     24.00     24.00     53.53
[Latency]  fork:capture_right         4441     24.00     24.00     24.00     65.84
[Latency]  display                    5815     12.00     24.00     24.00    283.36
[Latency]  brightness_adjustment      2182      6.00     12.00     12.00    585.31
[Latency]  fork:ipc:frame_l           4181      6.00     12.00     24.00     23.56
[Latency]  fork:ipc:frame_r           4431      6.00     12.00     12.00     19.22
[Latency]  main                      44993      1.50      3.00      6.00    212.08

I noticed you mentioned interest in IP streaming — I think VisionPipe might actually fit your use case nicely! Here’s the VSP DSL code I use for the full capture-to-stream pipeline:

pipeline setup

   v4l2_setup("/dev/video3", 1640, 1232, "SRGGB8", 60, 4)
   v4l2_prop("/dev/video3", "vertical_flip", 1)
   v4l2_prop("/dev/video3", "exposure", 1703)      # Max exposure
   v4l2_prop("/dev/video3", "analogue_gain", 232)  # Max analogue gain
   v4l2_prop("/dev/video3", "digital_gain", 614)  # Boost digital gain


   ccm = mat_create([[1.35, -0.25, -0.10], [-0.10, 0.80, -0.10], [-0.05, -0.30, 1.35]])
   to_cvmat(ccm)
   global_cache("ccm_matrix")

   print("---- Props after set ----")
   v4l2_list_controls("/dev/video3")
end

pipeline brightness_adjustment
    # debug_start
    brightness_target = 115
    use(global "frame_r") 
    adaptive_auto_brightness("/dev/video3", exposure_prop="exposure", min_exposure=4, max_exposure=1703, analog_gain_prop="analogue_gain", min_analog_gain=0, max_analog_gain=232, digital_gain_prop="digital_gain", target=brightness_target, brightness_mode="median", kp=0.2, ki=0.05)
    # debug_end
end

pipeline main
    video_cap("/dev/video3", "v4l2_native")
    # debayer("BGGR", "bilinear", "bgr", 0)
    debayer("GRBG") # vertical flip => BGGR = GRBR
    cvt_color("bgr2gray")

    resize(640, 480) -> global "frame_r"
    # gpu_video_stabilize(0.5, 1)  
    # gpu_horizon_lock()
    # video_stabilize(0.7, 0.2)
    fps(true, 10, 30)
    ip_stream(5000, "0.0.0.0", 90)
    wait_key(1)
end

exec_interval brightness_adjustment 33

exec_seq setup
exec_loop main

This setup captures frames, processes them, and streams JPEG output to port 5000. Happy to answer any questions if you’d like to try it out!

Note: these camera output was Bayer which OpenCV can’t read directly so all video controls and frame input must be provided by Libcamera Backend or V4l2-native Backend. Enabled by -DLIBCAMERA_BACKEND=ON and -DV4L2_NATIVE_BACKEND=ON. While IP Streaming must enable -VISIONPIPE_IP_CAM=ON.

Hello, I am considering whether this development board can support debugging Qualcomm’s ISP (if not, then using this development board may be meaningless), but it seems that there are many restrictions in this area. I would like to ask if the post owner is currently working on related development? Or is there any way to debug Qualcomm’s ISP? Observing that the content of the post is related to the development of camera drivers and videos

Actually yes, absolutely. But you need to hand-on the UFS module, build the yocto-based image of Qualcomm Linux (*With RadxaQ6A meta layers), port some apt package of the ISP support on Ubuntu from the RubikPi3. In theory, it should work.

Or just try your best installing the QIMSDK!