Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Separate Linux static from hardware encoding #48

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
matrix:
include: ${{ fromJSON(needs.matrix_config.outputs.MATRIX) }}

name: Build ${{ matrix.os_name }} ${{ matrix.target_arch }}
name: Build ${{ matrix.os_name }} ${{ matrix.target_arch }} ${{ matrix.container }}
runs-on: ${{ matrix.os }}
container:
image: ${{ matrix.container }}
Expand All @@ -125,7 +125,7 @@ jobs:
# actions.
# See https://github.com/actions/runner/issues/801#issuecomment-2394425757
- name: Patch native Alpine NodeJS into Runner environment
if: runner.os == 'Linux'
if: startsWith(matrix.container, 'alpine')
run: |
apk add nodejs
sed -i "s:^ID=alpine:ID=NotpineForGHA:" /etc/os-release
Expand All @@ -140,10 +140,16 @@ jobs:
shell: sh # No bash in Alpine by default

- name: Install Alpine Linux deps
if: runner.os == 'Linux'
if: startsWith(matrix.container, 'alpine')
run: apk add bash npm sudo
shell: sh # No bash in Alpine until after this command

- name: Install Ubuntu Linux deps
if: startsWith(matrix.container, 'ubuntu')
# Sudo is needed by the first build script, but isn't in the default
# container image for Ubuntu.
run: apt -y update && apt -y upgrade && apt -y install sudo

- uses: actions/checkout@v4
with:
path: repo-src
Expand Down
38 changes: 36 additions & 2 deletions build-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@
"comment1": "runners hosted by GitHub, always enabled",
"hosted": [
{
"comment": "Alpine container for static Linux binaries",
"os": "ubuntu-latest",
"container": "alpine:3.20",
"os_name": "linux",
"target_arch": "x64",
"exe_ext": ""
},
{
"comment": "Ubuntu 24.04 with hardware acceleration",
"os": "ubuntu-latest",
"container": "ubuntu:24.04",
"os_name": "linux",
"target_arch": "x64",
"exe_ext": "-ubuntu-24.04"
},
{
"comment": "Ubuntu 22.04 with hardware acceleration",
"os": "ubuntu-latest",
"container": "ubuntu:22.04",
"os_name": "linux",
"target_arch": "x64",
"exe_ext": "-ubuntu-22.04"
},
{
"comment": "Explicit macOS version 13 is required for explicit x64 CPU.",
"os": "macos-13",
Expand All @@ -16,7 +33,7 @@
"exe_ext": ""
},
{
"comment": "Latest macOS version 13 is arm64 CPU.",
"comment": "Latest macOS version is arm64 CPU.",
"os": "macos-latest",
"os_name": "osx",
"target_arch": "arm64",
Expand All @@ -33,11 +50,28 @@
"comment2": "runners hosted by the owner, enabled by the ENABLE_SELF_HOSTED variable being set on the repo",
"selfHosted": [
{
"comment": "Alpine container for static Linux binaries",
"os": "self-hosted-linux-arm64",
"container": "arm64v8/alpine:3.20",
"container": "alpine:3.20",
"os_name": "linux",
"target_arch": "arm64",
"exe_ext": ""
},
{
"comment": "Ubuntu 24.04 with hardware acceleration",
"os": "self-hosted-linux-arm64",
"container": "ubuntu:24.04",
"os_name": "linux",
"target_arch": "arm64",
"exe_ext": "-ubuntu-24.04"
},
{
"comment": "Ubuntu 22.04 with hardware acceleration",
"os": "self-hosted-linux-arm64",
"container": "ubuntu:22.04",
"os_name": "linux",
"target_arch": "arm64",
"exe_ext": "-ubuntu-22.04"
}
]
}
3 changes: 2 additions & 1 deletion build-scripts/00-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ if [[ "$RUNNER_OS" == "Linux" ]]; then
sudo apt -y update
sudo apt -y upgrade
sudo apt -y install \
clang \
cmake \
curl \
g++ \
git \
libffmpeg-nvenc-dev \
libvdpau-dev \
libva-dev \
make \
nasm \
npm \
Expand Down
39 changes: 24 additions & 15 deletions build-scripts/90-ffmpeg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,27 @@ cd ffmpeg

# Set some OS-specific environment variables and flags.
if [[ "$RUNNER_OS" == "Linux" ]]; then
export CFLAGS="-static"
export LDFLAGS="-static"
if ../repo-src/is-alpine.sh; then
# Truly static builds are only possible in musl-based Alpine Linux.
# Go for a completely static binary, but this prevents the use of hardware
# acceleration.
export CFLAGS="-static"
export LDFLAGS="-static"
else
# We can't build a truly static binary, so we might as well enable hardware
# acceleration, which uses dynamic libraries and will depend heavily on the
# OS distribution.
PLATFORM_CONFIGURE_FLAGS="--enable-vaapi --enable-nvenc"
Comment on lines +35 to +36
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting...
didn't nvenc use to be gpl incompatible and thus not re-distributable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are only compiling against these headers from ffmpeg: https://github.com/FFmpeg/nv-codec-headers/blob/master/include/ffnvcodec/nvEncodeAPI.h

So we don't directly link against anything from Nvidia AFAICT.

# TODO: Is AMF an option for us in this context?

# Enable platform-specific hardware acceleration.
PLATFORM_CONFIGURE_FLAGS="--enable-vdpau"
# This version of ffmpeg will accept NVEnc 11.5.1.3+, but not Ubuntu
# 22.04's packaged version, 11.5.1.1. This patch makes it flexible enough
# to build with the older NVEnc version in Ubuntu Jammy.
# For code archaeologists, the commits that set the minimum beyond 11.5.1.1
# were https://github.com/ffmpeg/ffmpeg/commit/5c288a44 (released in n6.0)
# and https://github.com/ffmpeg/ffmpeg/commit/05f8b2ca (released in n6.1).
patch -p1 -i ../repo-src/ffmpeg-nvenc-jammy.patch
fi
elif [[ "$RUNNER_OS" == "macOS" ]]; then
export CFLAGS="-static"
# You can't do a _truly_ static build on macOS except the kernel.
Expand All @@ -36,11 +52,10 @@ elif [[ "$RUNNER_OS" == "macOS" ]]; then
# Enable platform-specific hardware acceleration.
PLATFORM_CONFIGURE_FLAGS="--enable-videotoolbox"

# Disable x86 ASM on macOS. It fails to build with an error about
# how macho64 format can't contain 32-bit assembly. I'm not sure
# how else to resolve this, and from my searches, it appears that
# others are not having this problem with ffmpeg. This is still a problem
# with n6.0.
# Disable x86 ASM on macOS. It fails to build with an error about "32-bit
# absolute addressing is not supported in 64-bit mode". I'm not sure how
# else to resolve this, and from my searches, it appears that others are not
# having this problem with ffmpeg. This is still a problem with n7.1
PLATFORM_CONFIGURE_FLAGS="$PLATFORM_CONFIGURE_FLAGS --disable-x86asm --disable-inline-asm"
elif [[ "$RUNNER_OS" == "Windows" ]]; then
# /usr/local/incude and /usr/local/lib are not in mingw's include
Expand All @@ -55,12 +70,6 @@ elif [[ "$RUNNER_OS" == "Windows" ]]; then
PLATFORM_CONFIGURE_FLAGS="--target-os=mingw64"
fi

# Install a patch from https://github.com/FFmpeg/FFmpeg/commit/effadce6 to
# resolve the binutils error "operand type mismatch for shr" on Windows,
# described in https://github.com/msys2/MINGW-packages/issues/17946
wget https://github.com/FFmpeg/FFmpeg/commit/effadce6.patch
patch -p1 -i effadce6.patch

if ! ./configure \
--pkg-config-flags="--static" \
--disable-ffplay \
Expand Down
14 changes: 10 additions & 4 deletions build-scripts/99-check-static.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@ set -x
cd ffmpeg

if [[ "$RUNNER_OS" == "Linux" ]]; then
# If ldd succeeds, then these are dynamic executables, so we fail
# this step if ldd succeeds. The output of ldd will still be logged.
ldd ffmpeg && exit 1
ldd ffprobe && exit 1
# We only check for static binaries on Alpine Linux. In other distributions,
# these are not possible due to the use of glibc. We allow glibc builds here
# because while tied to the distro, they at least give us the chance for
# hardware encoding.
if ../repo-src/is-alpine.sh; then
# If ldd succeeds, then these are dynamic executables, so we fail
# this step if ldd succeeds. The output of ldd will still be logged.
ldd ffmpeg && exit 1
ldd ffprobe && exit 1
fi
elif [[ "$RUNNER_OS" == "Windows" ]]; then
# These will still be dynamic executables.
# Capture the full list of DLL dependencies.
Expand Down
48 changes: 48 additions & 0 deletions ffmpeg-nvenc-jammy.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
FFmpeg n7.1 will accept NVEnc 11.5.1.3+, but not Ubuntu 22.04's packaged
version, 11.5.1.1. This patch makes it flexible enough to build with the older
NVEnc version in Ubuntu Jammy. For code archaeologists, the commits that set
the minimum beyond 11.5.1.1 were
https://github.com/ffmpeg/ffmpeg/commit/5c288a44 (released in n6.0) and
https://github.com/ffmpeg/ffmpeg/commit/05f8b2ca (released in n6.1).


diff --git a/configure b/configure
index d77a55b653..c28dcffbb0 100755
--- a/configure
+++ b/configure
@@ -6761,7 +6761,7 @@ if ! disabled ffnvcodec; then
ffnv_hdr_list="ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h"
check_pkg_config ffnvcodec "ffnvcodec >= 12.1.14.0" "$ffnv_hdr_list" "" || \
check_pkg_config ffnvcodec "ffnvcodec >= 12.0.16.1 ffnvcodec < 12.1" "$ffnv_hdr_list" "" || \
- check_pkg_config ffnvcodec "ffnvcodec >= 11.1.5.3 ffnvcodec < 12.0" "$ffnv_hdr_list" "" || \
+ check_pkg_config ffnvcodec "ffnvcodec >= 11.1.5.1 ffnvcodec < 12.0" "$ffnv_hdr_list" "" || \
check_pkg_config ffnvcodec "ffnvcodec >= 11.0.10.3 ffnvcodec < 11.1" "$ffnv_hdr_list" "" || \
check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.15 ffnvcodec < 8.2" "$ffnv_hdr_list" ""
fi
@@ -7388,7 +7388,7 @@ int main(void) { return 0; }
EOF

if enabled nvenc; then
- check_type "ffnvcodec/nvEncodeAPI.h" "NV_ENC_PIC_PARAMS_AV1"
+ check_type "ffnvcodec/nvEncodeAPI.h" "NV_ENC_PIC_PARAMS_AV1" || add_cflags -DJAMMY
fi

if enabled_any nvdec cuvid; then
diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c
index 3de3847399..0815360a46 100644
--- a/libavutil/hwcontext_cuda.c
+++ b/libavutil/hwcontext_cuda.c
@@ -363,11 +363,13 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) {
hwctx->internal->cuda_device));
if (ret < 0)
return ret;
+#ifndef JAMMY
} else if (flags & AV_CUDA_USE_CURRENT_CONTEXT) {
ret = CHECK_CU(cu->cuCtxGetCurrent(&hwctx->cuda_ctx));
if (ret < 0)
return ret;
av_log(device_ctx, AV_LOG_INFO, "Using current CUDA context.\n");
+#endif
} else {
ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags,
hwctx->internal->cuda_device));
2 changes: 1 addition & 1 deletion versions.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ffmpeg: n6.0
ffmpeg: n7.1
libvpx: v1.13.0
svt-av1: v1.7.0
x264: a8b68ebf
Expand Down
Loading