Merge pull request #6414 from richlander/mediabrowser-controller-mediaencoding
This commit is contained in:
commit
f83a5bb08e
|
@ -10,6 +10,15 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
{
|
{
|
||||||
public class BaseEncodingJobOptions
|
public class BaseEncodingJobOptions
|
||||||
{
|
{
|
||||||
|
public BaseEncodingJobOptions()
|
||||||
|
{
|
||||||
|
EnableAutoStreamCopy = true;
|
||||||
|
AllowVideoStreamCopy = true;
|
||||||
|
AllowAudioStreamCopy = true;
|
||||||
|
Context = EncodingContext.Streaming;
|
||||||
|
StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the id.
|
/// Gets or sets the id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -191,14 +200,5 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseEncodingJobOptions()
|
|
||||||
{
|
|
||||||
EnableAutoStreamCopy = true;
|
|
||||||
AllowVideoStreamCopy = true;
|
|
||||||
AllowAudioStreamCopy = true;
|
|
||||||
Context = EncodingContext.Streaming;
|
|
||||||
StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -161,6 +161,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name of the output video codec.
|
/// Gets the name of the output video codec.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encording state.</param>
|
||||||
|
/// <param name="encodingOptions">Encoding options.</param>
|
||||||
|
/// <returns>Encoder string.</returns>
|
||||||
public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions)
|
public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions)
|
||||||
{
|
{
|
||||||
var codec = state.OutputVideoCodec;
|
var codec = state.OutputVideoCodec;
|
||||||
|
@ -315,6 +318,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets decoder from a codec.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codec">Codec to use.</param>
|
||||||
|
/// <returns>Decoder string.</returns>
|
||||||
public string GetDecoderFromCodec(string codec)
|
public string GetDecoderFromCodec(string codec)
|
||||||
{
|
{
|
||||||
// For these need to find out the ffmpeg names
|
// For these need to find out the ffmpeg names
|
||||||
|
@ -344,6 +352,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Infers the audio codec based on the url.
|
/// Infers the audio codec based on the url.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="container">Container to use.</param>
|
||||||
|
/// <returns>Codec string.</returns>
|
||||||
public string InferAudioCodec(string container)
|
public string InferAudioCodec(string container)
|
||||||
{
|
{
|
||||||
var ext = "." + (container ?? string.Empty);
|
var ext = "." + (container ?? string.Empty);
|
||||||
|
@ -489,6 +499,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the input argument.
|
/// Gets the input argument.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="encodingOptions">Encoding options.</param>
|
||||||
|
/// <returns>Input arguments.</returns>
|
||||||
public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions)
|
public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions)
|
||||||
{
|
{
|
||||||
var arg = new StringBuilder();
|
var arg = new StringBuilder();
|
||||||
|
@ -965,6 +978,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the video bitrate to specify on the command line.
|
/// Gets the video bitrate to specify on the command line.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="videoEncoder">Video encoder to use.</param>
|
||||||
|
/// <param name="encodingOptions">Encoding options.</param>
|
||||||
|
/// <param name="defaultPreset">Default present to use for encoding.</param>
|
||||||
|
/// <returns>Video bitrate.</returns>
|
||||||
public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset)
|
public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset)
|
||||||
{
|
{
|
||||||
var param = string.Empty;
|
var param = string.Empty;
|
||||||
|
@ -1966,8 +1984,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the graphical subtitle param.
|
/// Gets the graphical subtitle parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="options">Encoding options.</param>
|
||||||
|
/// <param name="outputVideoCodec">Video codec to use.</param>
|
||||||
|
/// <returns>Graphical subtitle parameter.</returns>
|
||||||
public string GetGraphicalSubtitleParam(
|
public string GetGraphicalSubtitleParam(
|
||||||
EncodingJobInfo state,
|
EncodingJobInfo state,
|
||||||
EncodingOptions options,
|
EncodingOptions options,
|
||||||
|
@ -2485,6 +2507,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return string.Format(CultureInfo.InvariantCulture, filter, widthParam, heightParam);
|
return string.Format(CultureInfo.InvariantCulture, filter, widthParam, heightParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the output size parameter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="options">Encoding options.</param>
|
||||||
|
/// <param name="outputVideoCodec">Video codec to use.</param>
|
||||||
|
/// <returns>The output size parameter.</returns>
|
||||||
public string GetOutputSizeParam(
|
public string GetOutputSizeParam(
|
||||||
EncodingJobInfo state,
|
EncodingJobInfo state,
|
||||||
EncodingOptions options,
|
EncodingOptions options,
|
||||||
|
@ -2495,8 +2524,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Gets the output size parameter.
|
||||||
/// If we're going to put a fixed size on the command line, this will calculate it.
|
/// If we're going to put a fixed size on the command line, this will calculate it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="options">Encoding options.</param>
|
||||||
|
/// <param name="outputVideoCodec">Video codec to use.</param>
|
||||||
|
/// <returns>The output size parameter.</returns>
|
||||||
public string GetOutputSizeParamInternal(
|
public string GetOutputSizeParamInternal(
|
||||||
EncodingJobInfo state,
|
EncodingJobInfo state,
|
||||||
EncodingOptions options,
|
EncodingOptions options,
|
||||||
|
@ -2908,6 +2942,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the number of threads.
|
/// Gets the number of threads.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="encodingOptions">Encoding options.</param>
|
||||||
|
/// <param name="outputVideoCodec">Video codec to use.</param>
|
||||||
|
/// <returns>Number of threads.</returns>
|
||||||
#nullable enable
|
#nullable enable
|
||||||
public static int GetNumberOfThreads(EncodingJobInfo? state, EncodingOptions encodingOptions, string? outputVideoCodec)
|
public static int GetNumberOfThreads(EncodingJobInfo? state, EncodingOptions encodingOptions, string? outputVideoCodec)
|
||||||
{
|
{
|
||||||
|
@ -3551,6 +3589,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a hw decoder name.
|
/// Gets a hw decoder name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="options">Encoding options.</param>
|
||||||
|
/// <param name="decoder">Decoder to use.</param>
|
||||||
|
/// <param name="videoCodec">Video codec to use.</param>
|
||||||
|
/// <param name="isColorDepth10">Specifies if color depth 10.</param>
|
||||||
|
/// <returns>Hardware decoder name.</returns>
|
||||||
public string GetHwDecoderName(EncodingOptions options, string decoder, string videoCodec, bool isColorDepth10)
|
public string GetHwDecoderName(EncodingOptions options, string decoder, string videoCodec, bool isColorDepth10)
|
||||||
{
|
{
|
||||||
var isCodecAvailable = _mediaEncoder.SupportsDecoder(decoder) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase);
|
var isCodecAvailable = _mediaEncoder.SupportsDecoder(decoder) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase);
|
||||||
|
@ -3569,6 +3612,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a hwaccel type to use as a hardware decoder(dxva/vaapi) depending on the system.
|
/// Gets a hwaccel type to use as a hardware decoder(dxva/vaapi) depending on the system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Encoding state.</param>
|
||||||
|
/// <param name="options">Encoding options.</param>
|
||||||
|
/// <param name="videoCodec">Video codec to use.</param>
|
||||||
|
/// <param name="isColorDepth10">Specifies if color depth 10.</param>
|
||||||
|
/// <returns>Hardware accelerator type.</returns>
|
||||||
public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec, bool isColorDepth10)
|
public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec, bool isColorDepth10)
|
||||||
{
|
{
|
||||||
var isWindows = OperatingSystem.IsWindows();
|
var isWindows = OperatingSystem.IsWindows();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591, SA1401
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -20,6 +20,44 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
// For now, a common base class until the API and MediaEncoding classes are unified
|
// For now, a common base class until the API and MediaEncoding classes are unified
|
||||||
public class EncodingJobInfo
|
public class EncodingJobInfo
|
||||||
{
|
{
|
||||||
|
public int? OutputAudioBitrate;
|
||||||
|
public int? OutputAudioChannels;
|
||||||
|
|
||||||
|
private TranscodeReason[] _transcodeReasons = null;
|
||||||
|
|
||||||
|
public EncodingJobInfo(TranscodingJobType jobType)
|
||||||
|
{
|
||||||
|
TranscodingType = jobType;
|
||||||
|
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
SupportedAudioCodecs = Array.Empty<string>();
|
||||||
|
SupportedVideoCodecs = Array.Empty<string>();
|
||||||
|
SupportedSubtitleCodecs = Array.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TranscodeReason[] TranscodeReasons
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_transcodeReasons == null)
|
||||||
|
{
|
||||||
|
if (BaseRequest.TranscodeReasons == null)
|
||||||
|
{
|
||||||
|
return Array.Empty<TranscodeReason>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_transcodeReasons = BaseRequest.TranscodeReasons
|
||||||
|
.Split(',')
|
||||||
|
.Where(i => !string.IsNullOrEmpty(i))
|
||||||
|
.Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _transcodeReasons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProgress<double> Progress { get; set; }
|
||||||
|
|
||||||
public MediaStream VideoStream { get; set; }
|
public MediaStream VideoStream { get; set; }
|
||||||
|
|
||||||
public VideoType VideoType { get; set; }
|
public VideoType VideoType { get; set; }
|
||||||
|
@ -58,40 +96,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
public string MimeType { get; set; }
|
public string MimeType { get; set; }
|
||||||
|
|
||||||
public string GetMimeType(string outputPath, bool enableStreamDefault = true)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(MimeType))
|
|
||||||
{
|
|
||||||
return MimeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MimeTypes.GetMimeType(outputPath, enableStreamDefault);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TranscodeReason[] _transcodeReasons = null;
|
|
||||||
|
|
||||||
public TranscodeReason[] TranscodeReasons
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_transcodeReasons == null)
|
|
||||||
{
|
|
||||||
if (BaseRequest.TranscodeReasons == null)
|
|
||||||
{
|
|
||||||
return Array.Empty<TranscodeReason>();
|
|
||||||
}
|
|
||||||
|
|
||||||
_transcodeReasons = BaseRequest.TranscodeReasons
|
|
||||||
.Split(',')
|
|
||||||
.Where(i => !string.IsNullOrEmpty(i))
|
|
||||||
.Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _transcodeReasons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IgnoreInputDts => MediaSource.IgnoreDts;
|
public bool IgnoreInputDts => MediaSource.IgnoreDts;
|
||||||
|
|
||||||
public bool IgnoreInputIndex => MediaSource.IgnoreIndex;
|
public bool IgnoreInputIndex => MediaSource.IgnoreIndex;
|
||||||
|
@ -144,196 +148,17 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
public BaseEncodingJobOptions BaseRequest { get; set; }
|
public BaseEncodingJobOptions BaseRequest { get; set; }
|
||||||
|
|
||||||
public long? StartTimeTicks => BaseRequest.StartTimeTicks;
|
|
||||||
|
|
||||||
public bool CopyTimestamps => BaseRequest.CopyTimestamps;
|
|
||||||
|
|
||||||
public int? OutputAudioBitrate;
|
|
||||||
public int? OutputAudioChannels;
|
|
||||||
|
|
||||||
public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
|
|
||||||
{
|
|
||||||
var videoStream = VideoStream;
|
|
||||||
var isInputInterlaced = videoStream != null && videoStream.IsInterlaced;
|
|
||||||
|
|
||||||
if (!isInputInterlaced)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Support general param
|
|
||||||
if (BaseRequest.DeInterlace)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(videoCodec))
|
|
||||||
{
|
|
||||||
if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetRequestedProfiles(string codec)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(BaseRequest.Profile))
|
|
||||||
{
|
|
||||||
return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
var profile = BaseRequest.GetOption(codec, "profile");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profile))
|
|
||||||
{
|
|
||||||
return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.Empty<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetRequestedLevel(string codec)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(BaseRequest.Level))
|
|
||||||
{
|
|
||||||
return BaseRequest.Level;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
return BaseRequest.GetOption(codec, "level");
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? GetRequestedMaxRefFrames(string codec)
|
|
||||||
{
|
|
||||||
if (BaseRequest.MaxRefFrames.HasValue)
|
|
||||||
{
|
|
||||||
return BaseRequest.MaxRefFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
var value = BaseRequest.GetOption(codec, "maxrefframes");
|
|
||||||
if (!string.IsNullOrEmpty(value)
|
|
||||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? GetRequestedVideoBitDepth(string codec)
|
|
||||||
{
|
|
||||||
if (BaseRequest.MaxVideoBitDepth.HasValue)
|
|
||||||
{
|
|
||||||
return BaseRequest.MaxVideoBitDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
var value = BaseRequest.GetOption(codec, "videobitdepth");
|
|
||||||
if (!string.IsNullOrEmpty(value)
|
|
||||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? GetRequestedAudioBitDepth(string codec)
|
|
||||||
{
|
|
||||||
if (BaseRequest.MaxAudioBitDepth.HasValue)
|
|
||||||
{
|
|
||||||
return BaseRequest.MaxAudioBitDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
var value = BaseRequest.GetOption(codec, "audiobitdepth");
|
|
||||||
if (!string.IsNullOrEmpty(value)
|
|
||||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? GetRequestedAudioChannels(string codec)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
var value = BaseRequest.GetOption(codec, "audiochannels");
|
|
||||||
if (!string.IsNullOrEmpty(value)
|
|
||||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BaseRequest.MaxAudioChannels.HasValue)
|
|
||||||
{
|
|
||||||
return BaseRequest.MaxAudioChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BaseRequest.AudioChannels.HasValue)
|
|
||||||
{
|
|
||||||
return BaseRequest.AudioChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BaseRequest.TranscodingMaxAudioChannels.HasValue)
|
|
||||||
{
|
|
||||||
return BaseRequest.TranscodingMaxAudioChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsVideoRequest { get; set; }
|
public bool IsVideoRequest { get; set; }
|
||||||
|
|
||||||
public TranscodingJobType TranscodingType { get; set; }
|
public TranscodingJobType TranscodingType { get; set; }
|
||||||
|
|
||||||
public EncodingJobInfo(TranscodingJobType jobType)
|
public long? StartTimeTicks => BaseRequest.StartTimeTicks;
|
||||||
{
|
|
||||||
TranscodingType = jobType;
|
public bool CopyTimestamps => BaseRequest.CopyTimestamps;
|
||||||
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
SupportedAudioCodecs = Array.Empty<string>();
|
|
||||||
SupportedVideoCodecs = Array.Empty<string>();
|
|
||||||
SupportedSubtitleCodecs = Array.Empty<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSegmentedLiveStream
|
public bool IsSegmentedLiveStream
|
||||||
=> TranscodingType != TranscodingJobType.Progressive && !RunTimeTicks.HasValue;
|
=> TranscodingType != TranscodingJobType.Progressive && !RunTimeTicks.HasValue;
|
||||||
|
|
||||||
public bool EnableBreakOnNonKeyFrames(string videoCodec)
|
|
||||||
{
|
|
||||||
if (TranscodingType != TranscodingJobType.Progressive)
|
|
||||||
{
|
|
||||||
if (IsSegmentedLiveStream)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BaseRequest.BreakOnNonKeyFrames && EncodingHelper.IsCopyCodec(videoCodec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? TotalOutputBitrate => (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0);
|
public int? TotalOutputBitrate => (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0);
|
||||||
|
|
||||||
public int? OutputWidth
|
public int? OutputWidth
|
||||||
|
@ -682,6 +507,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
public int HlsListSize => 0;
|
public int HlsListSize => 0;
|
||||||
|
|
||||||
|
public bool EnableBreakOnNonKeyFrames(string videoCodec)
|
||||||
|
{
|
||||||
|
if (TranscodingType != TranscodingJobType.Progressive)
|
||||||
|
{
|
||||||
|
if (IsSegmentedLiveStream)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BaseRequest.BreakOnNonKeyFrames && EncodingHelper.IsCopyCodec(videoCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private int? GetMediaStreamCount(MediaStreamType type, int limit)
|
private int? GetMediaStreamCount(MediaStreamType type, int limit)
|
||||||
{
|
{
|
||||||
var count = MediaSource.GetStreamCount(type);
|
var count = MediaSource.GetStreamCount(type);
|
||||||
|
@ -694,7 +534,167 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IProgress<double> Progress { get; set; }
|
public string GetMimeType(string outputPath, bool enableStreamDefault = true)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(MimeType))
|
||||||
|
{
|
||||||
|
return MimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MimeTypes.GetMimeType(outputPath, enableStreamDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
|
||||||
|
{
|
||||||
|
var videoStream = VideoStream;
|
||||||
|
var isInputInterlaced = videoStream != null && videoStream.IsInterlaced;
|
||||||
|
|
||||||
|
if (!isInputInterlaced)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support general param
|
||||||
|
if (BaseRequest.DeInterlace)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(videoCodec))
|
||||||
|
{
|
||||||
|
if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetRequestedProfiles(string codec)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(BaseRequest.Profile))
|
||||||
|
{
|
||||||
|
return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var profile = BaseRequest.GetOption(codec, "profile");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(profile))
|
||||||
|
{
|
||||||
|
return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetRequestedLevel(string codec)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(BaseRequest.Level))
|
||||||
|
{
|
||||||
|
return BaseRequest.Level;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
return BaseRequest.GetOption(codec, "level");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetRequestedMaxRefFrames(string codec)
|
||||||
|
{
|
||||||
|
if (BaseRequest.MaxRefFrames.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.MaxRefFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var value = BaseRequest.GetOption(codec, "maxrefframes");
|
||||||
|
if (!string.IsNullOrEmpty(value)
|
||||||
|
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetRequestedVideoBitDepth(string codec)
|
||||||
|
{
|
||||||
|
if (BaseRequest.MaxVideoBitDepth.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.MaxVideoBitDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var value = BaseRequest.GetOption(codec, "videobitdepth");
|
||||||
|
if (!string.IsNullOrEmpty(value)
|
||||||
|
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetRequestedAudioBitDepth(string codec)
|
||||||
|
{
|
||||||
|
if (BaseRequest.MaxAudioBitDepth.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.MaxAudioBitDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var value = BaseRequest.GetOption(codec, "audiobitdepth");
|
||||||
|
if (!string.IsNullOrEmpty(value)
|
||||||
|
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetRequestedAudioChannels(string codec)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var value = BaseRequest.GetOption(codec, "audiochannels");
|
||||||
|
if (!string.IsNullOrEmpty(value)
|
||||||
|
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BaseRequest.MaxAudioChannels.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.MaxAudioChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BaseRequest.AudioChannels.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.AudioChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BaseRequest.TranscodingMaxAudioChannels.HasValue)
|
||||||
|
{
|
||||||
|
return BaseRequest.TranscodingMaxAudioChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
public virtual void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refreshes the chapter images.
|
/// Refreshes the chapter images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="video">Video to use.</param>
|
||||||
|
/// <param name="directoryService">Directory service to use.</param>
|
||||||
|
/// <param name="chapters">Set of chapters to refresh.</param>
|
||||||
|
/// <param name="extractImages">Option to extract images.</param>
|
||||||
|
/// <param name="saveChapters">Option to save chapters.</param>
|
||||||
|
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
|
||||||
|
/// <returns><c>true</c> if successful, <c>false</c> if not.</returns>
|
||||||
Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
|
Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,13 +71,42 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracts the video image.
|
/// Extracts the video image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="inputFile">Input file.</param>
|
||||||
|
/// <param name="container">Video container type.</param>
|
||||||
|
/// <param name="mediaSource">Media source information.</param>
|
||||||
|
/// <param name="videoStream">Media stream information.</param>
|
||||||
|
/// <param name="threedFormat">Video 3D format.</param>
|
||||||
|
/// <param name="offset">Time offset.</param>
|
||||||
|
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
|
||||||
|
/// <returns>Location of video image.</returns>
|
||||||
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
|
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extracts the video image.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputFile">Input file.</param>
|
||||||
|
/// <param name="container">Video container type.</param>
|
||||||
|
/// <param name="mediaSource">Media source information.</param>
|
||||||
|
/// <param name="imageStream">Media stream information.</param>
|
||||||
|
/// <param name="imageStreamIndex">Index of the stream to extract from.</param>
|
||||||
|
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
|
||||||
|
/// <returns>Location of video image.</returns>
|
||||||
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken);
|
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracts the video images on interval.
|
/// Extracts the video images on interval.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="inputFile">Input file.</param>
|
||||||
|
/// <param name="container">Video container type.</param>
|
||||||
|
/// <param name="videoStream">Media stream information.</param>
|
||||||
|
/// <param name="mediaSource">Media source information.</param>
|
||||||
|
/// <param name="threedFormat">Video 3D format.</param>
|
||||||
|
/// <param name="interval">Time interval.</param>
|
||||||
|
/// <param name="targetDirectory">Directory to write images.</param>
|
||||||
|
/// <param name="filenamePrefix">Filename prefix to use.</param>
|
||||||
|
/// <param name="maxWidth">Maximum width of image.</param>
|
||||||
|
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
|
||||||
|
/// <returns>A task.</returns>
|
||||||
Task ExtractVideoImagesOnInterval(
|
Task ExtractVideoImagesOnInterval(
|
||||||
string inputFile,
|
string inputFile,
|
||||||
string container,
|
string container,
|
||||||
|
@ -122,10 +151,24 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string EscapeSubtitleFilterPath(string path);
|
string EscapeSubtitleFilterPath(string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the path to find FFmpeg.
|
||||||
|
/// </summary>
|
||||||
void SetFFmpegPath();
|
void SetFFmpegPath();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the encoder path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path.</param>
|
||||||
|
/// <param name="pathType">The type of path.</param>
|
||||||
void UpdateEncoderPath(string path, string pathType);
|
void UpdateEncoderPath(string path, string pathType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the primary playlist of .vob files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The to the .vob files.</param>
|
||||||
|
/// <param name="titleNumber">The title number to start with.</param>
|
||||||
|
/// <returns>A playlist.</returns>
|
||||||
IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, uint? titleNumber);
|
IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, uint? titleNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the subtitles.
|
/// Gets the subtitles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="item">Item to use.</param>
|
||||||
|
/// <param name="mediaSourceId">Media source.</param>
|
||||||
|
/// <param name="subtitleStreamIndex">Subtitle stream to use.</param>
|
||||||
|
/// <param name="outputFormat">Output format to use.</param>
|
||||||
|
/// <param name="startTimeTicks">Start time.</param>
|
||||||
|
/// <param name="endTimeTicks">End time.</param>
|
||||||
|
/// <param name="preserveOriginalTimestamps">Option to preserve original timestamps.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token for the operation.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<Stream> GetSubtitles(
|
Task<Stream> GetSubtitles(
|
||||||
BaseItem item,
|
BaseItem item,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user