aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.MediaEncoding/Encoder
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.MediaEncoding/Encoder')
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs37
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs58
2 files changed, 47 insertions, 48 deletions
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
index 5683de169f..f4e8c39c11 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
@@ -123,6 +123,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
"tonemap_opencl",
"overlay_opencl",
"transpose_opencl",
+ "yadif_opencl",
+ "bwdif_opencl",
// vaapi
"scale_vaapi",
"deinterlace_vaapi",
@@ -150,15 +152,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
"overlay_rkrga"
];
- private static readonly Dictionary<int, string[]> _filterOptionsDict = new Dictionary<int, string[]>
+ private static readonly Dictionary<FilterOptionType, (string, string)> _filterOptionsDict = new Dictionary<FilterOptionType, (string, string)>
{
- { 0, new string[] { "scale_cuda", "format" } },
- { 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } },
- { 2, new string[] { "tonemap_opencl", "bt2390" } },
- { 3, new string[] { "overlay_opencl", "Action to take when encountering EOF from secondary input" } },
- { 4, new string[] { "overlay_vaapi", "Action to take when encountering EOF from secondary input" } },
- { 5, new string[] { "overlay_vulkan", "Action to take when encountering EOF from secondary input" } },
- { 6, new string[] { "transpose_opencl", "rotate by half-turn" } }
+ { FilterOptionType.ScaleCudaFormat, ("scale_cuda", "format") },
+ { FilterOptionType.TonemapCudaName, ("tonemap_cuda", "GPU accelerated HDR to SDR tonemapping") },
+ { FilterOptionType.TonemapOpenclBt2390, ("tonemap_opencl", "bt2390") },
+ { FilterOptionType.OverlayOpenclFrameSync, ("overlay_opencl", "Action to take when encountering EOF from secondary input") },
+ { FilterOptionType.OverlayVaapiFrameSync, ("overlay_vaapi", "Action to take when encountering EOF from secondary input") },
+ { FilterOptionType.OverlayVulkanFrameSync, ("overlay_vulkan", "Action to take when encountering EOF from secondary input") },
+ { FilterOptionType.TransposeOpenclReversal, ("transpose_opencl", "rotate by half-turn") },
+ { FilterOptionType.OverlayOpenclAlphaFormat, ("overlay_opencl", "alpha_format") },
+ { FilterOptionType.OverlayCudaAlphaFormat, ("overlay_cuda", "alpha_format") }
};
private static readonly Dictionary<BitStreamFilterOptionType, (string, string)> _bsfOptionsDict = new Dictionary<BitStreamFilterOptionType, (string, string)>
@@ -294,7 +298,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
public IEnumerable<string> GetFilters() => GetFFmpegFilters();
- public IDictionary<int, bool> GetFiltersWithOption() => GetFFmpegFiltersWithOption();
+ public IDictionary<FilterOptionType, bool> GetFiltersWithOption() => _filterOptionsDict
+ .ToDictionary(item => item.Key, item => CheckFilterWithOption(item.Value.Item1, item.Value.Item2));
public IDictionary<BitStreamFilterOptionType, bool> GetBitStreamFiltersWithOption() => _bsfOptionsDict
.ToDictionary(item => item.Key, item => CheckBitStreamFilterWithOption(item.Value.Item1, item.Value.Item2));
@@ -628,20 +633,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
return found;
}
- private Dictionary<int, bool> GetFFmpegFiltersWithOption()
- {
- Dictionary<int, bool> dict = new Dictionary<int, bool>();
- for (int i = 0; i < _filterOptionsDict.Count; i++)
- {
- if (_filterOptionsDict.TryGetValue(i, out var val) && val.Length == 2)
- {
- dict.Add(i, CheckFilterWithOption(val[0], val[1]));
- }
- }
-
- return dict;
- }
-
private string GetProcessOutput(string path, string arguments, bool readStdErr, string? testKey)
{
var redirectStandardIn = !string.IsNullOrEmpty(testKey);
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 2c57cf8710..237b537bc3 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -72,7 +72,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
private List<string> _decoders = new List<string>();
private List<string> _hwaccels = new List<string>();
private List<string> _filters = new List<string>();
- private IDictionary<int, bool> _filtersWithOption = new Dictionary<int, bool>();
+ private IDictionary<FilterOptionType, bool> _filtersWithOption = new Dictionary<FilterOptionType, bool>();
private IDictionary<BitStreamFilterOptionType, bool> _bitStreamFiltersWithOption = new Dictionary<BitStreamFilterOptionType, bool>();
private bool _isPkeyPauseSupported = false;
@@ -341,7 +341,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
_filters = list.ToList();
}
- public void SetAvailableFiltersWithOption(IDictionary<int, bool> dict)
+ public void SetAvailableFiltersWithOption(IDictionary<FilterOptionType, bool> dict)
{
_filtersWithOption = dict;
}
@@ -383,12 +383,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <inheritdoc />
public bool SupportsFilterWithOption(FilterOptionType option)
{
- if (_filtersWithOption.TryGetValue((int)option, out var val))
- {
- return val;
- }
-
- return false;
+ return _filtersWithOption.TryGetValue(option, out var val) && val;
}
public bool SupportsBitStreamFilterWithOption(BitStreamFilterOptionType option)
@@ -542,7 +537,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
EnableRaisingEvents = true
};
- _logger.LogInformation("Starting {ProcessFileName} with args {ProcessArgs}", _ffprobePath, args);
+ _logger.LogDebug("Starting {ProcessFileName} with args {ProcessArgs}", _ffprobePath, args);
var memoryStream = new MemoryStream();
await using (memoryStream.ConfigureAwait(false))
@@ -642,7 +637,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
catch (Exception ex)
{
- _logger.LogError(ex, "I-frame image extraction failed, will attempt standard way. Input: {Arguments}", inputArgument);
+ _logger.LogWarning(ex, "I-frame image extraction failed, will attempt standard way. Input: {Arguments}", inputArgument);
}
}
@@ -737,12 +732,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
var peak = videoStream.VideoRangeType == VideoRangeType.DOVI ? "400" : "100";
enableHdrExtraction = true;
- filters.Add($"tonemapx=tonemap=bt2390:desat=0:peak={peak}:t=bt709:m=bt709:p=bt709:format=yuv420p");
+ filters.Add($"tonemapx=tonemap=bt2390:desat=0:peak={peak}:t=bt709:m=bt709:p=bt709:format=yuv420p:range=full");
}
else if (SupportsFilter("zscale") && videoStream.VideoRangeType != VideoRangeType.DOVI)
{
enableHdrExtraction = true;
- filters.Add("zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0:peak=100,zscale=t=bt709:m=bt709,format=yuv420p");
+ filters.Add("zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0:peak=100,zscale=t=bt709:m=bt709:out_range=full,format=yuv420p");
}
}
@@ -756,7 +751,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
_threads,
vf,
isAudio ? string.Empty : GetImageResolutionParameter(),
- EncodingHelper.GetVideoSyncOption("-1", EncoderVersion).Trim(), // auto decide fps mode
+ EncodingHelper.GetVideoSyncOption("-1", EncoderVersion), // auto decide fps mode
tempExtractPath);
if (offset.HasValue)
@@ -767,7 +762,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
// The mpegts demuxer cannot seek to keyframes, so we have to let the
// decoder discard non-keyframes, which may contain corrupted images.
var seekMpegTs = offset.HasValue && string.Equals("mpegts", container, StringComparison.OrdinalIgnoreCase);
- if ((useIFrame && useTradeoff) || seekMpegTs)
+ if (useIFrame && (useTradeoff || seekMpegTs))
{
args = "-skip_frame nokey " + args;
}
@@ -832,7 +827,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
/// <inheritdoc />
- public Task<string> ExtractVideoImagesOnIntervalAccelerated(
+ public async Task<string> ExtractVideoImagesOnIntervalAccelerated(
string inputFile,
string container,
MediaSourceInfo mediaSource,
@@ -923,18 +918,34 @@ namespace MediaBrowser.MediaEncoding.Encoder
inputArg = "-hwaccel_flags +low_priority " + inputArg;
}
- if (enableKeyFrameOnlyExtraction)
- {
- inputArg = "-skip_frame nokey " + inputArg;
- }
-
var filterParam = encodingHelper.GetVideoProcessingFilterParam(jobState, options, vidEncoder).Trim();
if (string.IsNullOrWhiteSpace(filterParam))
{
throw new InvalidOperationException("EncodingHelper returned empty or invalid filter parameters.");
}
- return ExtractVideoImagesOnIntervalInternal(inputArg, filterParam, vidEncoder, threads, qualityScale, priority, cancellationToken);
+ try
+ {
+ return await ExtractVideoImagesOnIntervalInternal(
+ (enableKeyFrameOnlyExtraction ? "-skip_frame nokey " : string.Empty) + inputArg,
+ filterParam,
+ vidEncoder,
+ threads,
+ qualityScale,
+ priority,
+ cancellationToken).ConfigureAwait(false);
+ }
+ catch (FfmpegException ex)
+ {
+ if (!enableKeyFrameOnlyExtraction)
+ {
+ throw;
+ }
+
+ _logger.LogWarning(ex, "I-frame trickplay extraction failed, will attempt standard way. Input: {InputFile}", inputFile);
+ }
+
+ return await ExtractVideoImagesOnIntervalInternal(inputArg, filterParam, vidEncoder, threads, qualityScale, priority, cancellationToken).ConfigureAwait(false);
}
private async Task<string> ExtractVideoImagesOnIntervalInternal(
@@ -1076,11 +1087,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
}
- var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
-
- if (exitCode == -1)
+ if (!ranToCompletion || processWrapper.ExitCode != 0)
{
- _logger.LogError("ffmpeg image extraction failed for {ProcessDescription}", processDescription);
// Cleanup temp folder here, because the targetDirectory is not returned and the cleanup for failed ffmpeg process is not possible for caller.
// Ideally the ffmpeg should not write any files if it fails, but it seems like it is not guaranteed.
try