Browse Source

fix nvidia edge case with missing bit depth info (#2123)

* fix nvidia edge case with missing bit depth info

* revert docker-compose changes
pull/2125/head
Jason Dove 1 month ago committed by GitHub
parent
commit
beaaa62ed9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderImplicitCuda.cs
  3. 4
      ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs
  4. 2
      ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs
  5. 21
      ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs

1
CHANGELOG.md

@ -95,6 +95,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -95,6 +95,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- This only matters if you configured `ETV_UI_PORT` to be a different value, which makes UI endpoints inaccessible on the streaming port
- Update Plex movie/other video plot ("summary") during library deep scan
- Fix compatibility with ffmpeg 7.2+ when using NVIDIA accel and 10-bit source content
- Fix some NVIDIA edge cases when media servers don't provide video bit depth information
## [25.2.0] - 2025-06-24
### Added

2
ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderImplicitCuda.cs

@ -22,6 +22,6 @@ public class DecoderImplicitCuda : DecoderBase @@ -22,6 +22,6 @@ public class DecoderImplicitCuda : DecoderBase
pixelFormat => pixelFormat.BitDepth == 8
? nextState with { PixelFormat = new PixelFormatNv12(pixelFormat.Name) }
: nextState with { PixelFormat = new PixelFormatCuda(pixelFormat.Name, 10) },
() => nextState);
() => nextState with { PixelFormat = new PixelFormatNv12(FFmpegFormat.YUV420P) });
}
}

4
ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs

@ -166,7 +166,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -166,7 +166,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
currentState = decoder.NextState(currentState);
// ffmpeg 7.2+ uses p016 internally for cuda, so convert to p010 for compatibility until min ver is 7.2
if (decoder is DecoderImplicitCuda && videoStream.PixelFormat.Map(pf => pf.BitDepth).IfNone(8) == 10)
if (decoder is DecoderImplicitCuda && videoStream.BitDepth == 10)
{
var filter = new ScaleCudaFilter(
currentState with { PixelFormat = new PixelFormatP010() },
@ -573,7 +573,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -573,7 +573,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
var pixelFormatFilter = new PixelFormatFilter(new PixelFormatYuva420P());
subtitle.FilterSteps.Add(pixelFormatFilter);
if (currentState.PixelFormat.Map(pf => pf.BitDepth).IfNone(8) == 8)
if (currentState.BitDepth == 8)
{
if (_ffmpegCapabilities.HasFilter(FFmpegKnownFilter.ScaleNpp))
{

2
ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs

@ -198,7 +198,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -198,7 +198,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
_subtitleInputFile.Map(s => s is { IsImageBased: true, Method: SubtitleMethod.Burn }).IfNone(false),
_subtitleInputFile.Map(s => s is { IsImageBased: false, Method: SubtitleMethod.Burn }).IfNone(false),
desiredState.Deinterlaced,
desiredState.PixelFormat.Map(pf => pf.BitDepth).IfNone(8) == 10,
desiredState.BitDepth == 10,
false,
videoStream.ColorParams.IsHdr);

21
ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs

@ -75,7 +75,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -75,7 +75,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
}
bool isHevcOrH264 = videoStream.Codec is /*VideoFormat.Hevc or*/ VideoFormat.H264;
bool is10Bit = videoStream.PixelFormat.Map(pf => pf.BitDepth).IfNone(8) == 10;
bool is10Bit = videoStream.BitDepth == 10;
// 10-bit hevc/h264 qsv decoders have issues, so use software
if (decodeCapability == FFmpegCapability.Hardware && isHevcOrH264 && is10Bit)
@ -336,18 +336,15 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -336,18 +336,15 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
// force p010/nv12 if we're still in hardware
if (currentState.FrameDataLocation == FrameDataLocation.Hardware)
{
foreach (int bitDepth in currentState.PixelFormat.Map(pf => pf.BitDepth))
if (currentState.BitDepth is 10 && formatForDownload is not PixelFormatYuv420P10Le)
{
if (bitDepth is 10 && formatForDownload is not PixelFormatYuv420P10Le)
{
formatForDownload = new PixelFormatYuv420P10Le();
currentState = currentState with { PixelFormat = Some(formatForDownload) };
}
else if (bitDepth is 8 && formatForDownload is not PixelFormatNv12)
{
formatForDownload = new PixelFormatNv12(formatForDownload.Name);
currentState = currentState with { PixelFormat = Some(formatForDownload) };
}
formatForDownload = new PixelFormatYuv420P10Le();
currentState = currentState with { PixelFormat = Some(formatForDownload) };
}
else if (currentState.BitDepth is 8 && formatForDownload is not PixelFormatNv12)
{
formatForDownload = new PixelFormatNv12(formatForDownload.Name);
currentState = currentState with { PixelFormat = Some(formatForDownload) };
}
}

Loading…
Cancel
Save