Browse Source

refactor

pull/2824/head
Jason Dove 6 months ago
parent
commit
53cad42e76
No known key found for this signature in database
  1. 209
      ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs
  2. 2
      ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs
  3. 2
      ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs

209
ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs

@ -665,7 +665,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
string vaapiDevice, string vaapiDevice,
Option<int> qsvExtraHardwareFrames) Option<int> qsvExtraHardwareFrames)
{ {
FFmpegPlaybackSettings playbackSettings = FFmpegPlaybackSettingsCalculator.CalculateErrorSettings( FFmpegPlaybackSettings playbackSettings = FFmpegPlaybackSettingsCalculator.CalculateGeneratedImageSettings(
channel.StreamingMode, channel.StreamingMode,
channel.FFmpegProfile, channel.FFmpegProfile,
hlsRealtime); hlsRealtime);
@ -726,57 +726,6 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
playbackSettings.NormalizeColors, playbackSettings.NormalizeColors,
playbackSettings.Deinterlace); playbackSettings.Deinterlace);
OutputFormatKind outputFormat = OutputFormatKind.MpegTs;
switch (channel.StreamingMode)
{
case StreamingMode.HttpLiveStreamingSegmenter:
outputFormat = OutputFormatKind.Hls;
break;
}
Option<string> hlsPlaylistPath = outputFormat is OutputFormatKind.Hls or OutputFormatKind.HlsMp4
? Path.Combine(FileSystemLayout.TranscodeFolder, channel.Number, "live.m3u8")
: Option<string>.None;
long nowSeconds = now.ToUnixTimeSeconds();
Option<string> hlsSegmentTemplate = outputFormat switch
{
OutputFormatKind.Hls => Path.Combine(FileSystemLayout.TranscodeFolder, channel.Number, "live%06d.ts"),
OutputFormatKind.HlsMp4 => Path.Combine(
FileSystemLayout.TranscodeFolder,
channel.Number,
$"live_{nowSeconds}_%06d.m4s"),
_ => Option<string>.None
};
Option<string> hlsInitTemplate = outputFormat switch
{
OutputFormatKind.HlsMp4 => $"{nowSeconds}_init.mp4",
_ => Option<string>.None
};
Option<string> hlsSegmentOptions = Option<string>.None;
if (outputFormat is OutputFormatKind.Hls)
{
string options = string.Empty;
if (ptsOffset == TimeSpan.Zero)
{
options += "+initial_discontinuity";
}
if (audioFormat == AudioFormat.AacLatm)
{
options += "+latm";
}
if (!string.IsNullOrWhiteSpace(options))
{
hlsSegmentOptions = $"mpegts_flags={options}";
}
}
string videoPath = _localFileSystem.GetCustomOrDefaultFile( string videoPath = _localFileSystem.GetCustomOrDefaultFile(
FileSystemLayout.ResourcesCacheFolder, FileSystemLayout.ResourcesCacheFolder,
"background.png"); "background.png");
@ -802,6 +751,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
HardwareAccelerationMode hwAccel = GetHardwareAccelerationMode(playbackSettings); HardwareAccelerationMode hwAccel = GetHardwareAccelerationMode(playbackSettings);
_logger.LogDebug("HW accel mode: {HwAccel}", hwAccel); _logger.LogDebug("HW accel mode: {HwAccel}", hwAccel);
var hlsOptions = GetHlsOptions(channel, now, ptsOffset, audioFormat);
var ffmpegState = new FFmpegState( var ffmpegState = new FFmpegState(
channel.Number == FileSystemLayout.TranscodeTroubleshootingChannel, channel.Number == FileSystemLayout.TranscodeTroubleshootingChannel,
HardwareAccelerationMode.None, // no hw accel decode since errors loop HardwareAccelerationMode.None, // no hw accel decode since errors loop
@ -816,11 +767,11 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
None, None,
None, None,
None, None,
outputFormat, hlsOptions.OutputFormat,
hlsPlaylistPath, hlsOptions.HlsPlaylistPath,
hlsSegmentTemplate, hlsOptions.HlsSegmentTemplate,
hlsInitTemplate, hlsOptions.HlsInitTemplate,
hlsSegmentOptions, hlsOptions.HlsSegmentOptions,
ptsOffset, ptsOffset,
Option<int>.None, Option<int>.None,
qsvExtraHardwareFrames, qsvExtraHardwareFrames,
@ -870,7 +821,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
bool hlsRealtime, bool hlsRealtime,
TimeSpan ptsOffset) TimeSpan ptsOffset)
{ {
FFmpegPlaybackSettings playbackSettings = FFmpegPlaybackSettingsCalculator.CalculateErrorSettings( FFmpegPlaybackSettings playbackSettings = FFmpegPlaybackSettingsCalculator.CalculateGeneratedImageSettings(
channel.StreamingMode, channel.StreamingMode,
channel.FFmpegProfile, channel.FFmpegProfile,
hlsRealtime); hlsRealtime);
@ -911,70 +862,13 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
? FFmpegFilterMode.HardwareIfPossible ? FFmpegFilterMode.HardwareIfPossible
: FFmpegFilterMode.Software, : FFmpegFilterMode.Software,
IsAnamorphic: false, IsAnamorphic: false,
playbackSettings.FrameRate, Option<FrameRate>.None,
playbackSettings.VideoBitrate, playbackSettings.VideoBitrate,
playbackSettings.VideoBufferSize, playbackSettings.VideoBufferSize,
playbackSettings.VideoTrackTimeScale, playbackSettings.VideoTrackTimeScale,
playbackSettings.NormalizeColors, playbackSettings.NormalizeColors,
playbackSettings.Deinterlace); playbackSettings.Deinterlace);
OutputFormatKind outputFormat = OutputFormatKind.MpegTs;
switch (channel.StreamingMode)
{
case StreamingMode.HttpLiveStreamingSegmenter:
outputFormat = OutputFormatKind.Hls;
break;
}
Option<string> hlsPlaylistPath = outputFormat is OutputFormatKind.Hls or OutputFormatKind.HlsMp4
? Path.Combine(FileSystemLayout.TranscodeFolder, channel.Number, "live.m3u8")
: Option<string>.None;
long nowSeconds = now.ToUnixTimeSeconds();
Option<string> hlsSegmentTemplate = outputFormat switch
{
OutputFormatKind.Hls => Path.Combine(FileSystemLayout.TranscodeFolder, channel.Number, "live%06d.ts"),
OutputFormatKind.HlsMp4 => Path.Combine(
FileSystemLayout.TranscodeFolder,
channel.Number,
$"live_{nowSeconds}_%06d.m4s"),
_ => Option<string>.None
};
Option<string> hlsInitTemplate = outputFormat switch
{
OutputFormatKind.HlsMp4 => $"{nowSeconds}_init.mp4",
_ => Option<string>.None
};
Option<string> hlsSegmentOptions = Option<string>.None;
if (outputFormat is OutputFormatKind.Hls)
{
string options = string.Empty;
if (ptsOffset == TimeSpan.Zero)
{
options += "+initial_discontinuity";
}
if (audioFormat == AudioFormat.AacLatm)
{
options += "+latm";
}
if (!string.IsNullOrWhiteSpace(options))
{
hlsSegmentOptions = $"mpegts_flags={options}";
}
}
string videoPath = _localFileSystem.GetCustomOrDefaultFile(
FileSystemLayout.ResourcesCacheFolder,
"background.png");
var videoVersion = BackgroundImageMediaVersion.ForPath(videoPath, desiredResolution);
var frameRate = playbackSettings.FrameRate.IfNone(new FrameRate("24")); var frameRate = playbackSettings.FrameRate.IfNone(new FrameRate("24"));
var ffmpegVideoStream = new VideoStream( var ffmpegVideoStream = new VideoStream(
@ -983,19 +877,21 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
string.Empty, string.Empty,
new PixelFormatUnknown(), // leave this unknown so we convert to desired yuv420p new PixelFormatUnknown(), // leave this unknown so we convert to desired yuv420p
ColorParams.Default, ColorParams.Default,
new FrameSize(videoVersion.Width, videoVersion.Height), desiredState.PaddedSize,
videoVersion.SampleAspectRatio, MaybeSampleAspectRatio: "1:1",
videoVersion.DisplayAspectRatio, DisplayAspectRatio: string.Empty,
frameRate, frameRate,
true, true,
ScanKind.Progressive); ScanKind.Progressive);
var videoInputFile = new LavfiInputFile( var videoInputFile = new LavfiInputFile(
$"color=c=black:s={videoVersion.Width}x{videoVersion.Height}:r={frameRate.FrameRateString}:d={duration.TotalSeconds}", $"color=c=black:s={desiredState.PaddedSize.Width}x{desiredState.PaddedSize.Height}:r={frameRate.FrameRateString}:d={duration.TotalSeconds}",
ffmpegVideoStream); ffmpegVideoStream);
HardwareAccelerationMode hwAccel = GetHardwareAccelerationMode(playbackSettings); HardwareAccelerationMode hwAccel = GetHardwareAccelerationMode(playbackSettings);
var hlsOptions = GetHlsOptions(channel, now, ptsOffset, audioFormat);
var ffmpegState = new FFmpegState( var ffmpegState = new FFmpegState(
channel.Number == FileSystemLayout.TranscodeTroubleshootingChannel, channel.Number == FileSystemLayout.TranscodeTroubleshootingChannel,
HardwareAccelerationMode.None, // no hw accel decode since errors loop HardwareAccelerationMode.None, // no hw accel decode since errors loop
@ -1010,11 +906,11 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
None, None,
None, None,
None, None,
outputFormat, hlsOptions.OutputFormat,
hlsPlaylistPath, hlsOptions.HlsPlaylistPath,
hlsSegmentTemplate, hlsOptions.HlsSegmentTemplate,
hlsInitTemplate, hlsOptions.HlsInitTemplate,
hlsSegmentOptions, hlsOptions.HlsSegmentOptions,
ptsOffset, ptsOffset,
Option<int>.None, Option<int>.None,
Optional(channel.FFmpegProfile.QsvExtraHardwareFrames), Optional(channel.FFmpegProfile.QsvExtraHardwareFrames),
@ -1445,4 +1341,67 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
return false; return false;
} }
private static HlsOptions GetHlsOptions(Channel channel, DateTimeOffset now, TimeSpan ptsOffset, string audioFormat)
{
OutputFormatKind outputFormat = OutputFormatKind.MpegTs;
switch (channel.StreamingMode)
{
case StreamingMode.HttpLiveStreamingSegmenter:
outputFormat = OutputFormatKind.Hls;
break;
}
Option<string> hlsPlaylistPath = outputFormat is OutputFormatKind.Hls or OutputFormatKind.HlsMp4
? Path.Combine(FileSystemLayout.TranscodeFolder, channel.Number, "live.m3u8")
: Option<string>.None;
long nowSeconds = now.ToUnixTimeSeconds();
Option<string> hlsSegmentTemplate = outputFormat switch
{
OutputFormatKind.Hls => Path.Combine(FileSystemLayout.TranscodeFolder, channel.Number, "live%06d.ts"),
OutputFormatKind.HlsMp4 => Path.Combine(
FileSystemLayout.TranscodeFolder,
channel.Number,
$"live_{nowSeconds}_%06d.m4s"),
_ => Option<string>.None
};
Option<string> hlsInitTemplate = outputFormat switch
{
OutputFormatKind.HlsMp4 => $"{nowSeconds}_init.mp4",
_ => Option<string>.None
};
Option<string> hlsSegmentOptions = Option<string>.None;
if (outputFormat is OutputFormatKind.Hls)
{
string options = string.Empty;
if (ptsOffset == TimeSpan.Zero)
{
options += "+initial_discontinuity";
}
if (audioFormat == AudioFormat.AacLatm)
{
options += "+latm";
}
if (!string.IsNullOrWhiteSpace(options))
{
hlsSegmentOptions = $"mpegts_flags={options}";
}
}
return new HlsOptions(outputFormat, hlsPlaylistPath, hlsSegmentTemplate, hlsInitTemplate, hlsSegmentOptions);
}
private sealed record HlsOptions(
OutputFormatKind OutputFormat,
Option<string> HlsPlaylistPath,
Option<string> HlsSegmentTemplate,
Option<string> HlsInitTemplate,
Option<string> HlsSegmentOptions);
} }

2
ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs

@ -181,7 +181,7 @@ public static class FFmpegPlaybackSettingsCalculator
return result; return result;
} }
public static FFmpegPlaybackSettings CalculateErrorSettings( public static FFmpegPlaybackSettings CalculateGeneratedImageSettings(
StreamingMode streamingMode, StreamingMode streamingMode,
FFmpegProfile ffmpegProfile, FFmpegProfile ffmpegProfile,
bool hlsRealtime) => bool hlsRealtime) =>

2
ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs

@ -71,7 +71,7 @@ public class FFmpegProcessService
} }
FFmpegPlaybackSettings playbackSettings = FFmpegPlaybackSettings playbackSettings =
FFmpegPlaybackSettingsCalculator.CalculateErrorSettings( FFmpegPlaybackSettingsCalculator.CalculateGeneratedImageSettings(
StreamingMode.TransportStream, StreamingMode.TransportStream,
channel.FFmpegProfile, channel.FFmpegProfile,
false); false);

Loading…
Cancel
Save