############################
# bestsource / lsmash / ffms2
# todo: check if CFLAGS=-fPIC CXXFLAGS=-fPIC LDFLAGS="-Wl,-Bsymbolic" --extra-ldflags="-static" is required
############################
FROM ubuntu:22.04 as bestsource-lsmash-ffms2-vs

ARG DEBIAN_FRONTEND=noninteractive
WORKDIR /workspace

RUN apt update -y
RUN apt install autoconf libtool nasm ninja-build yasm python3.11 python3.11-venv python3.11-dev python3-pip wget git pkg-config python-is-python3 -y
RUN apt --fix-broken install
RUN pip install meson ninja cython

# install g++13
RUN apt install build-essential manpages-dev software-properties-common -y
RUN add-apt-repository ppa:ubuntu-toolchain-r/test -y
RUN apt update -y && apt install gcc-13 g++-13 -y
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13

# zimg
# setting pkg version manually since otherwise 'Version' field value '-1': version number is empty
RUN apt-get install checkinstall -y
RUN git clone https://github.com/sekrit-twc/zimg --recursive && cd zimg && \
  ./autogen.sh && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static --disable-shared && make -j$(nproc) && checkinstall -y -pkgversion=0.0 && \
  apt install /workspace/zimg/zimg_0.0-1_amd64.deb -y

# vapoursynth
RUN wget https://github.com/vapoursynth/vapoursynth/archive/refs/tags/R65.tar.gz && \
  tar -zxvf R65.tar.gz && mv vapoursynth-R65 vapoursynth && cd vapoursynth && \
  ./autogen.sh && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static --disable-shared && make -j$(nproc) && make install && ldconfig

# dav1d
RUN git clone https://code.videolan.org/videolan/dav1d/ && \
  cd dav1d && meson build --buildtype release -Ddefault_library=static && ninja -C build install

# ffmpeg
RUN apt remove ffmpeg -y
RUN git clone https://git.ffmpeg.org/ffmpeg.git --depth 1 && cd ffmpeg && \
  CFLAGS=-fPIC ./configure --disable-shared --enable-static --enable-gpl --enable-version3 --disable-programs --disable-doc --disable-avdevice --disable-swresample --disable-postproc --disable-avfilter --disable-encoders --disable-muxers --disable-debug --enable-pic --extra-ldflags="-static" --extra-cflags="-march=native" && \
  make -j$(nproc) && make install -j$(nproc)

# jansson
RUN git clone https://github.com/akheron/jansson && cd jansson && autoreconf -fi && CFLAGS=-fPIC ./configure --disable-shared --enable-static && \
  make -j$(nproc) && make install

# Vulkan-Headers
Run apt install cmake -y
RUN git clone https://github.com/KhronosGroup/Vulkan-Headers.git && cd Vulkan-Headers/ && cmake -S . -DBUILD_SHARED_LIBS=OFF -B build/ && cmake --install build

# nv-codec-headers
RUN git clone https://github.com/FFmpeg/nv-codec-headers && cd nv-codec-headers && make -j$(nproc) && make install

# bzip2
RUN git clone https://github.com/libarchive/bzip2 && cd bzip2 && \
  mkdir build && cd build && cmake .. -DBUILD_SHARED_LIBS=OFF && make -j$(nproc) && make install

# bestsource
RUN apt-get install -y && git clone https://github.com/vapoursynth/bestsource && cd bestsource && git clone https://github.com/sekrit-twc/libp2p.git --depth 1 && \
  CFLAGS=-fPIC meson setup -Dlink_static=true build && CFLAGS=-fPIC ninja -C build && ninja -C build install

# ffmpeg (HomeOfAviSynthPlusEvolution version with sws)
# official ffmpeg does not compile
# fatal error: libswresample/swresample.h: No such file or directory
RUN apt remove ffmpeg -y
RUN rm -rf FFmpeg

RUN git clone https://github.com/HomeOfAviSynthPlusEvolution/FFmpeg
RUN cd FFmpeg && git switch "custom-patches-for-lsmashsource" && git checkout -b new_branch bf4d6ef && \
  LDFLAGS="-Wl,-Bsymbolic" CFLAGS=-fPIC ./configure --disable-shared --enable-static --enable-gpl --enable-version3 --disable-programs --disable-doc --disable-avdevice --disable-postproc --disable-avfilter --disable-encoders --disable-muxers --disable-debug --enable-pic --extra-ldflags="-Wl,-Bsymbolic" --extra-cflags="-march=native" --disable-vulkan && \
  make -j$(nproc) && make install -j$(nproc)

# lsmash
RUN git clone https://github.com/l-smash/l-smash && cd l-smash && CFLAGS=-fPIC CXXFLAGS=-fPIC LDFLAGS="-Wl,-Bsymbolic" ./configure --enable-shared --extra-ldflags="-Wl,-Bsymbolic"  && \
  make -j$(nproc) && make install
RUN git clone https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works && cd L-SMASH-Works && \
   cd VapourSynth/ && CFLAGS=-fPIC CXXFLAGS=-fPIC LDFLAGS="-Wl,-Bsymbolic" meson build && CFLAGS=-fPIC CXXFLAGS=-fPIC LDFLAGS="-Wl,-Bsymbolic" ninja -C build && ninja -C build install 

# ffms2
RUN apt install autoconf -y
RUN git clone https://github.com/FFMS/ffms2 && cd ffms2 && ./autogen.sh && CFLAGS=-fPIC CXXFLAGS=-fPIC LDFLAGS="-Wl,-Bsymbolic" ./configure --enable-shared && make -j$(nproc) && make install

############################
# TensorRT + ORT
############################
FROM nvidia/cuda:12.1.1-devel-ubuntu22.04 as TensorRT-ubuntu

ARG DEBIAN_FRONTEND=noninteractive

# install python
# https://stackoverflow.com/questions/75159821/installing-python-3-11-1-on-a-docker-container
# https://stackoverflow.com/questions/45954528/pip-is-configured-with-locations-that-require-tls-ssl-however-the-ssl-module-in
# /usr/local/lib/libpython3.11.a(longobject.o): relocation R_X86_64_PC32 against symbol `_Py_NotImplementedStruct' can not be used when making a shared object; recompile with -fPIC
# todo: test CFLAGS="-fPIC -march=native"
RUN apt update -y && apt install liblzma-dev libbz2-dev ca-certificates openssl libssl-dev libncurses5-dev libsqlite3-dev libreadline-dev libtk8.6 libgdm-dev \
  libdb4o-cil-dev libpcap-dev software-properties-common wget zlib1g-dev -y && \
  wget https://www.python.org/ftp/python/3.11.3/Python-3.11.3.tar.xz && \
  tar -xf Python-3.11.3.tar.xz && cd Python-3.11.3 && \
  CFLAGS=-fPIC ./configure --with-openssl-rpath=auto --enable-optimizations CFLAGS=-fPIC && \
  make -j$(nproc) && make altinstall && make install
# todo: update-alternatives may not be required
RUN update-alternatives --install /usr/bin/python python /usr/local/bin/python3.11 1 && \
  update-alternatives --install /usr/bin/pip pip /usr/local/bin/pip3.11 1 && \
  cp /usr/local/bin/python3.11 /usr/local/bin/python && \
  cp /usr/local/bin/pip3.11 /usr/local/bin/pip && \
  cp /usr/local/bin/pip3.11 /usr/local/bin/pip3

# required since ModuleNotFoundError: No module named 'pip' with nvidia pip packages, even if cli works
RUN wget "https://bootstrap.pypa.io/get-pip.py" && python get-pip.py --force-reinstall

# TensorRT9
# trt9.3 with tar.gz since apt still only has 8.6

# TensorRT-9.3.0.1/bin/trtexec
# TensorRT-9.3.0.1/python/tensorrt-*-cp311-*.whl
# TensorRT-9.3.0.1/onnx_graphsurgeon/onnx_graphsurgeon-0.4.0-py2.py3-none-any.whl
# TensorRT-9.3.0.1/lib/*.so

# https://github.com/NVIDIA/TensorRT-LLM/blob/main/docker/common/install_tensorrt.sh
# https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=tensorrt
RUN wget "https://developer.download.nvidia.com/compute/machine-learning/tensorrt/9.3.0/TensorRT-9.3.0.1.Linux.x86_64-gnu.cuda-12.2.tar.gz" -O /tmp/TensorRT.tar
RUN tar -xf /tmp/TensorRT.tar -C /usr/local/
RUN mv /usr/local/TensorRT-9.3.0.1 /usr/local/tensorrt
RUN pip3 install /usr/local/tensorrt/python/tensorrt-*-cp311-*.whl
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/tensorrt/lib

# cudnn
# https://gitlab.archlinux.org/archlinux/packaging/packages/cudnn/-/blob/main/PKGBUILD?ref_type=heads
RUN wget "https://developer.download.nvidia.com/compute/cudnn/redist/cudnn/linux-x86_64/cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz" -O /tmp/cudnn.tar
RUN tar -xf /tmp/cudnn.tar -C /usr/local/
RUN mv /usr/local/cudnn-linux-x86_64-8.9.7.29_cuda12-archive /usr/local/cudnn
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cudnn

# ORT
# onnxruntime requires working tensorrt installation and thus can't be easily seperated into a seperate instance
# https://github.com/microsoft/onnxruntime/blob/main/dockerfiles/Dockerfile.tensorrt
ARG ONNXRUNTIME_REPO=https://github.com/Microsoft/onnxruntime
ARG ONNXRUNTIME_BRANCH=rel-1.17.0
ARG CMAKE_CUDA_ARCHITECTURES=37;50;52;53;60;61;62;70;72;75;80;89

RUN apt-get update &&\
    apt-get install -y sudo git bash unattended-upgrades
RUN unattended-upgrade

WORKDIR /code
ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH}

RUN apt install git -y

# cmake 3.28 (CMake 3.26 or higher is required)
RUN apt-get -y update && apt install wget && wget https://github.com/Kitware/CMake/releases/download/v3.28.0-rc1/cmake-3.28.0-rc1-linux-x86_64.sh  && \
    chmod +x cmake-3.28.0-rc1-linux-x86_64.sh  && sh cmake-3.28.0-rc1-linux-x86_64.sh  --skip-license && \
    cp /code/bin/cmake /usr/bin/cmake && cp /code/bin/cmake /usr/lib/cmake && \
    cp /code/bin/cmake /usr/local/bin/cmake && cp /code/bin/ctest /usr/local/bin/ctest && cp -r /code/share/cmake-3.28 /usr/local/share/ && \
    rm -rf cmake-3.28.0-rc1-linux-x86_64.sh 

# Prepare onnxruntime repository & build onnxruntime with TensorRT
# --parallel 32 oom
RUN git clone --single-branch --branch ${ONNXRUNTIME_BRANCH} --recursive ${ONNXRUNTIME_REPO} onnxruntime &&\
    /bin/sh onnxruntime/dockerfiles/scripts/install_common_deps.sh 
RUN /usr/local/bin/pip3 install psutil numpy wheel setuptools packaging
RUN cd onnxruntime && PYTHONPATH=/usr/bin/python3 /bin/sh build.sh --nvcc_threads 2 --parallel 16 --allow_running_as_root --build_shared_lib --cuda_home /usr/local/cuda \
      --cudnn_home /usr/local/cudnn --use_tensorrt --tensorrt_home /usr/local/tensorrt --config Release --build_wheel --skip_tests --skip_submodule_sync --cmake_extra_defines '"CMAKE_CUDA_ARCHITECTURES='${CMAKE_CUDA_ARCHITECTURES}'"'

# move trtexec so it can be globally accessed
RUN cp /usr/local/tensorrt/bin/trtexec /usr/bin


############################
# Vapoursynth
############################
WORKDIR /workspace

# zimg
# setting pkg version manually since otherwise 'Version' field value '-1': version number is empty
RUN apt-get install checkinstall -y
RUN apt install fftw3-dev pkg-config p7zip-full autoconf libtool yasm ffmsindex libffms2-5 libffms2-dev -y && \
  git clone https://github.com/sekrit-twc/zimg --depth 1 --recurse-submodules --shallow-submodules && cd zimg && \
  ./autogen.sh && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --enable-static --disable-shared && make -j$(nproc) && checkinstall -y -pkgversion=0.0 && \
  apt install /workspace/zimg/zimg_0.0-1_amd64.deb -y
  
# vapoursynth
RUN pip install --upgrade pip && pip install cython && git clone https://github.com/vapoursynth/vapoursynth && \
  cd vapoursynth && ./autogen.sh && \
  ./configure && make -j$(nproc) && make install && cd .. && ldconfig && \
  cd vapoursynth && python setup.py bdist_wheel

# pycuda
RUN pip install numpy && git clone https://github.com/inducer/pycuda --recursive && cd pycuda && python setup.py bdist_wheel


########################
# vs plugins

# vs-mlrt
RUN cp -r /usr/local/tensorrt/lib/* /usr/lib/x86_64-linux-gnu
RUN cp -r /usr/local/tensorrt/include/* /usr/include/x86_64-linux-gnu/
RUN cd /usr/lib/x86_64-linux-gnu \
  && ldconfig
ENV CPLUS_INCLUDE_PATH="/usr/include/x86_64-linux-gnu/"
RUN  git clone https://github.com/AmusementClub/vs-mlrt /workspace/vs-mlrt && cd /workspace/vs-mlrt/vstrt && mkdir build && \
  cd build && cmake .. -DVAPOURSYNTH_INCLUDE_DIRECTORY=/workspace/vapoursynth/include -D USE_NVINFER_PLUGIN=ON && make -j$(nproc) && make install 

RUN pip install meson ninja 

# Vapoursynth-VFRToCFR
RUN git clone https://github.com/Irrational-Encoding-Wizardry/Vapoursynth-VFRToCFR && cd Vapoursynth-VFRToCFR && \
  mkdir build && cd build && meson --buildtype release .. && ninja && ninja install

# fmtconv
RUN git clone https://github.com/EleonoreMizo/fmtconv && cd fmtconv/build/unix/ && ./autogen.sh && ./configure && make -j$(nproc) && make install

# VMAF
RUN apt install nasm xxd -y && wget https://github.com/Netflix/vmaf/archive/refs/tags/v3.0.0.tar.gz && \
  tar -xzf v3.0.0.tar.gz && cd vmaf-3.0.0/libvmaf/ && \
  meson build --buildtype release -Denable_cuda=true -Denable_avx512=true && ninja -C build && \
  ninja -C build install && cd /workspace && rm -rf v3.0.0.tar.gz vmaf-3.0.0 && \
  git clone https://github.com/HomeOfVapourSynthEvolution/VapourSynth-VMAF && cd VapourSynth-VMAF && meson build && \
  ninja -C build && ninja -C build install

# vs plugins
COPY --from=bestsource-lsmash-ffms2-vs /usr/local/lib/liblsmash.so* /usr/local/lib/
COPY --from=bestsource-lsmash-ffms2-vs /workspace/L-SMASH-Works/VapourSynth/build/libvslsmashsource.so /workspace/bestsource/build/libbestsource.so /usr/local/lib/vapoursynth

RUN cp /usr/local/lib/x86_64-linux-gnu/vapoursynth/libvfrtocfr.so /usr/local/lib/x86_64-linux-gnu/vapoursynth/libvfrtocfr.so /usr/local/lib/x86_64-linux-gnu/

RUN MAKEFLAGS="-j$(nproc)" pip install timm wget cmake scipy meson ninja numpy einops kornia vsutil onnx

RUN pip install coloredlogs flatbuffers numpy packaging protobuf sympy

# installing onnx tensorrt with a workaround, error with import otherwise
# https://github.com/onnx/onnx-tensorrt/issues/643
# also disables pip cache purge
RUN git clone https://github.com/onnx/onnx-tensorrt.git && \
  cd onnx-tensorrt && \
  cp -r onnx_tensorrt /usr/local/lib/python3.11/dist-packages && \
  cd .. && rm -rf onnx-tensorrt


RUN apt update && apt install ffmpeg -y

# trt
RUN cp -r /usr/local/cudnn/lib/* /usr/local/tensorrt/lib/* /usr/lib/x86_64-linux-gnu/

ENV CUDA_MODULE_LOADING=LAZY
WORKDIR /workspace