frigate/docker/qcs6490/Dockerfile
notori0us 52ba582e54 Add Qualcomm Hexagon NPU detector (qcs6490)
Adds a community-supported hardware detector for the Qualcomm Hexagon NPU
on QCS6490 SoCs (e.g. Radxa Dragon Q6A) via QAIRT 2.37.1 / qai_appbuilder.

Mirrors the existing community-board pattern (Rockchip / Synaptics):

- frigate/detectors/plugins/qnn.py: detector plugin using yolo-generic model
  type, lazy SDK import, runs pre-compiled QNN context binaries from
  Qualcomm AI Hub.
- docker/qcs6490/: Dockerfile (two-stage; rebuilds qai_appbuilder wheel
  inside Frigate's image to match libstdc++ ABI), bake target (qcs6490.hcl),
  make targets (qcs6490.mk), and a host-side user_installation.sh that
  installs fastrpc, the QCS6490 firmware (cDSP image + skel libs), and
  configures cdsprpcd.
- .github/workflows/ci.yml: qcs6490_build job mirroring synaptics_build.
- CODEOWNERS: /docker/qcs6490/ + qnn.py.
- docs: new "Qualcomm Hexagon NPU" sections under Community Supported
  Detectors in object_detectors.md, plus matching entries in
  installation.md and hardware.md.

Performance on Radxa Dragon Q6A (Hexagon v68, ~12 TOPS), YOLOv8n 640x640:
~10ms per inference under light load, ~24ms with 5 RTSP cameras live.

Closes #18602.
2026-04-19 17:03:37 -07:00

81 lines
3.4 KiB
Docker

# syntax=docker/dockerfile:1.6
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND=noninteractive
# Globally set pip break-system-packages option to avoid having to specify it every time
ARG PIP_BREAK_SYSTEM_PACKAGES=1
# QAIRT 2.37.1 runtime tarball + qai_appbuilder source pinned to a known-good
# commit that builds against this SDK version. Override at build time via
# --build-arg if a downstream maintainer hosts these elsewhere.
ARG QAIRT_RUNTIME_URL=https://github.com/notori0us/qairt-runtime/releases/download/v2.37.1.250807/qairt-runtime-2.37.1.250807-aarch64.tar.gz
ARG QAI_APPBUILDER_REF=942bc0d
# ---------- stage: builder ----------
# Build the qai_appbuilder Python wheel inside the Frigate image so its C++
# ABI (libstdc++/glibc) matches Frigate's runtime stage.
FROM deps AS qcs6490-wheels
ARG DEBIAN_FRONTEND
ARG PIP_BREAK_SYSTEM_PACKAGES
ARG QAIRT_RUNTIME_URL
ARG QAI_APPBUILDER_REF
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential cmake git ca-certificates curl \
python3-dev libyaml-0-2 \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir \
wheel==0.45.1 setuptools==80.9.0 pybind11==2.13.6 build==1.4.0
# Fetch QAIRT runtime (libQnnHtp*, libQnnSystem, hexagon-v68 skel, fastrpc shell).
RUN mkdir -p /opt/qairt \
&& curl -fsSL "${QAIRT_RUNTIME_URL}" | tar -C /opt/qairt -xzf -
# Fetch qai_appbuilder source at a pinned commit. Patch out the Genie target
# (its headers don't match QAIRT 2.37.1) and ensure dist/ exists for the build.
RUN git clone --filter=blob:none https://github.com/quic/ai-engine-direct-helper.git /tmp/aedh \
&& cd /tmp/aedh \
&& git checkout "${QAI_APPBUILDER_REF}" \
&& sed -i '/add_subdirectory(genie)/d' pybind/CMakeLists.txt \
&& sed -i 's|zip_package|os.makedirs("dist", exist_ok=True)\n zip_package|' setup.py
ENV QNN_SDK_ROOT=/opt/qairt \
QAI_TOOLCHAINS=aarch64-oe-linux-gcc11.2 \
QAI_HEXAGONARCH=68
RUN cd /tmp/aedh && python3 -m build -w
# ---------- stage: runtime ----------
FROM deps AS qcs6490-frigate
ARG DEBIAN_FRONTEND
ARG PIP_BREAK_SYSTEM_PACKAGES
# Runtime libs: libcdsprpc.so dlopen path + QNN SDK libs need libyaml-0.so.
RUN apt-get update \
&& apt-get install -y --no-install-recommends libyaml-0-2 \
&& rm -rf /var/lib/apt/lists/*
# QAIRT runtime layout. ADSP_LIBRARY_PATH below points cDSP firmware here for
# the QNN HTP backend skel (libQnnHtpV68Skel.so) and the fastrpc shell.
COPY --from=qcs6490-wheels /opt/qairt/lib /opt/qairt/lib/
COPY --from=qcs6490-wheels /opt/qairt/hexagon-v68 /opt/qairt/hexagon-v68/
# Make libcdsprpc.so visible to the dynamic linker without polluting LD_LIBRARY_PATH.
RUN ln -sf /opt/qairt/lib/libcdsprpc.so /usr/lib/libcdsprpc.so && ldconfig
# Install the qai_appbuilder wheel built in the previous stage.
RUN --mount=type=bind,from=qcs6490-wheels,source=/tmp/aedh/dist,target=/wheels \
pip3 install --no-cache-dir /wheels/qai_appbuilder-*.whl
WORKDIR /opt/frigate/
COPY --from=rootfs / /
# fastrpc separator gotcha: ADSP_LIBRARY_PATH is split by ';' (semicolon),
# not the usual ':'. The cDSP firmware also requires its skel + libc++ files
# at host paths /usr/lib/dsp/cdsp and /usr/lib/rfsa/adsp; bind-mount these
# from the host (see docs/docs/frigate/installation.md#qualcomm-platform).
ENV ADSP_LIBRARY_PATH="/opt/qairt/hexagon-v68;/usr/lib/dsp/cdsp;/usr/lib/rfsa/adsp" \
LD_LIBRARY_PATH="/opt/qairt/lib"