diff --git a/ErsatzTV.FFmpeg.Tests/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOptionTests.cs b/ErsatzTV.FFmpeg.Tests/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOptionTests.cs new file mode 100644 index 000000000..01c290b09 --- /dev/null +++ b/ErsatzTV.FFmpeg.Tests/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOptionTests.cs @@ -0,0 +1,38 @@ +using ErsatzTV.FFmpeg.Capabilities; +using ErsatzTV.FFmpeg.GlobalOption.HardwareAcceleration; +using NUnit.Framework; +using Shouldly; +using static LanguageExt.Prelude; + +namespace ErsatzTV.FFmpeg.Tests.GlobalOption.HardwareAcceleration; + +[TestFixture] +public class QsvHardwareAccelerationOptionTests +{ + [Test] + public void GlobalOptions_WithDevice_ShouldDeriveQsvDeviceFromVaapiDevice() + { + var option = new QsvHardwareAccelerationOption("/dev/dri/renderD128", FFmpegCapability.Software); + + option.GlobalOptions.ShouldBe( + [ + "-init_hw_device", "vaapi=va:/dev/dri/renderD128", + "-init_hw_device", "qsv=hw@va", + "-filter_hw_device", "hw" + ]); + } + + [Test] + public void GlobalOptions_WithHardwareDecode_ShouldEnableQsvHwaccel() + { + var option = new QsvHardwareAccelerationOption(None, FFmpegCapability.Hardware); + + option.GlobalOptions.ShouldBe( + [ + "-hwaccel", "qsv", + "-hwaccel_output_format", "qsv", + "-init_hw_device", "qsv=hw", + "-filter_hw_device", "hw" + ]); + } +} diff --git a/ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOption.cs b/ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOption.cs index 9754b9cda..e4691fac6 100644 --- a/ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOption.cs +++ b/ErsatzTV.FFmpeg/GlobalOption/HardwareAcceleration/QsvHardwareAccelerationOption.cs @@ -16,8 +16,6 @@ public class QsvHardwareAccelerationOption(Option device, FFmpegCapabili { get { - string[] initDevices = ["-init_hw_device", "qsv=hw", "-filter_hw_device", "hw"]; - var result = new List { "-hwaccel", "qsv", @@ -29,18 +27,26 @@ public class QsvHardwareAccelerationOption(Option device, FFmpegCapabili result.Clear(); } - if (OperatingSystem.IsLinux()) + var deviceConfigured = false; + foreach (string qsvDevice in device) { - foreach (string qsvDevice in device) + if (!string.IsNullOrWhiteSpace(qsvDevice)) { - if (!string.IsNullOrWhiteSpace(qsvDevice)) - { - result.AddRange(new[] { "-qsv_device", qsvDevice }); - } + result.AddRange( + [ + "-init_hw_device", $"vaapi=va:{qsvDevice}", + "-init_hw_device", "qsv=hw@va" + ]); + deviceConfigured = true; } } - result.AddRange(initDevices); + if (!deviceConfigured) + { + result.AddRange(["-init_hw_device", "qsv=hw"]); + } + + result.AddRange(["-filter_hw_device", "hw"]); return result.ToArray(); } diff --git a/docker/Dockerfile b/docker/Dockerfile index f468b1703..529cbb468 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble-amd64 AS dotnet-runtime -FROM --platform=linux/amd64 192.168.1.95:3000/timothy/ersatztv-ffmpeg:7.1.1 AS runtime-base +FROM --platform=linux/amd64 192.168.1.95:3000/timothy/ersatztv-ffmpeg:8.1.2 AS runtime-base COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet RUN apt-get update && \ apt-get install -y --no-install-recommends python3 python3-pip && \ @@ -40,7 +40,7 @@ COPY ErsatzTV.Infrastructure/*.csproj ./ErsatzTV.Infrastructure/ COPY ErsatzTV.Infrastructure.Sqlite/*.csproj ./ErsatzTV.Infrastructure.Sqlite/ COPY ErsatzTV.Infrastructure.MySql/*.csproj ./ErsatzTV.Infrastructure.MySql/ COPY ErsatzTV.Scanner/*.csproj ./ErsatzTV.Scanner/ -RUN dotnet restore -r linux-x64 ErsatzTV/ +RUN dotnet restore -r linux-x64 ErsatzTV/ErsatzTV.csproj # copy everything else and build app COPY ErsatzTV/. ./ErsatzTV/ diff --git a/docker/ffmpeg-tests/Dockerfile b/docker/ffmpeg-tests/Dockerfile index 5f3cedef4..4708f992c 100644 --- a/docker/ffmpeg-tests/Dockerfile +++ b/docker/ffmpeg-tests/Dockerfile @@ -1,14 +1,15 @@ -FROM ghcr.io/ersatztv/ersatztv-ffmpeg:7.1.1 +FROM 192.168.1.95:3000/timothy/ersatztv-ffmpeg:8.1.2 RUN apt-get update && apt-get install -y ca-certificates gnupg mkvtoolnix && \ curl -L https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh && \ chmod +x ./dotnet-install.sh && \ - ./dotnet-install.sh --channel 9.0 + ./dotnet-install.sh --channel 10.0 ENV DOTNET_ROOT="/root/.dotnet" ENV PATH="$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools" WORKDIR /source # copy csproj and restore as distinct layers COPY *.sln . +COPY Directory.Build.props Directory.Build.targets Directory.Packages.props global.json .editorconfig ./ COPY artwork/* ./artwork/ COPY ErsatzTV/*.csproj ./ErsatzTV/ COPY ErsatzTV.Application/*.csproj ./ErsatzTV.Application/ @@ -20,7 +21,7 @@ COPY ErsatzTV.Infrastructure.Sqlite/*.csproj ./ErsatzTV.Infrastructure.Sqlite/ COPY ErsatzTV.Infrastructure.MySql/*.csproj ./ErsatzTV.Infrastructure.MySql/ COPY ErsatzTV.Scanner/*.csproj ./ErsatzTV.Scanner/ COPY ErsatzTV.Scanner.Tests/*.csproj ./ErsatzTV.Scanner.Tests/ -RUN dotnet restore -r linux-x64 ErsatzTV/ +RUN dotnet restore -r linux-x64 ErsatzTV/ErsatzTV.csproj # copy everything else and build app COPY ErsatzTV/. ./ErsatzTV/ diff --git a/docs/ci-cd.md b/docs/ci-cd.md index 0bffb0fd3..a5e115929 100644 --- a/docs/ci-cd.md +++ b/docs/ci-cd.md @@ -75,9 +75,9 @@ the image build. ## Dockerfile notes (`docker/Dockerfile`) -- Base image: **`192.168.1.95:3000/timothy/ersatztv-ffmpeg:7.1.1`** (our Gitea fork of - the archived `ghcr.io/ersatztv/ersatztv-ffmpeg`). FFmpeg 8 upgrade is backlogged: - base image → ersatztv-ffmpeg#4, app-side compat → ersatztv#9. +- Base image: **`192.168.1.95:3000/timothy/ersatztv-ffmpeg:8.1.2`** (our Gitea fork of + the archived `ghcr.io/ersatztv/ersatztv-ffmpeg`). FFmpeg 8 base image work landed in + ersatztv-ffmpeg#4; app-side compatibility work landed in ersatztv#9. - Copies `Directory.Build.props`, `Directory.Build.targets`, `Directory.Packages.props`, `global.json`, `.editorconfig` before `dotnet restore` so the image build uses the same MSBuild config, central package versions, SDK pin, and analyzer severities as local/CI diff --git a/docs/fork-strategy.md b/docs/fork-strategy.md index 680f75ea9..731d7d1dd 100644 --- a/docs/fork-strategy.md +++ b/docs/fork-strategy.md @@ -24,7 +24,7 @@ We diverge freely from upstream's final state. There is no upstream to merge fro ### Docker Base Images - .NET SDK/runtime images (`mcr.microsoft.com/dotnet/sdk:10.0-noble-amd64`) — update when .NET patches ship. -- FFmpeg image: forked separately at [timothy/ersatztv-ffmpeg](http://192.168.1.95:3000/timothy/ersatztv-ffmpeg). Currently `192.168.1.95:3000/timothy/ersatztv-ffmpeg:7.1.1`. The main Dockerfile still references the upstream `ghcr.io` image and needs updating. +- FFmpeg image: forked separately at [timothy/ersatztv-ffmpeg](http://192.168.1.95:3000/timothy/ersatztv-ffmpeg). Currently `192.168.1.95:3000/timothy/ersatztv-ffmpeg:8.1.2`. ### CVE Response