diff options
Diffstat (limited to 'MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs')
| -rw-r--r-- | MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs | 179 |
1 files changed, 104 insertions, 75 deletions
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 9cdc4a7bf..27072efe1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -66,38 +67,56 @@ namespace MediaBrowser.MediaEncoding.Encoder ? mediaSources.First() : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId)); - AttachMediaStreamInfo(state, mediaSource, options); + var videoRequest = state.Options; - state.OutputAudioBitrate = GetAudioBitrateParam(request, state.AudioStream); + AttachMediaSourceInfo(state, mediaSource, videoRequest); + + //var container = Path.GetExtension(state.RequestedUrl); + + //if (string.IsNullOrEmpty(container)) + //{ + // container = request.Static ? + // state.InputContainer : + // (Path.GetExtension(GetOutputFilePath(state)) ?? string.Empty).TrimStart('.'); + //} + + //state.OutputContainer = (container ?? string.Empty).TrimStart('.'); + + state.OutputAudioBitrate = GetAudioBitrateParam(state.Options, state.AudioStream); state.OutputAudioSampleRate = request.AudioSampleRate; - state.OutputAudioCodec = GetAudioCodec(request); + state.OutputAudioCodec = state.Options.AudioCodec; - state.OutputAudioChannels = GetNumAudioChannelsParam(request, state.AudioStream, state.OutputAudioCodec); + state.OutputAudioChannels = GetNumAudioChannelsParam(state.Options, state.AudioStream, state.OutputAudioCodec); - if (isVideoRequest) + if (videoRequest != null) { - state.OutputVideoCodec = GetVideoCodec(request); - state.OutputVideoBitrate = GetVideoBitrateParamValue(request, state.VideoStream); + state.OutputVideoCodec = state.Options.VideoCodec; + state.OutputVideoBitrate = GetVideoBitrateParamValue(state.Options, state.VideoStream); if (state.OutputVideoBitrate.HasValue) { var resolution = ResolutionNormalizer.Normalize( - state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, - state.OutputVideoBitrate.Value, - state.VideoStream == null ? null : state.VideoStream.Codec, + state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, + state.OutputVideoBitrate.Value, + state.VideoStream == null ? null : state.VideoStream.Codec, state.OutputVideoCodec, - request.MaxWidth, - request.MaxHeight); + videoRequest.MaxWidth, + videoRequest.MaxHeight); - request.MaxWidth = resolution.MaxWidth; - request.MaxHeight = resolution.MaxHeight; + videoRequest.MaxWidth = resolution.MaxWidth; + videoRequest.MaxHeight = resolution.MaxHeight; } } ApplyDeviceProfileSettings(state); - TryStreamCopy(state, request); + if (videoRequest != null) + { + TryStreamCopy(state, videoRequest); + } + + //state.OutputFilePath = GetOutputFilePath(state); return state; } @@ -119,7 +138,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - internal static void AttachMediaStreamInfo(EncodingJob state, + internal static void AttachMediaSourceInfo(EncodingJob state, MediaSourceInfo mediaSource, EncodingJobOptions videoRequest) { @@ -131,11 +150,6 @@ namespace MediaBrowser.MediaEncoding.Encoder state.RunTimeTicks = mediaSource.RunTimeTicks; state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; - if (mediaSource.ReadAtNativeFramerate) - { - state.ReadInputAtNativeFramerate = true; - } - if (mediaSource.VideoType.HasValue) { state.VideoType = mediaSource.VideoType.Value; @@ -156,6 +170,7 @@ namespace MediaBrowser.MediaEncoding.Encoder state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; state.InputBitrate = mediaSource.Bitrate; state.InputFileSize = mediaSource.Size; + state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; if (state.ReadInputAtNativeFramerate || mediaSource.Protocol == MediaProtocol.File && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase)) @@ -165,6 +180,12 @@ namespace MediaBrowser.MediaEncoding.Encoder state.InputAudioSync = "1"; } + if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase)) + { + // Seeing some stuttering when transcoding wma to audio-only HLS + state.InputAudioSync = "1"; + } + var mediaStreams = mediaSource.MediaStreams; if (videoRequest != null) @@ -210,19 +231,21 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <returns>System.Nullable{VideoCodecs}.</returns> private static string InferVideoCodec(string container) { - if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase)) + var ext = "." + (container ?? string.Empty); + + if (string.Equals(ext, ".asf", StringComparison.OrdinalIgnoreCase)) { return "wmv"; } - if (string.Equals(container, "webm", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { return "vpx"; } - if (string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ogv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) { return "theora"; } - if (string.Equals(container, "m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ts", StringComparison.OrdinalIgnoreCase)) { return "h264"; } @@ -232,35 +255,37 @@ namespace MediaBrowser.MediaEncoding.Encoder private string InferAudioCodec(string container) { - if (string.Equals(container, "mp3", StringComparison.OrdinalIgnoreCase)) + var ext = "." + (container ?? string.Empty); + + if (string.Equals(ext, ".mp3", StringComparison.OrdinalIgnoreCase)) { return "mp3"; } - if (string.Equals(container, "aac", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".aac", StringComparison.OrdinalIgnoreCase)) { return "aac"; } - if (string.Equals(container, "wma", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".wma", StringComparison.OrdinalIgnoreCase)) { return "wma"; } - if (string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "oga", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".oga", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "ogv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "webm", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "webma", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".webma", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } @@ -398,15 +423,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (bitrate.HasValue) { - var hasFixedResolution = state.Options.HasFixedResolution; - if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { - if (hasFixedResolution) - { - return string.Format(" -minrate:v ({0}*.90) -maxrate:v ({0}*1.10) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture)); - } - // With vpx when crf is used, b:v becomes a max rate // https://trac.ffmpeg.org/wiki/vpxEncodingGuide. But higher bitrate source files -b:v causes judder so limite the bitrate but dont allow it to "saturate" the bitrate. So dont contrain it down just up. return string.Format(" -maxrate:v {0} -bufsize:v ({0}*2) -b:v {0}", bitrate.Value.ToString(UsCulture)); @@ -417,20 +435,15 @@ namespace MediaBrowser.MediaEncoding.Encoder return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } - // H264 - if (hasFixedResolution) + // h264 + if (isHls) { - if (isHls) - { - return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); - } - - return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); } - return string.Format(" -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); + return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } return string.Empty; @@ -466,11 +479,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Gets the name of the output audio codec /// </summary> - /// <param name="request">The request.</param> + /// <param name="state">The state.</param> /// <returns>System.String.</returns> - private string GetAudioCodec(EncodingJobOptions request) + internal static string GetAudioEncoder(EncodingJob state) { - var codec = request.AudioCodec; + var codec = state.OutputAudioCodec; if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase)) { @@ -489,40 +502,56 @@ namespace MediaBrowser.MediaEncoding.Encoder return "wmav2"; } - return (codec ?? string.Empty).ToLower(); + return codec.ToLower(); } /// <summary> /// Gets the name of the output video codec /// </summary> - /// <param name="request">The request.</param> + /// <param name="state">The state.</param> + /// <param name="options">The options.</param> /// <returns>System.String.</returns> - private string GetVideoCodec(EncodingJobOptions request) + internal static string GetVideoEncoder(EncodingJob state, EncodingOptions options) { - var codec = request.VideoCodec; + var codec = state.OutputVideoCodec; - if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(codec)) { - return "libx264"; - } - if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) - { - return "libx265"; - } - if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) - { - return "libvpx"; - } - if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) - { - return "wmv2"; + if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) + { + return GetH264Encoder(state, options); + } + if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) + { + return "libvpx"; + } + if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) + { + return "wmv2"; + } + if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase)) + { + return "libtheora"; + } + + return codec.ToLower(); } - if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase)) + + return "copy"; + } + + internal static string GetH264Encoder(EncodingJob state, EncodingOptions options) + { + if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - return "libtheora"; + // It's currently failing on live tv + if (state.RunTimeTicks.HasValue) + { + return "h264_qsv"; + } } - return (codec ?? string.Empty).ToLower(); + return "libx264"; } internal static bool CanStreamCopyVideo(EncodingJobOptions request, MediaStream videoStream) |
