diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 5f6047e0d..c6ea91d69 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -301,42 +301,73 @@ namespace MediaBrowser.Api.Playback /// The state. /// The video codec. /// System.String. - protected string GetVideoQualityParam(StreamState state, string videoCodec) + protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls) { - // webm - if (videoCodec.Equals("libvpx", StringComparison.OrdinalIgnoreCase)) - { - // http://www.webmproject.org/docs/encoder-parameters/ - return "-speed 16 -quality good -profile:v 0 -slices 8 -crf 18"; - } + var param = string.Empty; - // asf/wmv - if (videoCodec.Equals("wmv2", StringComparison.OrdinalIgnoreCase)) - { - return "-qmin 2"; - } - - if (videoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) { switch (GetQualitySetting()) { case EncodingQuality.HighSpeed: - return "-preset ultrafast -crf 18"; + param = "-preset ultrafast -crf 18"; + break; case EncodingQuality.HighQuality: - return "-preset superfast -crf 18"; + param = "-preset superfast -crf 18"; + break; case EncodingQuality.MaxQuality: - return "-preset superfast -crf 18"; - default: - throw new Exception("Unrecognized MediaEncodingQuality value."); + param = "-preset superfast -crf 18"; + break; } } - if (videoCodec.Equals("mpeg4", StringComparison.OrdinalIgnoreCase)) + // webm + else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { - return "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; + // http://www.webmproject.org/docs/encoder-parameters/ + param = "-speed 16 -quality good -profile:v 0 -slices 8 -crf 18"; } - return string.Empty; + else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase)) + { + param = "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; + } + + // asf/wmv + else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase)) + { + param = "-qmin 2"; + } + + else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + { + param = "-mbd 2"; + } + + param += GetVideoBitrateParam(state, videoCodec, isHls); + + var framerate = GetFramerateParam(state); + if (framerate.HasValue) + { + param += string.Format(" -r {0}", framerate.Value.ToString(UsCulture)); + } + + if (!string.IsNullOrEmpty(state.VideoSync)) + { + param += " -vsync " + state.VideoSync; + } + + if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) + { + param += " -profile:v " + state.VideoRequest.Profile; + } + + if (!string.IsNullOrEmpty(state.VideoRequest.Level)) + { + param += " -level " + state.VideoRequest.Level; + } + + return param; } protected string GetAudioFilterParam(StreamState state, bool isHls) @@ -723,7 +754,7 @@ namespace MediaBrowser.Api.Playback } if (codec == VideoCodecs.Wmv) { - return "wmv2"; + return "msmpeg4"; } if (codec == VideoCodecs.Theora) { @@ -899,11 +930,40 @@ namespace MediaBrowser.Api.Playback } } - protected int? GetVideoBitrateParam(StreamState state) + protected int? GetVideoBitrateParamValue(StreamState state) { return state.VideoRequest.VideoBitRate; } + protected string GetVideoBitrateParam(StreamState state, string videoCodec, bool isHls) + { + var bitrate = GetVideoBitrateParamValue(state); + + if (bitrate.HasValue) + { + if (isHls) + { + return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); + } + + // With vpx when crf is used, b:v becomes a max rate + // https://trac.ffmpeg.org/wiki/vpxEncodingGuide + if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) + { + return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + } + if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + { + return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + } + return string.Format(" -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); + } + + return string.Empty; + } + protected int? GetAudioBitrateParam(StreamState state) { if (state.Request.AudioBitRate.HasValue) @@ -1180,7 +1240,7 @@ namespace MediaBrowser.Api.Playback var probeSize = GetProbeSizeArgument(state.MediaPath, state.IsInputVideo, state.VideoType, state.IsoType); inputModifier += " " + probeSize; inputModifier = inputModifier.Trim(); - + inputModifier += " " + GetUserAgentParam(state.MediaPath); inputModifier = inputModifier.Trim(); diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 736d2122d..35a418ba7 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -172,7 +172,7 @@ namespace MediaBrowser.Api.Playback.Hls protected void GetPlaylistBitrates(StreamState state, out int audioBitrate, out int videoBitrate) { var audioBitrateParam = GetAudioBitrateParam(state); - var videoBitrateParam = GetVideoBitrateParam(state); + var videoBitrateParam = GetVideoBitrateParamValue(state); if (!audioBitrateParam.HasValue) { diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 388339f17..e04fc3b14 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -299,14 +299,7 @@ namespace MediaBrowser.Api.Playback.Hls (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1); - var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264") + keyFrameArg; - - var bitrate = GetVideoBitrateParam(state); - - if (bitrate.HasValue) - { - args += string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); - } + var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg; // Add resolution params, if specified if (!hasGraphicalSubs) @@ -317,27 +310,6 @@ namespace MediaBrowser.Api.Playback.Hls } } - var framerate = GetFramerateParam(state); - if (framerate.HasValue) - { - args += string.Format(" -r {0}", framerate.Value.ToString(UsCulture)); - } - - if (!string.IsNullOrEmpty(state.VideoSync)) - { - args += " -vsync " + state.VideoSync; - } - - if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) - { - args += " -profile:v " + state.VideoRequest.Profile; - } - - if (!string.IsNullOrEmpty(state.VideoRequest.Level)) - { - args += " -level " + state.VideoRequest.Level; - } - // This is for internal graphical subs if (hasGraphicalSubs) { diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 9d9c62a28..4fdcc8472 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -176,14 +176,7 @@ namespace MediaBrowser.Api.Playback.Hls (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1); - var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264") + keyFrameArg; - - var bitrate = GetVideoBitrateParam(state); - - if (bitrate.HasValue) - { - args += string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); - } + var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg; // Add resolution params, if specified if (!hasGraphicalSubs) @@ -194,27 +187,6 @@ namespace MediaBrowser.Api.Playback.Hls } } - var framerate = GetFramerateParam(state); - if (framerate.HasValue) - { - args += string.Format(" -r {0}", framerate.Value.ToString(UsCulture)); - } - - if (!string.IsNullOrEmpty(state.VideoSync)) - { - args += " -vsync " + state.VideoSync; - } - - if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) - { - args += " -profile:v " + state.VideoRequest.Profile; - } - - if (!string.IsNullOrEmpty(state.VideoRequest.Level)) - { - args += " -level " + state.VideoRequest.Level; - } - // This is for internal graphical subs if (hasGraphicalSubs) { diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index b16761595..916f99a10 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -156,50 +156,13 @@ namespace MediaBrowser.Api.Playback.Progressive } } - var framerate = GetFramerateParam(state); - if (framerate.HasValue) - { - args += string.Format(" -r {0}", framerate.Value.ToString(UsCulture)); - } - - var qualityParam = GetVideoQualityParam(state, codec); - - var bitrate = GetVideoBitrateParam(state); - - if (bitrate.HasValue) - { - if (string.Equals(codec, "libvpx", StringComparison.OrdinalIgnoreCase)) - { - qualityParam += string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); - } - else - { - qualityParam += string.Format(" -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); - } - } + var qualityParam = GetVideoQualityParam(state, codec, false); if (!string.IsNullOrEmpty(qualityParam)) { args += " " + qualityParam.Trim(); } - if (!string.IsNullOrEmpty(state.VideoSync)) - { - args += " -vsync " + state.VideoSync; - } - - if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) - { - args += " -profile:v " + state.VideoRequest.Profile; - } - - if (!string.IsNullOrEmpty(state.VideoRequest.Level)) - { - args += " -level " + state.VideoRequest.Level; - } - // This is for internal graphical subs if (hasGraphicalSubs) {