diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml index 8a776a7b..dd8ac7f6 100644 --- a/.github/workflows/artifacts.yml +++ b/.github/workflows/artifacts.yml @@ -47,7 +47,7 @@ jobs: submodules: true - name: Setup .NET Core - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x @@ -163,7 +163,7 @@ jobs: fetch-depth: 0 - name: Setup .NET Core - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 98da169c..30387833 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -58,17 +58,17 @@ jobs: if: ${{ matrix.qemu == true }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 id: docker-buildx - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.docker_hub_username }} password: ${{ secrets.docker_hub_access_token }} - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: builder: ${{ steps.docker-buildx.outputs.name }} context: . @@ -82,7 +82,7 @@ jobs: if: ${{ matrix.name != 'arm64' && matrix.name != 'arm32v7' }} - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: builder: ${{ steps.docker-buildx.outputs.name }} context: . @@ -97,7 +97,7 @@ jobs: if: ${{ matrix.name == 'arm64' }} - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@5 with: builder: ${{ steps.docker-buildx.outputs.name }} context: . diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e0d3d73c..6835890b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -9,7 +9,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET Core - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x @@ -44,7 +44,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET Core - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x @@ -72,7 +72,7 @@ jobs: submodules: true - name: Setup .NET Core - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x diff --git a/CHANGELOG.md b/CHANGELOG.md index aad409c6..92ec762b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix bug where previously-synchronized collection tags would disappear - This bug affected Jellyfin, Emby and Plex collections - Fix detection of AMF hardware acceleration on Windows +- Fix green line at bottom of video when NVIDIA accel is used with intermittent watermark ## [0.8.3-beta] - 2023-11-22 ### Added diff --git a/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs index 1edb6cea..91474912 100644 --- a/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs @@ -214,6 +214,16 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder fontsFolder, subtitleOverlayFilterSteps); + // need to use software overlay for watermark with fade points + // because `-loop 1` seems to cause a green line at the bottom of the resulting video with overlay_cuda + if (context.HasWatermark && watermarkInputFile + .Map(wm => wm.DesiredState.MaybeFadePoints.Map(fp => fp.Count > 0).IfNone(false)).IfNone(false)) + { + var hardwareDownload = new CudaHardwareDownloadFilter(currentState.PixelFormat, None); + currentState = hardwareDownload.NextState(currentState); + videoInputFile.FilterSteps.Add(hardwareDownload); + } + currentState = SetWatermark( videoStream, watermarkInputFile, @@ -404,17 +414,42 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder watermark.FilterSteps.AddRange(fadePoints.Map(fp => new WatermarkFadeFilter(fp))); } - watermark.FilterSteps.Add( - new HardwareUploadCudaFilter(currentState with { FrameDataLocation = FrameDataLocation.Software })); - - var watermarkFilter = new OverlayWatermarkCudaFilter( - watermark.DesiredState, - desiredState.PaddedSize, - videoStream.SquarePixelFrameSize(currentState.PaddedSize), - _logger); - watermarkOverlayFilterSteps.Add(watermarkFilter); + // if we're in software, it's because we need to overlay in software (watermark with fade points - loop) + if (currentState.FrameDataLocation is FrameDataLocation.Software) + { + foreach (IPixelFormat desiredPixelFormat in desiredState.PixelFormat) + { + IPixelFormat pf = desiredPixelFormat; + if (desiredPixelFormat is PixelFormatNv12 nv12) + { + foreach (IPixelFormat availablePixelFormat in AvailablePixelFormats.ForPixelFormat(nv12.Name, null)) + { + pf = availablePixelFormat; + } + } - currentState = watermarkFilter.NextState(currentState); + var watermarkFilter = new OverlayWatermarkFilter( + watermark.DesiredState, + desiredState.PaddedSize, + videoStream.SquarePixelFrameSize(currentState.PaddedSize), + pf, + _logger); + watermarkOverlayFilterSteps.Add(watermarkFilter); + } + } + else + { + watermark.FilterSteps.Add( + new HardwareUploadCudaFilter(currentState with { FrameDataLocation = FrameDataLocation.Software })); + + var watermarkFilter = new OverlayWatermarkCudaFilter( + watermark.DesiredState, + desiredState.PaddedSize, + videoStream.SquarePixelFrameSize(currentState.PaddedSize), + _logger); + watermarkOverlayFilterSteps.Add(watermarkFilter); + currentState = watermarkFilter.NextState(currentState); + } } return currentState;