From 78bbb1cf8fddb90787017639e04ba216bba09b2f Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Wed, 15 Aug 2012 22:42:37 -0400 Subject: [PATCH] Added resolution params to the video handler --- MediaBrowser.Api/HttpHandlers/VideoHandler.cs | 140 ++++++++++++++++-- MediaBrowser.Api/ImageProcessor.cs | 74 +-------- MediaBrowser.Common/Drawing/DrawingUtils.cs | 81 ++++++++++ .../MediaBrowser.Common.csproj | 2 + 4 files changed, 219 insertions(+), 78 deletions(-) create mode 100644 MediaBrowser.Common/Drawing/DrawingUtils.cs diff --git a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs index 32ba45ede..7fe82ef0c 100644 --- a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Model.Entities; +using System.Drawing; +using MediaBrowser.Common.Drawing; namespace MediaBrowser.Api.HttpHandlers { @@ -41,12 +43,16 @@ namespace MediaBrowser.Api.HttpHandlers return true; } + if (RequiresVideoConversion()) + { + return true; + } + AudioStream audio = LibraryItem.AudioStreams.FirstOrDefault(); if (audio != null) { - // If the number of channels is greater than our desired channels, we need to transcode - if (AudioChannels.HasValue && AudioChannels.Value < audio.Channels) + if (RequiresAudioConversion(audio)) { return true; } @@ -100,6 +106,16 @@ namespace MediaBrowser.Api.HttpHandlers string args = "-vcodec " + codec; + if (!codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) + { + if (Width.HasValue || Height.HasValue || MaxHeight.HasValue || MaxWidth.HasValue) + { + Size size = DrawingUtils.Resize(LibraryItem.Width, LibraryItem.Height, Width, Height, MaxWidth, MaxHeight); + + args += string.Format(" -s {0}x{1}", size.Width, size.Height); + } + } + return args; } @@ -157,6 +173,11 @@ namespace MediaBrowser.Api.HttpHandlers return "libtheora"; } + if (!RequiresVideoConversion()) + { + return "copy"; + } + return "libx264"; } @@ -181,7 +202,7 @@ namespace MediaBrowser.Api.HttpHandlers } // See if we can just copy the stream - if (HasBasicAudio(audioStream)) + if (!RequiresAudioConversion(audioStream)) { return "copy"; } @@ -208,30 +229,131 @@ namespace MediaBrowser.Api.HttpHandlers return GetNumAudioChannelsParam(libraryItemChannels); } - private bool HasBasicAudio(AudioStream audio) + private bool RequiresVideoConversion() + { + // Check dimensions + if (Width.HasValue) + { + if (Width.Value != LibraryItem.Width) + { + return true; + } + } + if (Height.HasValue) + { + if (Height.Value != LibraryItem.Height) + { + return true; + } + } + if (MaxWidth.HasValue) + { + if (MaxWidth.Value < LibraryItem.Width) + { + return true; + } + } + if (MaxHeight.HasValue) + { + if (MaxHeight.Value < LibraryItem.Height) + { + return true; + } + } + + if (LibraryItem.VideoCodec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 || LibraryItem.VideoCodec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1) + { + return false; + } + + return false; + } + + private bool RequiresAudioConversion(AudioStream audio) { if (AudioChannels.HasValue) { if (audio.Channels > AudioChannels.Value) { - return false; + return true; } } if (audio.AudioFormat.IndexOf("aac", StringComparison.OrdinalIgnoreCase) != -1) { - return true; + return false; } if (audio.AudioFormat.IndexOf("ac-3", StringComparison.OrdinalIgnoreCase) != -1 || audio.AudioFormat.IndexOf("ac3", StringComparison.OrdinalIgnoreCase) != -1) { - return true; + return false; } if (audio.AudioFormat.IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1 || audio.AudioFormat.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1) { - return true; + return false; } - return false; + return true; } + + private int? Height + { + get + { + string val = QueryString["height"]; + + if (string.IsNullOrEmpty(val)) + { + return null; + } + + return int.Parse(val); + } + } + + private int? Width + { + get + { + string val = QueryString["width"]; + + if (string.IsNullOrEmpty(val)) + { + return null; + } + + return int.Parse(val); + } + } + + private int? MaxHeight + { + get + { + string val = QueryString["maxheight"]; + + if (string.IsNullOrEmpty(val)) + { + return null; + } + + return int.Parse(val); + } + } + + private int? MaxWidth + { + get + { + string val = QueryString["maxwidth"]; + + if (string.IsNullOrEmpty(val)) + { + return null; + } + + return int.Parse(val); + } + } + } } diff --git a/MediaBrowser.Api/ImageProcessor.cs b/MediaBrowser.Api/ImageProcessor.cs index 014f65598..c4a2fdb69 100644 --- a/MediaBrowser.Api/ImageProcessor.cs +++ b/MediaBrowser.Api/ImageProcessor.cs @@ -3,6 +3,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; +using MediaBrowser.Common.Drawing; namespace MediaBrowser.Api { @@ -12,40 +13,9 @@ namespace MediaBrowser.Api { Image originalImage = Image.FromStream(sourceImageStream); - var newWidth = originalImage.Width; - var newHeight = originalImage.Height; + Size newSize = DrawingUtils.Resize(originalImage.Size, width, height, maxWidth, maxHeight); - if (width.HasValue && height.HasValue) - { - newWidth = width.Value; - newHeight = height.Value; - } - - else if (height.HasValue) - { - newWidth = GetNewWidth(newHeight, newWidth, height.Value); - newHeight = height.Value; - } - - else if (width.HasValue) - { - newHeight = GetNewHeight(newHeight, newWidth, width.Value); - newWidth = width.Value; - } - - if (maxHeight.HasValue && maxHeight < newHeight) - { - newWidth = GetNewWidth(newHeight, newWidth, maxHeight.Value); - newHeight = maxHeight.Value; - } - - if (maxWidth.HasValue && maxWidth < newWidth) - { - newHeight = GetNewHeight(newHeight, newWidth, maxWidth.Value); - newWidth = maxWidth.Value; - } - - Bitmap thumbnail = new Bitmap(newWidth, newHeight, originalImage.PixelFormat); + Bitmap thumbnail = new Bitmap(newSize.Width, newSize.Height, originalImage.PixelFormat); thumbnail.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution); Graphics thumbnailGraph = Graphics.FromImage(thumbnail); @@ -55,7 +25,7 @@ namespace MediaBrowser.Api thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality; thumbnailGraph.CompositingMode = CompositingMode.SourceOver; - thumbnailGraph.DrawImage(originalImage, 0, 0, newWidth, newHeight); + thumbnailGraph.DrawImage(originalImage, 0, 0, newSize.Width, newSize.Height); Write(originalImage, thumbnail, toStream, quality); @@ -74,7 +44,7 @@ namespace MediaBrowser.Api } else if (ImageFormat.Png.Equals(originalImage.RawFormat)) { - SavePng(newImage, toStream); + newImage.Save(toStream, ImageFormat.Png); } else { @@ -96,22 +66,6 @@ namespace MediaBrowser.Api } } - private static void SavePng(Image newImage, Stream target) - { - if (target.CanSeek) - { - newImage.Save(target, ImageFormat.Png); - } - else - { - using (MemoryStream ms = new MemoryStream(4096)) - { - newImage.Save(ms, ImageFormat.Png); - ms.WriteTo(target); - } - } - } - private static ImageCodecInfo GetImageCodeInfo(string mimeType) { ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders(); @@ -126,23 +80,5 @@ namespace MediaBrowser.Api } return info[1]; } - - private static int GetNewWidth(int currentHeight, int currentWidth, int newHeight) - { - decimal scaleFactor = newHeight; - scaleFactor /= currentHeight; - scaleFactor *= currentWidth; - - return Convert.ToInt32(scaleFactor); - } - - private static int GetNewHeight(int currentHeight, int currentWidth, int newWidth) - { - decimal scaleFactor = newWidth; - scaleFactor /= currentWidth; - scaleFactor *= currentHeight; - - return Convert.ToInt32(scaleFactor); - } } } diff --git a/MediaBrowser.Common/Drawing/DrawingUtils.cs b/MediaBrowser.Common/Drawing/DrawingUtils.cs new file mode 100644 index 000000000..4c0b5c207 --- /dev/null +++ b/MediaBrowser.Common/Drawing/DrawingUtils.cs @@ -0,0 +1,81 @@ +using System; +using System.Drawing; + +namespace MediaBrowser.Common.Drawing +{ + public static class DrawingUtils + { + /// + /// Resizes a set of dimensions + /// + public static Size Resize(int currentWidth, int currentHeight, int? width, int? height, int? maxWidth, int? maxHeight) + { + return Resize(new Size(currentWidth, currentHeight), width, height, maxWidth, maxHeight); + } + + /// + /// Resizes a set of dimensions + /// + /// The original size object + /// A new fixed width, if desired + /// A new fixed neight, if desired + /// A max fixed width, if desired + /// A max fixed height, if desired + /// A new size object + public static Size Resize(Size size, int? width, int? height, int? maxWidth, int? maxHeight) + { + decimal newWidth = size.Width; + decimal newHeight = size.Height; + + if (width.HasValue && height.HasValue) + { + newWidth = width.Value; + newHeight = height.Value; + } + + else if (height.HasValue) + { + newWidth = GetNewWidth(newHeight, newWidth, height.Value); + newHeight = height.Value; + } + + else if (width.HasValue) + { + newHeight = GetNewHeight(newHeight, newWidth, width.Value); + newWidth = width.Value; + } + + if (maxHeight.HasValue && maxHeight < newHeight) + { + newWidth = GetNewWidth(newHeight, newWidth, maxHeight.Value); + newHeight = maxHeight.Value; + } + + if (maxWidth.HasValue && maxWidth < newWidth) + { + newHeight = GetNewHeight(newHeight, newWidth, maxWidth.Value); + newWidth = maxWidth.Value; + } + + return new Size(Convert.ToInt32(newWidth), Convert.ToInt32(newHeight)); + } + + private static decimal GetNewWidth(decimal currentHeight, decimal currentWidth, int newHeight) + { + decimal scaleFactor = newHeight; + scaleFactor /= currentHeight; + scaleFactor *= currentWidth; + + return scaleFactor; + } + + private static decimal GetNewHeight(decimal currentHeight, decimal currentWidth, int newWidth) + { + decimal scaleFactor = newWidth; + scaleFactor /= currentWidth; + scaleFactor *= currentHeight; + + return scaleFactor; + } + } +} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 25a855c38..bd3a58c04 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -41,6 +41,7 @@ + False ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll @@ -57,6 +58,7 @@ +