doitandbedone / ispyagentdvr-docker

GNU General Public License v3.0
117 stars 45 forks source link

Nvidia GPU features not working #79

Open izevar opened 3 years ago

izevar commented 3 years ago

Hello Seem that all GPU related features are not working: GPU decoding GPU encoding Object detection

There is any extra step needed to enable it ?

doitandbedone commented 3 years ago

Thanks for sharing! Been a while since I last tried, the main problem was besides nvidia compatibility there were some extras for ispy to work. I'll give it a try!

On Mon, Mar 29, 2021 at 11:15 AM oriol73 @.***> wrote:

@doitandbedone https://github.com/doitandbedone there's a docker container with ffmpeg already compiled with nvidia libraries here:

example: docker run --runtime=nvidia jrottenberg/ffmpeg:4.1-nvidia -hwaccel cuvid -c:v h264_cuvid -i INPUT -vf scale_npp=-1:720 -c:v h264_nvenc -preset slow OUTPUT

You can leave this container up and running with: docker run --runtime=nvidia -it --entrypoint='bash' jrottenberg/ffmpeg:4.1-nvidia

and then ffmpeg binaries/libraries could be shared/cloned from ffmpeg container to agentdvr container....then adding the right PATH env, and start using them.

Would this help?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/doitandbedone/ispyagentdvr-docker/issues/79#issuecomment-809601685, or unsubscribe https://github.com/notifications/unsubscribe-auth/AORTFNFFSWMXMA5SQIPTHNTTGDGT7ANCNFSM4TF2GKTA .

oriol73 commented 3 years ago

@doitandbedone I've read on iSpy release notes that for Linux installation it's required an ffmeg distribution, required from specific PPAs: jonathonf/ffmpeg-4 or savoury1/ffmpeg4 .

Checking savoury1/ffmpeg4 PPA description here https://launchpad.net/~savoury1/+archive/ubuntu/ffmpeg4 , seems that this is already compiled with nvidia hardware support:

nVidia display hardware: FFmpeg at this PPA is built with nv-codec-headers allowing hardware-accelerated video encoding and decoding using recent enough nVidia GPUs. The version of nv-codec-headers used (9.1.23) requires at least version 435.21 or newer of the nVidia proprietary display drivers. For newer nVidia drivers than official Ubuntu repos see the Ubuntu "Graphics Drivers" team PPA here: https://launchpad.net/~graphics-drivers/+archive/ubuntu/ppa

Have you considered to configure your dockerfile with savoury1/ffmpeg4 PPA instead of jonathonf/ffmpeg-4 ? Furthermore, if this works well, you won't need a different tag for nvidia setup, having one single version of the container as this PPA seems verified by iSPY.

doitandbedone commented 3 years ago

@oriol73 I had actually already looked into this. There's a branch called feature/simple-ffmpeg-nvidia. Back then it still didn't work, but there's been multiple updates. You can check it out. At the moment I'm swamped but as soon as I get a chance I can revisit it.

theaccountforjake commented 3 years ago

I think I was able to get a container that uses hardware accelerated video decoding. I'll paste my Dockerfile below, but the highlights are:

  1. Built from a a .net docker image based on Debian 10 instead of Ubuntu 18.04, because this allows
  2. Installation of ffmpeg from the deb-multimedia repository

The deb-multimedia version of ffmpeg seems to fit the bill. It has various Nvidia hardware acceleration features enabled, and it's not built statically so it contains the required libraries.

Now when I run my custom Docker container, I see in the log:

Using hardware decoder: AV_HWDEVICE_TYPE_CUDA

And I also see an entry in nvidia-smi, showing that dotnet is using 67MiB on the GPU. However, CPU usage still seems to be higher than I would've thought, so I'm not sure everything is working correctly.

Anyway, the Dockerfile I used is:

# Use MS maintained .net docker image wuith aspnet and core runtimes.
FROM mcr.microsoft.com/dotnet/aspnet:3.1

#Define download location variables
ARG FILE_LOCATION="https://ispyfiles.azureedge.net/downloads/Agent_Linux64_3_2_7_0.zip"
ENV FILE_LOCATION_SET=${FILE_LOCATION:+true}
ENV DEFAULT_FILE_LOCATION="https://www.ispyconnect.com/api/Agent/DownloadLocation2?productID=24&is64=true&platform=Linux"
ARG DEBIAN_FRONTEND=noninteractive 
ARG TZ=America/Los_Angeles

# Download and install dependencies
RUN apt-get update \
    && apt-get install -y wget libtbb-dev libc6-dev unzip multiarch-support gss-ntlmssp software-properties-common \
    && wget http://security.ubuntu.com/ubuntu/pool/main/libj/libjpeg-turbo/libjpeg-turbo8_1.5.2-0ubuntu5.18.04.4_amd64.deb \
    && wget http://fr.archive.ubuntu.com/ubuntu/pool/main/libj/libjpeg8-empty/libjpeg8_8c-2ubuntu8_amd64.deb \
    && dpkg -i libjpeg-turbo8_1.5.2-0ubuntu5.18.04.4_amd64.deb \
    && dpkg -i libjpeg8_8c-2ubuntu8_amd64.deb \
    && rm libjpeg8_8c-2ubuntu8_amd64.deb \
    && rm libjpeg-turbo8_1.5.2-0ubuntu5.18.04.4_amd64.deb

# Install deb-multimedia ffmpeg
RUN apt-get update
RUN echo "deb http://www.deb-multimedia.org buster main non-free" >> /etc/apt/sources.list
RUN apt-get update -oAcquire::AllowInsecureRepositories=true -y --force-yes
RUN apt-get install deb-multimedia-keyring -y --force-yes
RUN apt-get update
RUN apt-get install ffmpeg -y --force-yes

# Download/Install iSpy Agent DVR: 
# Check if we were given a specific version
RUN if [ "${FILE_LOCATION_SET}" = "true" ]; then \
    echo "Downloading from specific location: ${FILE_LOCATION}" && \
    wget -c ${FILE_LOCATION} -O agent.zip; \
    else \
    #Get latest instead
    echo "Downloading latest" && \
    wget -c $(wget -qO- "https://www.ispyconnect.com/api/Agent/DownloadLocation2?productID=24&is64=true&platform=Linux" | tr -d '"') -O agent.zip; \
    fi && \
    unzip agent.zip -d /agent && \
    rm agent.zip

# Install libgdiplus, used for smart detection
RUN apt-get install -y libgdiplus

# Install Time Zone
RUN apt-get install -y tzdata

# Clean up
RUN apt-get -y --purge remove unzip wget \ 
    && apt autoremove -y \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Docker needs to run a TURN server to get webrtc traffic to and from it over forwarded ports from the host
# These are the default ports. If the ports below are modified here you'll also need to set the ports in XML/Config.xml
# for example <TurnServerPort>3478</TurnServerPort><TurnServerMinPort>50000</TurnServerMinPort><TurnServerMaxPort>50010</TurnServerMaxPort>
# The main server port is overridden by creating a text file called port.txt in the root directory containing the port number, eg: 8090
# To access the UI you must use the local IP address of the host, NOT localhost - for example http://192.168.1.12:8090/

# Define default environment variables
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Main UI port
EXPOSE 8090

# TURN server port
EXPOSE 3478/udp

# TURN server UDP port range
EXPOSE 50000-50010/udp

# Data volumes
VOLUME ["/agent/Media/XML", "/agent/Media/WebServerRoot/Media", "/agent/Commands"]

# Define service entrypoint
CMD ["dotnet", "/agent/Agent.dll"]
doitandbedone commented 3 years ago

@theaccountforjake Do appreciate all the work, however, I'm afraid I can't use a non-free and also experimental/unofficial repo. Will keep looking for alternatives however.

theaccountforjake commented 3 years ago

@doitandbedone That's a good point. Does usage of CUDA or other HW acceleration require the--enable-nonfree option in ffmpeg? I honestly don't know if it does, but I think suspect it does, and I think, in general, ffmpeg binaries built with the option aren't redistributable.

Nvidia's instructions for building (https://docs.nvidia.com/video-technologies/video-codec-sdk/ffmpeg-with-nvidia-gpu/) use the non-free option, unfortunately.

doitandbedone commented 3 years ago

Still a little bit of a grey area for me as well, since this is for ffmpeg. The repo didn't have much details to be honest. As for nvidia, last I found out was that it's open source (free) vs closed source (nvivida nonfree). These are available for everyone but not sure if there's any other licensing caveats in there, didn't find any. Once you get to the codecs there's some very tricky licensing schemes. This is why I went to use their CUDA images and that makes it work, but then ffmpeg became the issue.

autumnwalker commented 2 years ago

Check in on this - any update? I'm super interested in GPU support in the Docker, but unclear how I can assist.

scornflake commented 1 year ago

For those interested, here's a Dockerfile I put together for Ubuntu 22.04.
I've commented it where I made changes. It was based upon the Dockerfile of this repo (doitandbedone)

You need to have your docker setup for nvidia as per: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html

# Use Ubuntu LTS
#FROM ubuntu:22.04

# NOTE: Using a dev image containing all the required cuda stuff.
# IMPORTANT: The version (in this case 12.0.0) must be compatible with what's loaded on the bare metal.
FROM nvidia/cuda:12.0.0-devel-ubuntu22.04

# Define download location variables

ARG FILE_LOCATION="https://ispyfiles.azureedge.net/downloads/Agent_Linux64_4_9_6_0.zip"

ENV FILE_LOCATION_SET=${FILE_LOCATION:+true}
ENV DEFAULT_FILE_LOCATION="https://www.ispyconnect.com/api/Agent/DownloadLocation4?platform=Linux64&fromVersion=0"
ARG DEBIAN_FRONTEND=noninteractive 
ARG TZ=America/Los_Angeles
ARG name

# Download and install dependencies
RUN apt-get update \
    && apt-get install -y wget unzip software-properties-common alsa-utils

# Note: to install ffmpeg; you need the nv-codec-headers
# ffnvcodec
RUN apt-get install -y git make
RUN git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
RUN cd nv-codec-headers && make install && cd ..

# Download/Install iSpy Agent DVR: 
# Check if we were given a specific version
RUN if [ "${FILE_LOCATION_SET}" = "true" ]; then \
    echo "Downloading from specific location: ${FILE_LOCATION}" && \
    wget -c ${FILE_LOCATION} -O agent.zip; \
    else \
    #Get latest instead
    echo "Downloading latest" && \
    wget -c $(wget -qO- "https://www.ispyconnect.com/api/Agent/DownloadLocation4?platform=Linux64&fromVersion=0" | tr -d '"') -O agent.zip; \
    fi && \
    unzip agent.zip -d /agent && \
    rm agent.zip

# Install libgdiplus, used for smart detection
RUN apt-get install -y libgdiplus 

# Install ffmpeg
# NOTE: Added unzip wget libnuma1 libnuma-dev as per https://docs.nvidia.com/video-technologies/video-codec-sdk/11.1/ffmpeg-with-nvidia-gpu/index.html
RUN apt-get install -y build-essential xz-utils yasm cmake libtool libc6 libc6-dev \
 pkg-config libx264-dev libx265-dev libmp3lame-dev libopus-dev \
 libvorbis-dev libfdk-aac-dev libvpx-dev libva-dev \
 unzip wget libnuma1 libnuma-dev

# NOTE: Use the 'wget' method if you want a specific version of ffmpeg.
#RUN wget https://ffmpeg.org/releases/ffmpeg-6.0.tar.gz &&\
#tar xf ffmpeg-6.0.tar.gz &&\
#cd ffmpeg-6.0 && \

# NOTE: Using a git clone here; because v6.0 of ffmpeg is broken with respect to  --enable-hardcoded-tables
# Does that matter? Dunno 
RUN git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg/ &&\
cd ffmpeg && \
./configure --disable-debug \
 --disable-doc \
 --enable-shared \
 --enable-pthreads \
 --enable-hwaccels \
 # Broken in ffmpeg6.0 (works ok if pulling current from git direct)
 --enable-hardcoded-tables \   
 --enable-vaapi \
 --enable-nonfree \
 --enable-cuda-nvcc \
 --enable-libnpp \
 --disable-static \
 --enable-gpl \
 --enable-libx264 \
 --enable-libmp3lame \
 --enable-libopus \
 --enable-libvorbis \
 --enable-libfdk-aac \
 --enable-libx265 \
 --enable-libvpx \
 --extra-cflags=-I/usr/local/cuda/include \
 --extra-ldflags=-L/usr/local/cuda/lib64 && \
 make -j 8 && \
 make install && \
 cd ..

# Install Time Zone
RUN apt-get install -y tzdata

# Install curl, used for calling external webservices in Commands
RUN apt-get install -y curl

# Clean up
RUN apt-get -y --purge remove unzip wget build-essential \ 
    && apt autoremove -y \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Docker needs to run a TURN server to get webrtc traffic to and from it over forwarded ports from the host
# These are the default ports. If the ports below are modified here you'll also need to set the ports in XML/Config.xml
# for example <TurnServerPort>3478</TurnServerPort><TurnServerMinPort>50000</TurnServerMinPort><TurnServerMaxPort>50010</TurnServerMaxPort>
# The main server port is overridden by creating a text file called port.txt in the root directory containing the port number, eg: 8090
# To access the UI you must use the local IP address of the host, NOT localhost - for example http://192.168.1.12:8090/

# Modify permission for execution
RUN echo "Adding executable permissions" && \
    chmod +x /agent/Agent && \
    chmod +x /agent/agent-register.sh && \
    chmod +x /agent/agent-reset.sh && \
    chmod +x /agent/agent-reset-local-login.sh

# Define default environment variables
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Fix a memory leak on encoded recording
ENV MALLOC_TRIM_THRESHOLD_=100000

# Make sure that all libraries are loaded into the container
ENV NVIDIA_DRIVER_CAPABILITIES=all

# Main UI port
EXPOSE 8090

# STUN server port
EXPOSE 3478/udp

# TURN server UDP port range
EXPOSE 50000-50010/udp

# Data volumes
VOLUME ["/agent/Media/XML", "/agent/Media/WebServerRoot/Media", "/agent/Commands"]

# Define service entrypoint
CMD ["/agent/Agent"]