aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs')
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs516
1 files changed, 270 insertions, 246 deletions
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index bc0318ad7..17813559a 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -1,12 +1,13 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1401
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
@@ -20,6 +21,42 @@ namespace MediaBrowser.Controller.MediaEncoding
// For now, a common base class until the API and MediaEncoding classes are unified
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.HasValue)
+ {
+ if (BaseRequest.TranscodeReasons is null)
+ {
+ _transcodeReasons = 0;
+ return 0;
+ }
+
+ _ = Enum.TryParse<TranscodeReason>(BaseRequest.TranscodeReasons, out var reason);
+ _transcodeReasons = reason;
+ }
+
+ return _transcodeReasons.Value;
+ }
+ }
+
+ public IProgress<double> Progress { get; set; }
+
public MediaStream VideoStream { get; set; }
public VideoType VideoType { get; set; }
@@ -58,40 +95,6 @@ namespace MediaBrowser.Controller.MediaEncoding
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 IgnoreInputIndex => MediaSource.IgnoreIndex;
@@ -106,23 +109,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public string OutputContainer { get; set; }
- public string OutputVideoSync
- {
- get
- {
- // For live tv + in progress recordings
- if (string.Equals(InputContainer, "mpegts", StringComparison.OrdinalIgnoreCase)
- || string.Equals(InputContainer, "ts", StringComparison.OrdinalIgnoreCase))
- {
- if (!MediaSource.RunTimeTicks.HasValue)
- {
- return "cfr";
- }
- }
-
- return "-1";
- }
- }
+ public string OutputVideoSync { get; set; }
public string AlbumCoverPath { get; set; }
@@ -144,203 +131,24 @@ namespace MediaBrowser.Controller.MediaEncoding
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 TranscodingJobType TranscodingType { get; set; }
- 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 long? StartTimeTicks => BaseRequest.StartTimeTicks;
+
+ public bool CopyTimestamps => BaseRequest.CopyTimestamps;
public bool IsSegmentedLiveStream
=> 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? OutputWidth
{
get
{
- if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
+ if (VideoStream is not null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
{
var size = new ImageDimensions(VideoStream.Width.Value, VideoStream.Height.Value);
@@ -367,7 +175,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
- if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
+ if (VideoStream is not null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
{
var size = new ImageDimensions(VideoStream.Width.Value, VideoStream.Height.Value);
@@ -397,7 +205,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (BaseRequest.Static
|| EncodingHelper.IsCopyCodec(OutputAudioCodec))
{
- if (AudioStream != null)
+ if (AudioStream is not null)
{
return AudioStream.SampleRate;
}
@@ -420,7 +228,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (BaseRequest.Static
|| EncodingHelper.IsCopyCodec(OutputAudioCodec))
{
- if (AudioStream != null)
+ if (AudioStream is not null)
{
return AudioStream.BitDepth;
}
@@ -443,8 +251,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var level = GetRequestedLevel(ActualOutputVideoCodec);
- if (!string.IsNullOrEmpty(level)
- && double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
+ if (double.TryParse(level, CultureInfo.InvariantCulture, out var result))
{
return result;
}
@@ -498,7 +305,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (BaseRequest.Static
|| EncodingHelper.IsCopyCodec(OutputVideoCodec))
{
- return VideoStream == null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
+ return VideoStream is null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
}
return BaseRequest.MaxFramerate ?? BaseRequest.Framerate;
@@ -558,6 +365,27 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
+ /// <summary>
+ /// Gets the target video range type.
+ /// </summary>
+ public VideoRangeType TargetVideoRangeType
+ {
+ get
+ {
+ if (BaseRequest.Static || EncodingHelper.IsCopyCodec(OutputVideoCodec))
+ {
+ return VideoStream?.VideoRangeType ?? VideoRangeType.Unknown;
+ }
+
+ if (Enum.TryParse(GetRequestedRangeTypes(ActualOutputVideoCodec).FirstOrDefault() ?? "Unknown", true, out VideoRangeType requestedRangeType))
+ {
+ return requestedRangeType;
+ }
+
+ return VideoRangeType.Unknown;
+ }
+ }
+
public string TargetVideoCodecTag
{
get
@@ -590,14 +418,14 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
- if (VideoStream == null)
+ if (VideoStream is null)
{
return null;
}
if (EncodingHelper.IsCopyCodec(OutputVideoCodec))
{
- return VideoStream?.Codec;
+ return VideoStream.Codec;
}
return OutputVideoCodec;
@@ -608,14 +436,14 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
- if (AudioStream == null)
+ if (AudioStream is null)
{
return null;
}
if (EncodingHelper.IsCopyCodec(OutputAudioCodec))
{
- return AudioStream?.Codec;
+ return AudioStream.Codec;
}
return OutputAudioCodec;
@@ -682,6 +510,21 @@ namespace MediaBrowser.Controller.MediaEncoding
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)
{
var count = MediaSource.GetStreamCount(type);
@@ -694,7 +537,188 @@ namespace MediaBrowser.Controller.MediaEncoding
return count;
}
- public IProgress<double> Progress { get; set; }
+ public string GetMimeType(string outputPath, bool enableStreamDefault = true)
+ {
+ if (!string.IsNullOrEmpty(MimeType))
+ {
+ return MimeType;
+ }
+
+ if (enableStreamDefault)
+ {
+ return MimeTypes.GetMimeType(outputPath);
+ }
+
+ return MimeTypes.GetMimeType(outputPath, null);
+ }
+
+ public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
+ {
+ var videoStream = VideoStream;
+ var isInputInterlaced = videoStream is not 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;
+ }
+
+ 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[] GetRequestedRangeTypes(string codec)
+ {
+ if (!string.IsNullOrEmpty(BaseRequest.VideoRangeType))
+ {
+ return BaseRequest.VideoRangeType.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ if (!string.IsNullOrEmpty(codec))
+ {
+ var rangetype = BaseRequest.GetOption(codec, "rangetype");
+
+ if (!string.IsNullOrEmpty(rangetype))
+ {
+ return rangetype.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 (int.TryParse(value, 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 (int.TryParse(value, 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 (int.TryParse(value, 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 (int.TryParse(value, 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)
{