|
|
|
@ -171,6 +171,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
string audioFormat = playbackSettings.AudioFormat switch |
|
|
|
string audioFormat = playbackSettings.AudioFormat switch |
|
|
|
{ |
|
|
|
{ |
|
|
|
FFmpegProfileAudioFormat.Aac => AudioFormat.Aac, |
|
|
|
FFmpegProfileAudioFormat.Aac => AudioFormat.Aac, |
|
|
|
|
|
|
|
FFmpegProfileAudioFormat.AacLatm => AudioFormat.AacLatm, |
|
|
|
FFmpegProfileAudioFormat.Ac3 => AudioFormat.Ac3, |
|
|
|
FFmpegProfileAudioFormat.Ac3 => AudioFormat.Ac3, |
|
|
|
FFmpegProfileAudioFormat.Copy => AudioFormat.Copy, |
|
|
|
FFmpegProfileAudioFormat.Copy => AudioFormat.Copy, |
|
|
|
_ => throw new ArgumentOutOfRangeException($"unexpected audio format {playbackSettings.VideoFormat}") |
|
|
|
_ => throw new ArgumentOutOfRangeException($"unexpected audio format {playbackSettings.VideoFormat}") |
|
|
|
@ -403,6 +404,27 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
_ => Option<string>.None |
|
|
|
_ => 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}"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FrameSize scaledSize = ffmpegVideoStream.SquarePixelFrameSize( |
|
|
|
FrameSize scaledSize = ffmpegVideoStream.SquarePixelFrameSize( |
|
|
|
new FrameSize(channel.FFmpegProfile.Resolution.Width, channel.FFmpegProfile.Resolution.Height)); |
|
|
|
new FrameSize(channel.FFmpegProfile.Resolution.Width, channel.FFmpegProfile.Resolution.Height)); |
|
|
|
|
|
|
|
|
|
|
|
@ -506,6 +528,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
hlsPlaylistPath, |
|
|
|
hlsPlaylistPath, |
|
|
|
hlsSegmentTemplate, |
|
|
|
hlsSegmentTemplate, |
|
|
|
hlsInitTemplate, |
|
|
|
hlsInitTemplate, |
|
|
|
|
|
|
|
hlsSegmentOptions, |
|
|
|
ptsOffset, |
|
|
|
ptsOffset, |
|
|
|
playbackSettings.ThreadCount, |
|
|
|
playbackSettings.ThreadCount, |
|
|
|
qsvExtraHardwareFrames, |
|
|
|
qsvExtraHardwareFrames, |
|
|
|
@ -583,6 +606,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
string audioFormat = playbackSettings.AudioFormat switch |
|
|
|
string audioFormat = playbackSettings.AudioFormat switch |
|
|
|
{ |
|
|
|
{ |
|
|
|
FFmpegProfileAudioFormat.Ac3 => AudioFormat.Ac3, |
|
|
|
FFmpegProfileAudioFormat.Ac3 => AudioFormat.Ac3, |
|
|
|
|
|
|
|
FFmpegProfileAudioFormat.AacLatm => AudioFormat.AacLatm, |
|
|
|
_ => AudioFormat.Aac |
|
|
|
_ => AudioFormat.Aac |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
@ -645,6 +669,27 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
_ => Option<string>.None |
|
|
|
_ => 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_options={options}"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
string videoPath = Path.Combine(FileSystemLayout.ResourcesCacheFolder, "background.png"); |
|
|
|
string videoPath = Path.Combine(FileSystemLayout.ResourcesCacheFolder, "background.png"); |
|
|
|
|
|
|
|
|
|
|
|
var videoVersion = BackgroundImageMediaVersion.ForPath(videoPath, desiredResolution); |
|
|
|
var videoVersion = BackgroundImageMediaVersion.ForPath(videoPath, desiredResolution); |
|
|
|
@ -686,6 +731,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
hlsPlaylistPath, |
|
|
|
hlsPlaylistPath, |
|
|
|
hlsSegmentTemplate, |
|
|
|
hlsSegmentTemplate, |
|
|
|
hlsInitTemplate, |
|
|
|
hlsInitTemplate, |
|
|
|
|
|
|
|
hlsSegmentOptions, |
|
|
|
ptsOffset, |
|
|
|
ptsOffset, |
|
|
|
Option<int>.None, |
|
|
|
Option<int>.None, |
|
|
|
qsvExtraHardwareFrames, |
|
|
|
qsvExtraHardwareFrames, |
|
|
|
@ -778,6 +824,11 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService |
|
|
|
$"http://localhost:{Settings.StreamingPort}/iptv/channel/{channel.Number}.m3u8?mode=segmenter{accessTokenQuery}", |
|
|
|
$"http://localhost:{Settings.StreamingPort}/iptv/channel/{channel.Number}.m3u8?mode=segmenter{accessTokenQuery}", |
|
|
|
resolution); |
|
|
|
resolution); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (channel.FFmpegProfile.AudioFormat is FFmpegProfileAudioFormat.AacLatm) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
concatInputFile.AudioFormat = AudioFormat.AacLatm; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
IPipelineBuilder pipelineBuilder = await _pipelineBuilderFactory.GetBuilder( |
|
|
|
IPipelineBuilder pipelineBuilder = await _pipelineBuilderFactory.GetBuilder( |
|
|
|
HardwareAccelerationMode.None, |
|
|
|
HardwareAccelerationMode.None, |
|
|
|
Option<VideoInputFile>.None, |
|
|
|
Option<VideoInputFile>.None, |
|
|
|
|