Skip to content

Commit a96a951

Browse files
authoredJul 26, 2023
Nvidia Jetson ffmpeg + TensorRT support (blakeblackshear#6458)
* Non-Jetson changes Required for later commits: - Allow base image to be overridden (and don't assume its WORKDIR) - Ensure python3.9 - Map hwaccel decode presets as strings instead of lists Not required: - Fix existing documentation - Simplify hwaccel scale logic * Prepare for multi-arch tensorrt build * Add tensorrt images for Jetson boards * Add Jetson ffmpeg hwaccel * Update docs * Add CODEOWNERS * CI * Change default model from yolov7-tiny-416 to yolov7-320 In my experience the tiny models perform markedly worse without being much faster * fixup! Update docs
1 parent 6801981 commit a96a951

28 files changed

+567
-139
lines changed
 

‎.github/workflows/ci.yml

+29-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
set: |
8080
rpi.tags=ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}-rpi
8181
*.cache-from=type=gha
82-
- name: Build and push TensorRT
82+
- name: Build and push TensorRT (x86 GPU)
8383
uses: docker/bake-action@v3
8484
with:
8585
push: true
@@ -88,6 +88,34 @@ jobs:
8888
set: |
8989
tensorrt.tags=ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}-tensorrt
9090
*.cache-from=type=gha
91+
- name: Build and push TensorRT (Jetson, Jetpack 4)
92+
env:
93+
ARCH: arm64
94+
BASE_IMAGE: timongentzsch/l4t-ubuntu20-opencv:latest
95+
SLIM_BASE: timongentzsch/l4t-ubuntu20-opencv:latest
96+
TRT_BASE: timongentzsch/l4t-ubuntu20-opencv:latest
97+
uses: docker/bake-action@v3
98+
with:
99+
push: true
100+
targets: tensorrt
101+
files: docker/tensorrt/trt.hcl
102+
set: |
103+
tensorrt.tags=ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}-tensorrt-jp4
104+
*.cache-from=type=gha
105+
- name: Build and push TensorRT (Jetson, Jetpack 5)
106+
env:
107+
ARCH: arm64
108+
BASE_IMAGE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
109+
SLIM_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
110+
TRT_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
111+
uses: docker/bake-action@v3
112+
with:
113+
push: true
114+
targets: tensorrt
115+
files: docker/tensorrt/trt.hcl
116+
set: |
117+
tensorrt.tags=ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}-tensorrt-jp5
118+
*.cache-from=type=gha
91119
- name: Assemble and push default build
92120
uses: int128/docker-manifest-create-action@v1
93121
with:

‎CODEOWNERS

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Community-supported boards
2+
/docker/tensorrt/ @madsciencetist @NateMeyer

‎docker-compose.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ services:
2121
- driver: nvidia
2222
count: 1
2323
capabilities: [gpu]
24+
environment:
25+
YOLO_MODELS: yolov7-320
2426
devices:
2527
- /dev/bus/usb:/dev/bus/usb
2628
# - /dev/dri:/dev/dri # for intel hwaccel, needs to be updated for your hardware
@@ -30,8 +32,6 @@ services:
3032
- /etc/localtime:/etc/localtime:ro
3133
- ./config:/config
3234
- ./debug:/media/frigate
33-
# Create the trt-models folder using the documented method of generating TRT models
34-
# - ./debug/trt-models:/trt-models
3535
- /dev/bus/usb:/dev/bus/usb
3636
mqtt:
3737
container_name: mqtt

‎docker/main/Dockerfile

+13-6
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
44
ARG DEBIAN_FRONTEND=noninteractive
55

6-
FROM debian:11 AS base
6+
ARG BASE_IMAGE=debian:11
7+
ARG SLIM_BASE=debian:11-slim
8+
9+
FROM ${BASE_IMAGE} AS base
710

811
FROM --platform=linux/amd64 debian:11 AS base_amd64
912

10-
FROM debian:11-slim AS slim-base
13+
FROM ${SLIM_BASE} AS slim-base
1114

1215
FROM slim-base AS wget
1316
ARG DEBIAN_FRONTEND
@@ -123,8 +126,8 @@ RUN apt-get -qq update \
123126
&& echo "deb http://deb.debian.org/debian bullseye main contrib non-free" | tee /etc/apt/sources.list.d/raspi.list \
124127
&& apt-get -qq update \
125128
&& apt-get -qq install -y \
126-
python3 \
127-
python3-dev \
129+
python3.9 \
130+
python3.9-dev \
128131
wget \
129132
# opencv dependencies
130133
build-essential cmake git pkg-config libgtk-3-dev \
@@ -137,14 +140,17 @@ RUN apt-get -qq update \
137140
gcc gfortran libopenblas-dev liblapack-dev && \
138141
rm -rf /var/lib/apt/lists/*
139142

143+
# Ensure python3 defaults to python3.9
144+
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
145+
140146
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
141147
&& python3 get-pip.py "pip"
142148

143149
COPY docker/main/requirements.txt /requirements.txt
144-
RUN pip3 install -r requirements.txt
150+
RUN pip3 install -r /requirements.txt
145151

146152
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
147-
RUN pip3 wheel --wheel-dir=/wheels -r requirements-wheels.txt
153+
RUN pip3 wheel --wheel-dir=/wheels -r /requirements-wheels.txt
148154

149155

150156
# Collect deps in a single layer
@@ -176,6 +182,7 @@ RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_de
176182
/deps/install_deps.sh
177183

178184
RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
185+
python3 -m pip install --upgrade pip && \
179186
pip3 install -U /deps/wheels/*.whl
180187

181188
COPY --from=deps-rootfs / /

‎docker/main/install_deps.sh

+8-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ apt-get -qq install --no-install-recommends -y \
1010
wget \
1111
procps vainfo \
1212
unzip locales tzdata libxml2 xz-utils \
13+
python3.9 \
1314
python3-pip \
1415
curl \
1516
jq \
1617
nethogs
1718

19+
# ensure python3 defaults to python3.9
20+
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
21+
1822
mkdir -p -m 600 /root/.gnupg
1923

2024
# add coral repo
@@ -23,8 +27,10 @@ curl -fsSLo - https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
2327
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | tee /etc/apt/sources.list.d/coral-edgetpu.list
2428
echo "libedgetpu1-max libedgetpu/accepted-eula select true" | debconf-set-selections
2529

26-
# enable non-free repo
27-
sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list
30+
# enable non-free repo in Debian
31+
if grep -q "Debian" /etc/issue; then
32+
sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list
33+
fi
2834

2935
# coral drivers
3036
apt-get -qq update

‎docker/tensorrt/Dockerfile ‎docker/tensorrt/Dockerfile.amd64

+2-19
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,11 @@ ARG DEBIAN_FRONTEND
99
ARG TARGETARCH
1010

1111
# Add TensorRT wheels to another folder
12-
COPY docker/tensorrt/requirements.txt /requirements-tensorrt.txt
12+
COPY docker/tensorrt/requirements-amd64.txt /requirements-tensorrt.txt
1313
RUN mkdir -p /trt-wheels && pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt
1414

15-
# Build TensorRT-specific library
16-
FROM nvcr.io/nvidia/tensorrt:23.03-py3 AS trt-deps
17-
18-
RUN --mount=type=bind,source=docker/tensorrt/detector/tensorrt_libyolo.sh,target=/tensorrt_libyolo.sh \
19-
/tensorrt_libyolo.sh
20-
21-
# Frigate w/ TensorRT Support as separate image
22-
FROM deps AS frigate-tensorrt
23-
24-
#Disable S6 Global timeout
25-
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
26-
15+
FROM tensorrt-base AS frigate-tensorrt
2716
ENV TRT_VER=8.5.3
28-
ENV YOLO_MODELS="yolov7-tiny-416"
29-
30-
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
31-
COPY --from=trt-deps /usr/local/src/tensorrt_demos /usr/local/src/tensorrt_demos
32-
COPY docker/tensorrt/detector/rootfs/ /
33-
3417
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
3518
pip3 install -U /deps/trt-wheels/*.whl && \
3619
ldconfig

‎docker/tensorrt/Dockerfile.arm64

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# syntax=docker/dockerfile:1.4
2+
3+
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
4+
ARG DEBIAN_FRONTEND=noninteractive
5+
6+
ARG BASE_IMAGE
7+
FROM ${BASE_IMAGE} AS build-wheels
8+
ARG DEBIAN_FRONTEND
9+
10+
# Use a separate container to build wheels to prevent build dependencies in final image
11+
RUN apt-get -qq update \
12+
&& apt-get -qq install -y --no-install-recommends \
13+
python3.9 python3.9-dev \
14+
wget build-essential cmake git \
15+
&& rm -rf /var/lib/apt/lists/*
16+
17+
# Ensure python3 defaults to python3.9
18+
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
19+
20+
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
21+
&& python3 get-pip.py "pip"
22+
23+
24+
FROM build-wheels AS trt-wheels
25+
ARG DEBIAN_FRONTEND
26+
ARG TARGETARCH
27+
28+
# python-tensorrt build deps are 3.4 GB!
29+
RUN apt-get update \
30+
&& apt-get install -y ccache cuda-cudart-dev-* cuda-nvcc-* libnvonnxparsers-dev libnvparsers-dev libnvinfer-plugin-dev \
31+
&& ([ -e /usr/local/cuda ] || ln -s /usr/local/cuda-* /usr/local/cuda) \
32+
&& rm -rf /var/lib/apt/lists/*;
33+
34+
# Determine version of tensorrt already installed in base image, e.g. "Version: 8.4.1-1+cuda11.4"
35+
RUN NVINFER_VER=$(dpkg -s libnvinfer8 | grep -Po "Version: \K.*") \
36+
&& echo $NVINFER_VER | grep -Po "^\d+\.\d+\.\d+" > /etc/TENSORRT_VER
37+
38+
RUN --mount=type=bind,source=docker/tensorrt/detector/build_python_tensorrt.sh,target=/deps/build_python_tensorrt.sh \
39+
--mount=type=cache,target=/root/.ccache \
40+
export PATH="/usr/lib/ccache:$PATH" CCACHE_DIR=/root/.ccache CCACHE_MAXSIZE=2G \
41+
&& TENSORRT_VER=$(cat /etc/TENSORRT_VER) /deps/build_python_tensorrt.sh
42+
43+
COPY docker/tensorrt/requirements-arm64.txt /requirements-tensorrt.txt
44+
RUN pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt
45+
46+
FROM build-wheels AS trt-model-wheels
47+
ARG DEBIAN_FRONTEND
48+
49+
RUN apt-get update \
50+
&& apt-get install -y protobuf-compiler libprotobuf-dev \
51+
&& rm -rf /var/lib/apt/lists/*
52+
RUN --mount=type=bind,source=docker/tensorrt/requirements-models-arm64.txt,target=/requirements-tensorrt-models.txt \
53+
pip3 wheel --wheel-dir=/trt-model-wheels -r /requirements-tensorrt-models.txt
54+
55+
FROM wget AS jetson-ffmpeg
56+
ARG DEBIAN_FRONTEND
57+
ENV CCACHE_DIR /root/.ccache
58+
ENV CCACHE_MAXSIZE 2G
59+
RUN --mount=type=bind,source=docker/tensorrt/build_jetson_ffmpeg.sh,target=/deps/build_jetson_ffmpeg.sh \
60+
--mount=type=cache,target=/root/.ccache \
61+
/deps/build_jetson_ffmpeg.sh
62+
63+
# Frigate w/ TensorRT for NVIDIA Jetson platforms
64+
FROM tensorrt-base AS frigate-tensorrt
65+
RUN apt-get update \
66+
&& apt-get install -y python-is-python3 libprotobuf17 \
67+
&& rm -rf /var/lib/apt/lists/*
68+
69+
RUN rm -rf /usr/lib/btbn-ffmpeg/
70+
COPY --from=jetson-ffmpeg /rootfs /
71+
72+
COPY --from=trt-wheels /etc/TENSORRT_VER /etc/TENSORRT_VER
73+
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
74+
--mount=type=bind,from=trt-model-wheels,source=/trt-model-wheels,target=/deps/trt-model-wheels \
75+
pip3 install -U /deps/trt-wheels/*.whl /deps/trt-model-wheels/*.whl \
76+
&& ldconfig
77+
78+
WORKDIR /opt/frigate/
79+
COPY --from=rootfs / /

‎docker/tensorrt/Dockerfile.base

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# syntax=docker/dockerfile:1.4
2+
3+
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
4+
ARG DEBIAN_FRONTEND=noninteractive
5+
6+
ARG TRT_BASE=nvcr.io/nvidia/tensorrt:23.03-py3
7+
8+
# Build TensorRT-specific library
9+
FROM ${TRT_BASE} AS trt-deps
10+
11+
RUN apt-get update \
12+
&& apt-get install -y git build-essential cuda-nvcc-* cuda-nvtx-* libnvinfer-dev libnvinfer-plugin-dev libnvparsers-dev libnvonnxparsers-dev \
13+
&& rm -rf /var/lib/apt/lists/*
14+
RUN --mount=type=bind,source=docker/tensorrt/detector/tensorrt_libyolo.sh,target=/tensorrt_libyolo.sh \
15+
/tensorrt_libyolo.sh
16+
17+
# Frigate w/ TensorRT Support as separate image
18+
FROM deps AS tensorrt-base
19+
20+
#Disable S6 Global timeout
21+
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
22+
23+
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
24+
COPY --from=trt-deps /usr/local/src/tensorrt_demos /usr/local/src/tensorrt_demos
25+
COPY docker/tensorrt/detector/rootfs/ /
26+
ENV YOLO_MODELS="yolov7-320"
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/bin/bash
2+
3+
# For jetson platforms, build ffmpeg with custom patches. NVIDIA supplies a deb
4+
# with accelerated decoding, but it doesn't have accelerated scaling or encoding
5+
6+
set -euxo pipefail
7+
8+
INSTALL_PREFIX=/rootfs/usr/local
9+
10+
apt-get -qq update
11+
apt-get -qq install -y --no-install-recommends build-essential ccache clang cmake pkg-config
12+
apt-get -qq install -y --no-install-recommends libx264-dev libx265-dev
13+
14+
pushd /tmp
15+
16+
# Install libnvmpi to enable nvmpi decoders (h264_nvmpi, hevc_nvmpi)
17+
if [ -e /usr/local/cuda-10.2 ]; then
18+
# assume Jetpack 4.X
19+
wget -q https://developer.nvidia.com/embedded/L4T/r32_Release_v5.0/T186/Jetson_Multimedia_API_R32.5.0_aarch64.tbz2 -O jetson_multimedia_api.tbz2
20+
else
21+
# assume Jetpack 5.X
22+
wget -q https://developer.nvidia.com/downloads/embedded/l4t/r35_release_v3.1/release/jetson_multimedia_api_r35.3.1_aarch64.tbz2 -O jetson_multimedia_api.tbz2
23+
fi
24+
tar xaf jetson_multimedia_api.tbz2 -C / && rm jetson_multimedia_api.tbz2
25+
26+
wget -q https://github.com/madsciencetist/jetson-ffmpeg/archive/refs/heads/master.zip
27+
unzip master.zip && rm master.zip && cd jetson-ffmpeg-master
28+
LD_LIBRARY_PATH=$(pwd)/stubs:$LD_LIBRARY_PATH # tegra multimedia libs aren't available in image, so use stubs for ffmpeg build
29+
mkdir build
30+
cd build
31+
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX
32+
make -j$(nproc)
33+
make install
34+
cd ../../
35+
36+
# Install nv-codec-headers to enable ffnvcodec filters (scale_cuda)
37+
wget -q https://github.com/FFmpeg/nv-codec-headers/archive/refs/heads/master.zip
38+
unzip master.zip && rm master.zip && cd nv-codec-headers-master
39+
make PREFIX=$INSTALL_PREFIX install
40+
cd ../ && rm -rf nv-codec-headers-master
41+
42+
# Build ffmpeg with nvmpi patch
43+
wget -q https://ffmpeg.org/releases/ffmpeg-6.0.tar.xz
44+
tar xaf ffmpeg-*.tar.xz && rm ffmpeg-*.tar.xz && cd ffmpeg-*
45+
patch -p1 < ../jetson-ffmpeg-master/ffmpeg_patches/ffmpeg6.0_nvmpi.patch
46+
export PKG_CONFIG_PATH=$INSTALL_PREFIX/lib/pkgconfig
47+
# enable Jetson codecs but disable dGPU codecs
48+
./configure --cc='ccache gcc' --cxx='ccache g++' \
49+
--enable-shared --disable-static --prefix=$INSTALL_PREFIX \
50+
--enable-gpl --enable-libx264 --enable-libx265 \
51+
--enable-nvmpi --enable-ffnvcodec --enable-cuda-llvm \
52+
--disable-cuvid --disable-nvenc --disable-nvdec \
53+
|| { cat ffbuild/config.log && false; }
54+
make -j$(nproc)
55+
make install
56+
cd ../
57+
58+
rm -rf /var/lib/apt/lists/*
59+
popd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
set -euxo pipefail
4+
5+
mkdir -p /trt-wheels
6+
7+
if [[ "${TARGETARCH}" == "arm64" ]]; then
8+
9+
# NVIDIA supplies python-tensorrt for python3.8, but frigate uses python3.9,
10+
# so we must build python-tensorrt ourselves.
11+
12+
# Get python-tensorrt source
13+
mkdir /workspace
14+
cd /workspace
15+
git clone -b ${TENSORRT_VER} https://github.com/NVIDIA/TensorRT.git --depth=1
16+
17+
# Collect dependencies
18+
EXT_PATH=/workspace/external && mkdir -p $EXT_PATH
19+
pip3 install pybind11 && ln -s /usr/local/lib/python3.9/dist-packages/pybind11 $EXT_PATH/pybind11
20+
ln -s /usr/include/python3.9 $EXT_PATH/python3.9
21+
ln -s /usr/include/aarch64-linux-gnu/NvOnnxParser.h /workspace/TensorRT/parsers/onnx/
22+
23+
# Build wheel
24+
cd /workspace/TensorRT/python
25+
EXT_PATH=$EXT_PATH PYTHON_MAJOR_VERSION=3 PYTHON_MINOR_VERSION=9 TARGET_ARCHITECTURE=aarch64 /bin/bash ./build.sh
26+
mv build/dist/*.whl /trt-wheels/
27+
28+
fi

0 commit comments

Comments
 (0)
Please sign in to comment.