diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 36207c8b47..39c9285545 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1,12 +1,11 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; +using CommonIO; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -23,7 +22,6 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using CommonIO; namespace MediaBrowser.Api.Playback { @@ -518,18 +516,20 @@ protected string GetOutputSizeParam(StreamState state, filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam)); } - // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size + // Fit the video into the specified bounds while ensuring upscaling only occurs in one dimension else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue) { var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + // picks the highest resolution that will fit within the max/min boundaries that only causes upscaling in one or other dimension filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); } // If a fixed width was requested else if (request.Width.HasValue) { + // currently assumes Width < MaxWidth and ignores any MaxHeight var widthParam = request.Width.Value.ToString(UsCulture); filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam)); @@ -538,6 +538,7 @@ protected string GetOutputSizeParam(StreamState state, // If a fixed height was requested else if (request.Height.HasValue) { + // currently assume Height < MaxHeight and ignores and MaxWidth var heightParam = request.Height.Value.ToString(UsCulture); filters.Add(string.Format("scale=trunc(oh*a*2)/2:{0}", heightParam)); @@ -548,7 +549,7 @@ protected string GetOutputSizeParam(StreamState state, { var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); - filters.Add(string.Format("scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam)); + filters.Add(string.Format("scale=min(max(iw\\,ih*dar)\\,{0}):trunc(ow/dar/2)*2", maxWidthParam)); } // If a max height was requested @@ -556,7 +557,7 @@ protected string GetOutputSizeParam(StreamState state, { var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam)); + filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam)); } if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) @@ -1167,6 +1168,9 @@ private void ParseLogLine(string line, TranscodingJob transcodingJob, StreamStat isUpscaling = true; } + if (videoStream.IsAnamorphic.HasValue && videoStream.IsAnamorphic.Value) + isUpscaling = true; + // Don't allow bitrate increases unless upscaling if (!isUpscaling) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ddcd48b8b0..0e85f4a245 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -187,8 +187,45 @@ private MediaStream GetMediaStream(bool isAudio, MediaStreamInfo streamInfo, Med // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase); - // http://stackoverflow.com/questions/17353387/how-to-detect-anamorphic-video-with-ffprobe - stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase); + if (string.Equals(streamInfo.sample_aspect_ratio, "1:1", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAnamorphic = false; + } + else if (!((string.IsNullOrWhiteSpace(streamInfo.sample_aspect_ratio) || string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)))) + { + stream.IsAnamorphic = true; + } + else if (string.IsNullOrWhiteSpace(streamInfo.display_aspect_ratio) || string.Equals(streamInfo.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAnamorphic = false; + } + else + { + var ratioParts = streamInfo.display_aspect_ratio.Split(':'); + if (ratioParts.Length != 2) + { + stream.IsAnamorphic = false; + } + else + { + int ratio0; + int ratio1; + if (!Int32.TryParse(ratioParts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out ratio0)) + { + stream.IsAnamorphic = false; + } + else if (!Int32.TryParse(ratioParts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out ratio1)) + { + stream.IsAnamorphic = false; + } + else + { + // allow up to 2% difference between stated display aspect and the calculated ratio + stream.IsAnamorphic = (Math.Abs((streamInfo.width * ratio1) - (streamInfo.height * ratio0)) * 100.0f) / Math.Max((streamInfo.height * ratio0), (streamInfo.width * ratio1)) > 2; + } + } + } + if (streamInfo.refs > 0) { diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index e107ea9f13..fb80311e9f 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -534,7 +534,7 @@ private bool IsFileLocked(string path) try { - using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) + using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (_updateTimer != null) {