diff --git a/CHANGELOG.md b/CHANGELOG.md index 126852cf..8947907d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderImplicitCuda.cs b/ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderImplicitCuda.cs index dcbba225..756b9659 100644 --- a/ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderImplicitCuda.cs +++ b/ErsatzTV.FFmpeg/Decoder/Cuvid/DecoderImplicitCuda.cs @@ -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) }); } } diff --git a/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs index ea7c119e..a98055df 100644 --- a/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs @@ -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 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)) { diff --git a/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs b/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs index 815e38e0..bdf4d2c3 100644 --- a/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs +++ b/ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs @@ -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); diff --git a/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs index c2351bf8..93a5671b 100644 --- a/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs @@ -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 // 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) }; } }