Skip to content

Releases: ruisv/rcdl

RCDL 0.1.1

Choose a tag to compare

@ruisv ruisv released this 20 Sep 18:41

RCDL 0.1.1 is a patch release for one defect. If you letterbox, resize or crop-resize into an NV12 — or any YUV — destination, upgrade; nothing else changed in the library.

Install

conda create -n rcdl -c https://mirrors.ruis.ai/conda -c conda-forge rcdl        # Python 3.9–3.14
conda install -c https://mirrors.ruis.ai/conda -c conda-forge librcdl             # C++ only: librcdl.so + headers + find_package(rcdl)

The defect

letterbox, resize and cropResize on the RGA backend never reached the hardware when the destination was YUV. librga 1.10.6 validates the source buffer's colour-space field against a whitelist that the IM_RGB_TO_YUV_* values are not on, and RCDL wrote the legacy mode on both buffers — so the job was refused with src unsupported color space mode before a core was ever picked, on any heap and with any core mask. PreprocBackend::Rga threw; the default Auto backend fell back to the CPU without saying so, which is the version most people would have hit: correct pixels, at CPU speed.

This affects the published 0.1.0 packages, and not only on a board whose image happens to carry librga 1.10.6 — the conda packages bring that librga with them, so a 0.1.0 install is affected whatever the board image ships. cvtColor / cvt_color was never affected: imcvtcolor() takes the colour-space mode as a call argument instead of off the buffers, which is also why the existing RGB → NV12 coverage, all of it on the CPU backend, went straight past this.

The mode now goes on the destination buffer only. Measured in both directions: destination-only is pixel-identical to writing on both for YUV → RGB, so it is not a direction-dependent rule.

How it turned up

rga_probe had been printing <-- unexpected on case 8 for a while, and the cause was not the board — the probe asserted that RGB → YUV BT.709 succeeds on RGA3, while the colour-matrix table in docs/RGA.md §5 recorded that cell as CPU-only. The probe and the documentation simply disagreed. Re-measuring the whole table to settle it is what turned up the defect behind it.

That re-measurement is also in this release. The table now carries per-cell error figures instead of a blanket ±1 LSB, taken against a float reference over the full 16×16×16 component cube on an image constant within every 2×2 block, so 4:2:0 subsampling contributes no error of its own. Three of its conclusions changed:

  • BT.709 full range is missing from librga's legacy enum in both directions — not blocked by a core or by memory. The newer full-CSC form does not rescue it either: YUV → RGB BT.709 full is refused by the hardware itself.
  • RGB → YUV BT.709 limited is not "no core accepts the job". RGA2 with both buffers in dma32 performs it; it stays on the CPU because it lands 3 LSB from the reference, where every cell in use stays within ~1.
  • RGA2 and RGA3 disagree on YUV → RGB BT.709 limited (1.38 against 0.99), so BT.709 belongs on RGA3 wherever the buffers allow it.

docs/RGA.md §5 also now records which buffer may carry the colour-space mode, and that imcheck and improcess do not agree about it — a probe that stops at imcheck will report a conversion as refused that the hardware performs.


Full changelog: https://github.com/ruisv/rcdl/blob/v0.1.1/CHANGELOG.md

RCDL 0.1.0

Choose a tag to compare

@ruisv ruisv released this 18 Sep 06:15

RCDL 0.1.0 is the first release: a C++17 inference and media library for Rockchip RK3588 / RK3588S, with nanobind Python bindings, and — as of this release — conda packages, so installing it no longer means building it.

Install

conda create -n rcdl -c https://mirrors.ruis.ai/conda -c conda-forge rcdl        # Python 3.9–3.14
conda install -c https://mirrors.ruis.ai/conda -c conda-forge librcdl             # C++ only: librcdl.so + headers + find_package(rcdl)

linux-aarch64. The Rockchip userspace libraries come as packages too — librknnrt 2.3.2, librga 1.10.6, rockchip-mpp 1.1.0 — so an environment takes nothing from the board image but the kernel drivers (RKNPU, RGA, MPP). The full board test suite (584 tests) passes against the installed packages exactly as it does against a source build.

What is in it

  • One buffer, every unit. A dma-buf fd is what the NPU (rknn_create_mem_from_fd), RGA and the VPU all consume, so a decoded NV12 frame is letterboxed by RGA straight into the NPU's input tensor and the annotated frame is encoded without a copy. AsyncVideoDetectionPipeline runs 1080p H.264 → YOLOv8n at 72–97 fps against 23–28 fps for the synchronous pipeline, with identical detections frame by frame.
  • Engine: zero-copy I/O bound once, int8 / fp16 / fp32 dequantisation, NPU core pinning, duplicated contexts for three-core throughput.
  • RGA preprocessing with a CPU fallback that stays the numerical reference, BT.601 / BT.709, studio and full range — and, new in the last stretch before this release, the two facts about RK3588's RGA that decide whether a pipeline is reproducible: the RGA2 core only reaches memory below 4 GB (DmaBuf::Heap::SystemDma32, per-buffer below4g), and the driver load-balances between RGA3 and RGA2, which resample differently, so every op pins its core. docs/RGA.md §3 has the measurements, and rga_probe reruns them on your board.
  • Media: H.264 / H.265 / VP9 / AV1 / JPEG through MPP, external buffer groups, a batched box overlay that is byte-identical on its CPU and RGA2 paths.
  • Tasks: detection (YOLOv8 / 11 / 26, open-vocabulary), classification, pose and whole-body pose, instance and semantic segmentation, promptable segmentation, oriented boxes, depth, embeddings (SigLIP, ArcFace, ReID), OCR (PP-OCRv4 / v5 / v6), faces, sparse features, super-resolution, optical flow, panoptic driving — each a pure decoder with a numpy test and a board test.
  • Tracking: ByteTrack with BoT-SORT appearance association.

Found on the way out the door

Building the conda package was the first build against a sysroot without <linux/dma-heap.h>, and the fallback definitions in core/dma_buf.cc turned out never to have compiled. Fixed in this release; it is the kind of thing a release exists to find.


Full changelog: https://github.com/ruisv/rcdl/blob/v0.1.0/CHANGELOG.md