Browse Source

limit hls direct streams to realtime speed (#1237)

pull/1238/head
Jason Dove 2 years ago committed by GitHub
parent
commit
cf1552910a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 7
      ErsatzTV.FFmpeg.Tests/PipelineBuilderBaseTests.cs
  3. 41
      ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs

3
CHANGELOG.md

@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Limit `HLS Direct` streams to realtime speed
## [0.7.7-beta] - 2023-04-07
### Added
- Use `plot` field from Other Video NFO metadata as XMLTV description

7
ErsatzTV.FFmpeg.Tests/PipelineBuilderBaseTests.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using ErsatzTV.FFmpeg.Capabilities;
using ErsatzTV.FFmpeg.Encoder;
using ErsatzTV.FFmpeg.Format;
using ErsatzTV.FFmpeg.Option;
using ErsatzTV.FFmpeg.OutputFormat;
using ErsatzTV.FFmpeg.Pipeline;
using ErsatzTV.FFmpeg.State;
@ -325,11 +326,13 @@ public class PipelineBuilderBaseTests @@ -325,11 +326,13 @@ public class PipelineBuilderBaseTests
result.PipelineSteps.Should().HaveCountGreaterThan(0);
result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyVideo);
result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyAudio);
videoInputFile.InputOptions.Should().Contain(io => io is RealtimeInputOption);
string command = PrintCommand(videoInputFile, audioInputFile, None, None, result);
// 0.4.0 reference: "-nostdin -threads 1 -hide_banner -loglevel error -nostats -fflags +genpts+discardcorrupt+igndts -re -ss 00:14:33.6195516 -i /tmp/whatever.mkv -map 0:0 -map 0:a -c:v copy -flags cgop -sc_threshold 0 -c:a copy -movflags +faststart -muxdelay 0 -muxpreload 0 -metadata service_provider="ErsatzTV" -metadata service_name="ErsatzTV" -t 00:06:39.6934484 -f mpegts -mpegts_flags +initial_discontinuity pipe:1"
command.Should().Be(
"-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -i /tmp/whatever.mkv -map 0:1 -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
"-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -re -i /tmp/whatever.mkv -map 0:1 -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
}
[Test]
@ -407,7 +410,7 @@ public class PipelineBuilderBaseTests @@ -407,7 +410,7 @@ public class PipelineBuilderBaseTests
string command = PrintCommand(videoInputFile, audioInputFile, None, None, result);
command.Should().Be(
"-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -i /tmp/whatever.mkv -map 0:a -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
"-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -re -i /tmp/whatever.mkv -map 0:a -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
}
[Test]

41
ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs

@ -174,22 +174,13 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -174,22 +174,13 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
SetStreamSeek(ffmpegState, videoInputFile, context, pipelineSteps);
SetTimeLimit(ffmpegState, pipelineSteps);
FilterChain filterChain = FilterChain.Empty;
if (desiredState.VideoFormat == VideoFormat.Copy)
{
pipelineSteps.Add(new EncoderCopyVideo());
}
else
{
filterChain = BuildVideoPipeline(
FilterChain filterChain = BuildVideoPipeline(
videoInputFile,
videoStream,
ffmpegState,
desiredState,
context,
pipelineSteps);
}
if (_audioInputFile.IsNone)
{
@ -398,7 +389,10 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -398,7 +389,10 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
ffmpegState = SetAccelState(videoStream, ffmpegState, desiredState, context, pipelineSteps);
Option<IDecoder> maybeDecoder = SetDecoder(videoInputFile, videoStream, ffmpegState, context);
// don't use explicit decoder with HLS Direct
Option<IDecoder> maybeDecoder = desiredState.VideoFormat == VideoFormat.Copy
? None
: SetDecoder(videoInputFile, videoStream, ffmpegState, context);
SetStillImageInfiniteLoop(videoInputFile, videoStream, ffmpegState);
SetRealtimeInput(videoInputFile, desiredState);
@ -473,6 +467,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -473,6 +467,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
private static void SetOutputTsOffset(FFmpegState ffmpegState, FrameState desiredState, ICollection<IPipelineStep> pipelineSteps)
{
if (desiredState.VideoFormat == VideoFormat.Copy)
{
return;
}
if (ffmpegState.PtsOffset > 0)
{
foreach (int videoTrackTimeScale in desiredState.VideoTrackTimeScale)
@ -484,6 +483,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -484,6 +483,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
private static void SetVideoBufferSizeOutput(FrameState desiredState, ICollection<IPipelineStep> pipelineSteps)
{
if (desiredState.VideoFormat == VideoFormat.Copy)
{
return;
}
foreach (int desiredBufferSize in desiredState.VideoBufferSize)
{
pipelineSteps.Add(new VideoBufferSizeOutputOption(desiredBufferSize));
@ -492,6 +496,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -492,6 +496,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
private static void SetVideoBitrateOutput(FrameState desiredState, ICollection<IPipelineStep> pipelineSteps)
{
if (desiredState.VideoFormat == VideoFormat.Copy)
{
return;
}
foreach (int desiredBitrate in desiredState.VideoBitrate)
{
pipelineSteps.Add(new VideoBitrateOutputOption(desiredBitrate));
@ -500,6 +509,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -500,6 +509,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
private static void SetVideoTrackTimescaleOutput(FrameState desiredState, ICollection<IPipelineStep> pipelineSteps)
{
if (desiredState.VideoFormat == VideoFormat.Copy)
{
return;
}
foreach (int desiredTimeScale in desiredState.VideoTrackTimeScale)
{
pipelineSteps.Add(new VideoTrackTimescaleOutputOption(desiredTimeScale));
@ -508,6 +522,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -508,6 +522,11 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
private static void SetFrameRateOutput(FrameState desiredState, ICollection<IPipelineStep> pipelineSteps)
{
if (desiredState.VideoFormat == VideoFormat.Copy)
{
return;
}
foreach (int desiredFrameRate in desiredState.FrameRate)
{
pipelineSteps.Add(new FrameRateOutputOption(desiredFrameRate));

Loading…
Cancel
Save