Browse Source

optimize image playback (#1609)

pull/1610/head
Jason Dove 1 year ago committed by GitHub
parent
commit
9587692486
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      ErsatzTV.FFmpeg/Filter/LoopFilter.cs
  2. 4
      ErsatzTV.FFmpeg/InputOption/InfiniteLoopInputOption.cs
  3. 2
      ErsatzTV.FFmpeg/InputOption/ReadrateInputOption.cs
  4. 1
      ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs
  5. 9
      ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs
  6. 1
      ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs
  7. 1
      ErsatzTV.FFmpeg/Pipeline/SoftwarePipelineBuilder.cs
  8. 2
      ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs

8
ErsatzTV.FFmpeg/Filter/LoopFilter.cs

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
namespace ErsatzTV.FFmpeg.Filter;
public class LoopFilter : BaseFilter
{
public override FrameState NextState(FrameState currentState) => currentState;
public override string Filter => "loop=-1:1";
}

4
ErsatzTV.FFmpeg/InputOption/InfiniteLoopInputOption.cs

@ -17,11 +17,11 @@ public class InfiniteLoopInputOption : IInputOption @@ -17,11 +17,11 @@ public class InfiniteLoopInputOption : IInputOption
// loop 1 for still images
if (inputFile.Streams.OfType<VideoStream>().Any(s => s.StillImage))
{
return new[] { "-loop", "1" };
return ["-loop", "1"];
}
// stream_loop for looped video i.e. filler
return new[] { "-stream_loop", "-1" };
return ["-stream_loop", "-1"];
}
public string[] FilterOptions => Array.Empty<string>();

2
ErsatzTV.FFmpeg/InputOption/ReadrateInputOption.cs

@ -55,7 +55,7 @@ public class ReadrateInputOption : IInputOption @@ -55,7 +55,7 @@ public class ReadrateInputOption : IInputOption
public string[] OutputOptions => Array.Empty<string>();
public FrameState NextState(FrameState currentState) => currentState with { Realtime = true };
public bool AppliesTo(AudioInputFile audioInputFile) => true;
public bool AppliesTo(AudioInputFile audioInputFile) => audioInputFile is not NullAudioInputFile;
// don't use realtime input for a still image
public bool AppliesTo(VideoInputFile videoInputFile) => videoInputFile.VideoStreams.All(s => !s.StillImage);

1
ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs

@ -161,6 +161,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder @@ -161,6 +161,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
currentState = SetScale(videoInputFile, videoStream, context, ffmpegState, desiredState, currentState);
currentState = SetPad(videoInputFile, videoStream, desiredState, currentState);
currentState = SetCrop(videoInputFile, desiredState, currentState);
SetStillImageLoop(videoInputFile, videoStream);
if (currentState.BitDepth == 8 && context.HasSubtitleOverlay || context.HasWatermark)
{

9
ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs

@ -440,7 +440,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -440,7 +440,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
? None
: SetDecoder(videoInputFile, videoStream, ffmpegState, context);
SetStillImageInfiniteLoop(videoInputFile, videoStream, ffmpegState);
//SetStillImageInfiniteLoop(videoInputFile, videoStream, ffmpegState);
SetRealtimeInput(videoInputFile, ffmpegState, desiredState);
SetInfiniteLoop(videoInputFile, videoStream, ffmpegState, desiredState);
SetFrameRateOutput(desiredState, pipelineSteps);
@ -643,14 +643,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -643,14 +643,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
videoInputFile.AddOption(new ReadrateInputOption(_ffmpegCapabilities, initialBurst, _logger));
}
private static void SetStillImageInfiniteLoop(
VideoInputFile videoInputFile,
VideoStream videoStream,
FFmpegState ffmpegState)
protected static void SetStillImageLoop(VideoInputFile videoInputFile, VideoStream videoStream)
{
if (videoStream.StillImage)
{
videoInputFile.AddOption(new InfiniteLoopInputOption(ffmpegState.EncoderHardwareAccelerationMode));
videoInputFile.FilterSteps.Add(new LoopFilter());
}
}

1
ErsatzTV.FFmpeg/Pipeline/QsvPipelineBuilder.cs

@ -166,6 +166,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder @@ -166,6 +166,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
currentState = SetPad(videoInputFile, videoStream, desiredState, currentState);
// _logger.LogDebug("After pad: {PixelFormat}", currentState.PixelFormat);
currentState = SetCrop(videoInputFile, desiredState, currentState);
SetStillImageLoop(videoInputFile, videoStream);
// need to download for any sort of overlay
if (currentState.FrameDataLocation == FrameDataLocation.Hardware &&

1
ErsatzTV.FFmpeg/Pipeline/SoftwarePipelineBuilder.cs

@ -105,6 +105,7 @@ public class SoftwarePipelineBuilder : PipelineBuilderBase @@ -105,6 +105,7 @@ public class SoftwarePipelineBuilder : PipelineBuilderBase
currentState = SetScale(videoInputFile, videoStream, desiredState, currentState);
currentState = SetPad(videoInputFile, videoStream, desiredState, currentState);
currentState = SetCrop(videoInputFile, desiredState, currentState);
SetStillImageLoop(videoInputFile, videoStream);
SetSubtitle(
videoInputFile,
subtitleInputFile,

2
ErsatzTV.FFmpeg/Pipeline/VaapiPipelineBuilder.cs

@ -170,6 +170,8 @@ public class VaapiPipelineBuilder : SoftwarePipelineBuilder @@ -170,6 +170,8 @@ public class VaapiPipelineBuilder : SoftwarePipelineBuilder
currentState = SetCrop(videoInputFile, desiredState, currentState);
SetStillImageLoop(videoInputFile, videoStream);
// need to upload for hardware overlay
bool forceSoftwareOverlay = context is { HasSubtitleOverlay: true, HasWatermark: true }
|| ffmpegState.VaapiDriver == "radeonsi";

Loading…
Cancel
Save