From b4851d4789be94796b7bf964d5dba26bd2d82388 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Sep 2017 17:36:19 -0400 Subject: separate deinterlacing params by video codec --- .../MediaEncoding/EncodingHelper.cs | 10 ++--- .../MediaEncoding/EncodingJobInfo.cs | 45 +++++++++++++++++++++- .../MediaEncoding/EncodingJobOptions.cs | 33 +++++++++++++++- 3 files changed, 78 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 657b9c9593..642a42c8e2 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -796,12 +796,13 @@ namespace MediaBrowser.Controller.MediaEncoding if (videoStream.IsInterlaced) { - if (request.DeInterlace) + if (state.DeInterlace(videoStream.Codec)) { return false; } } + if (videoStream.IsAnamorphic ?? false) { if (request.RequireNonAnamorphic) @@ -1357,7 +1358,7 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwupload"); } - if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (state.DeInterlace("h264") && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase)) { @@ -1799,11 +1800,6 @@ namespace MediaBrowser.Controller.MediaEncoding state.InternalSubtitleStreamOffset = mediaStreams.Where(i => i.Type == MediaStreamType.Subtitle && !i.IsExternal).ToList().IndexOf(state.SubtitleStream); } - if (state.VideoStream != null && state.VideoStream.IsInterlaced) - { - state.DeInterlace = true; - } - EnforceResolutionLimit(state); NormalizeSubtitleEmbed(state); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index e76217fda6..fb8aa9767a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -160,7 +160,26 @@ namespace MediaBrowser.Controller.MediaEncoding public int? OutputAudioBitrate; public int? OutputAudioChannels; - public bool DeInterlace { get; set; } + + public bool DeInterlace(string videoCodec) + { + // Support general param + if (BaseRequest.DeInterlace) + { + return true; + } + + if (!string.IsNullOrWhiteSpace(videoCodec)) + { + if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + public bool IsVideoRequest { get; set; } public TranscodingJobType TranscodingType { get; set; } @@ -435,6 +454,28 @@ namespace MediaBrowser.Controller.MediaEncoding } } + public string ActualOutputVideoCodec + { + get + { + var codec = OutputVideoCodec; + + if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) + { + var stream = VideoStream; + + if (stream != null) + { + return stream.Codec; + } + + return null; + } + + return codec; + } + } + public bool? IsTargetInterlaced { get @@ -444,7 +485,7 @@ namespace MediaBrowser.Controller.MediaEncoding return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced; } - if (DeInterlace) + if (DeInterlace(ActualOutputVideoCodec)) { return false; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 5fc93bf382..cb675ba689 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -1,4 +1,6 @@ -using System.Globalization; +using System; +using System.Collections.Generic; +using System.Globalization; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; @@ -224,12 +226,41 @@ namespace MediaBrowser.Controller.MediaEncoding public EncodingContext Context { get; set; } + public void SetOption(string qualifier, string name, string value) + { + SetOption(qualifier + "-" + name, value); + } + + public Dictionary StreamOptions { get; private set; } + + public void SetOption(string name, string value) + { + StreamOptions[name] = value; + } + + public string GetOption(string qualifier, string name) + { + return GetOption(qualifier + "-" + name); + } + + public string GetOption(string name) + { + string value; + if (StreamOptions.TryGetValue(name, out value)) + { + return value; + } + + return null; + } + public BaseEncodingJobOptions() { EnableAutoStreamCopy = true; AllowVideoStreamCopy = true; AllowAudioStreamCopy = true; Context = EncodingContext.Streaming; + StreamOptions = new Dictionary(StringComparer.OrdinalIgnoreCase); } } } -- cgit v1.2.3 From 31b01cbb5645cdc71791c85f2607aafbc6568dbc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Sep 2017 16:33:01 -0400 Subject: add fixes for dng images --- Emby.Dlna/Didl/DidlBuilder.cs | 18 +- Emby.Drawing.ImageMagick/ImageMagickEncoder.cs | 2 - Emby.Drawing.Skia/SkiaEncoder.cs | 3 +- Emby.Drawing/ImageProcessor.cs | 161 ++---------------- Emby.Photos/PhotoProvider.cs | 189 ++++++++++++--------- Emby.Server.Implementations/Dto/DtoService.cs | 18 +- .../HttpServer/HttpResultFactory.cs | 16 +- MediaBrowser.Controller/Channels/Channel.cs | 8 + MediaBrowser.Controller/Drawing/IImageProcessor.cs | 2 - MediaBrowser.Controller/Drawing/ImageHelper.cs | 5 - .../Entities/Audio/AudioPodcast.cs | 2 +- .../Entities/BasePluginFolder.cs | 8 + .../Entities/CollectionFolder.cs | 8 + MediaBrowser.Controller/Entities/GameGenre.cs | 5 + MediaBrowser.Controller/Entities/GameSystem.cs | 8 + MediaBrowser.Controller/Entities/Genre.cs | 5 + MediaBrowser.Controller/Entities/Photo.cs | 29 ++++ MediaBrowser.Controller/Entities/PhotoAlbum.cs | 5 + MediaBrowser.Controller/Entities/User.cs | 5 + MediaBrowser.Controller/Entities/UserView.cs | 8 + MediaBrowser.Controller/Entities/Year.cs | 8 + 21 files changed, 236 insertions(+), 277 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 844a6a5ce6..1cb9a24fbc 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -1141,17 +1141,17 @@ namespace Emby.Dlna.Didl int? width = null; int? height = null; - try - { - var size = _imageProcessor.GetImageSize(imageInfo); + //try + //{ + // var size = _imageProcessor.GetImageSize(imageInfo); - width = Convert.ToInt32(size.Width); - height = Convert.ToInt32(size.Height); - } - catch - { + // width = Convert.ToInt32(size.Width); + // height = Convert.ToInt32(size.Height); + //} + //catch + //{ - } + //} var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty) .TrimStart('.') diff --git a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs index 2c40bf570c..24895b483e 100644 --- a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs @@ -148,7 +148,6 @@ namespace Emby.Drawing.ImageMagick } var originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height); - ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize); if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize)) { @@ -182,7 +181,6 @@ namespace Emby.Drawing.ImageMagick using (var originalImage = new MagickWand(inputPath)) { var originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height); - ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize); var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize); diff --git a/Emby.Drawing.Skia/SkiaEncoder.cs b/Emby.Drawing.Skia/SkiaEncoder.cs index eb0602afef..e8cdd441af 100644 --- a/Emby.Drawing.Skia/SkiaEncoder.cs +++ b/Emby.Drawing.Skia/SkiaEncoder.cs @@ -40,7 +40,9 @@ namespace Emby.Drawing.Skia "jpeg", "jpg", "png", + "dng", + "webp", "gif", "bmp", @@ -459,7 +461,6 @@ namespace Emby.Drawing.Skia //_logger.Info("Color type {0}", bitmap.Info.ColorType); var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height); - ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize); if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient) { diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index f5a05db051..8314549725 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -35,11 +35,6 @@ namespace Emby.Drawing /// protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// - /// The _cached imaged sizes - /// - private readonly ConcurrentDictionary _cachedImagedSizes; - /// /// Gets the list of currently registered image processors /// Image processors are specialized metadata providers that run after the normal ones @@ -75,34 +70,7 @@ namespace Emby.Drawing _appPaths = appPaths; ImageEnhancers = new IImageEnhancer[] { }; - _saveImageSizeTimer = timerFactory.Create(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite); ImageHelper.ImageProcessor = this; - - Dictionary sizeDictionary; - - try - { - sizeDictionary = jsonSerializer.DeserializeFromFile>(ImageSizeFile) ?? - new Dictionary(); - } - catch (FileNotFoundException) - { - // No biggie - sizeDictionary = new Dictionary(); - } - catch (IOException) - { - // No biggie - sizeDictionary = new Dictionary(); - } - catch (Exception ex) - { - logger.ErrorException("Error parsing image size cache file", ex); - - sizeDictionary = new Dictionary(); - } - - _cachedImagedSizes = new ConcurrentDictionary(sizeDictionary); } public IImageEncoder ImageEncoder @@ -133,7 +101,6 @@ namespace Emby.Drawing "aiff", "cr2", "crw", - "dng", // Remove until supported //"nef", @@ -275,15 +242,15 @@ namespace Emby.Drawing return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); } - ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified); - if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value) && !autoOrient) - { - // Just spit out the original file if all the options are default - _logger.Info("Returning original image {0}", originalImagePath); - return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); - } + //ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified); + //if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value) && !autoOrient) + //{ + // // Just spit out the original file if all the options are default + // _logger.Info("Returning original image {0}", originalImagePath); + // return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); + //} - var newSize = ImageHelper.GetNewImageSize(options, originalImageSize); + var newSize = ImageHelper.GetNewImageSize(options, null); var quality = options.Quality; var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); @@ -477,98 +444,30 @@ namespace Emby.Drawing public ImageSize GetImageSize(ItemImageInfo info, bool allowSlowMethods) { - return GetImageSize(info.Path, info.DateModified, allowSlowMethods); + return GetImageSize(info.Path, allowSlowMethods); } public ImageSize GetImageSize(ItemImageInfo info) { - return GetImageSize(info.Path, info.DateModified, false); + return GetImageSize(info.Path, false); } public ImageSize GetImageSize(string path) { - return GetImageSize(path, _fileSystem.GetLastWriteTimeUtc(path), false); + return GetImageSize(path, false); } /// /// Gets the size of the image. /// - /// The path. - /// The image date modified. - /// if set to true [allow slow method]. - /// ImageSize. - /// path - private ImageSize GetImageSize(string path, DateTime imageDateModified, bool allowSlowMethod) + private ImageSize GetImageSize(string path, bool allowSlowMethod) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } - ImageSize size; - - var cacheHash = GetImageSizeKey(path, imageDateModified); - - if (!_cachedImagedSizes.TryGetValue(cacheHash, out size)) - { - size = GetImageSizeInternal(path, allowSlowMethod); - - SaveImageSize(size, cacheHash, false); - } - - return size; - } - - public void SaveImageSize(string path, DateTime imageDateModified, ImageSize size) - { - var cacheHash = GetImageSizeKey(path, imageDateModified); - SaveImageSize(size, cacheHash, true); - } - - private void SaveImageSize(ImageSize size, Guid cacheHash, bool checkExists) - { - if (size.Width <= 0 || size.Height <= 0) - { - return; - } - - if (checkExists && _cachedImagedSizes.ContainsKey(cacheHash)) - { - return; - } - - if (checkExists) - { - if (_cachedImagedSizes.TryAdd(cacheHash, size)) - { - StartSaveImageSizeTimer(); - } - } - else - { - StartSaveImageSizeTimer(); - _cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size); - } - } - - private Guid GetImageSizeKey(string path, DateTime imageDateModified) - { - var name = path + "datemodified=" + imageDateModified.Ticks; - return name.GetMD5(); - } - - public ImageSize? GetSavedImageSize(string path, DateTime imageDateModified) - { - ImageSize size; - - var cacheHash = GetImageSizeKey(path, imageDateModified); - - if (_cachedImagedSizes.TryGetValue(cacheHash, out size)) - { - return size; - } - - return null; + return GetImageSizeInternal(path, allowSlowMethod); } /// @@ -619,39 +518,6 @@ namespace Emby.Drawing } } - private readonly ITimer _saveImageSizeTimer; - private const int SaveImageSizeTimeout = 5000; - private readonly object _saveImageSizeLock = new object(); - private void StartSaveImageSizeTimer() - { - _saveImageSizeTimer.Change(SaveImageSizeTimeout, Timeout.Infinite); - } - - private void SaveImageSizeCallback(object state) - { - lock (_saveImageSizeLock) - { - try - { - var path = ImageSizeFile; - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); - _jsonSerializer.SerializeToFile(_cachedImagedSizes, path); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving image size file", ex); - } - } - } - - private string ImageSizeFile - { - get - { - return Path.Combine(_appPaths.DataPath, "imagesizes.json"); - } - } - /// /// Gets the image cache tag. /// @@ -1016,7 +882,6 @@ namespace Emby.Drawing disposable.Dispose(); } - _saveImageSizeTimer.Dispose(); GC.SuppressFinalize(this); } diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index c3c30ab6d1..fe77cff694 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -20,134 +21,152 @@ namespace Emby.Photos { private readonly ILogger _logger; private readonly IFileSystem _fileSystem; + private IImageProcessor _imageProcessor; - public PhotoProvider(ILogger logger, IFileSystem fileSystem) + public PhotoProvider(ILogger logger, IFileSystem fileSystem, IImageProcessor imageProcessor) { _logger = logger; _fileSystem = fileSystem; + _imageProcessor = imageProcessor; } + // These are causing taglib to hang + private string[] _excludeExtensions = new string[] { ".dng" }; + public Task FetchAsync(Photo item, MetadataRefreshOptions options, CancellationToken cancellationToken) { item.SetImagePath(ImageType.Primary, item.Path); // Examples: https://github.com/mono/taglib-sharp/blob/a5f6949a53d09ce63ee7495580d6802921a21f14/tests/fixtures/TagLib.Tests.Images/NullOrientationTest.cs - - try + if (!_excludeExtensions.Contains(Path.GetExtension(item.Path) ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { - using (var fileStream = _fileSystem.OpenRead(item.Path)) + try { - using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(item.Path), fileStream, null))) + using (var fileStream = _fileSystem.OpenRead(item.Path)) { - var image = file as TagLib.Image.File; - - var tag = file.GetTag(TagTypes.TiffIFD) as IFDTag; - - if (tag != null) + using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(item.Path), fileStream, null))) { - var structure = tag.Structure; + var image = file as TagLib.Image.File; - if (structure != null) + var tag = file.GetTag(TagTypes.TiffIFD) as IFDTag; + + if (tag != null) { - var exif = structure.GetEntry(0, (ushort)IFDEntryTag.ExifIFD) as SubIFDEntry; + var structure = tag.Structure; - if (exif != null) + if (structure != null) { - var exifStructure = exif.Structure; + var exif = structure.GetEntry(0, (ushort)IFDEntryTag.ExifIFD) as SubIFDEntry; - if (exifStructure != null) + if (exif != null) { - var entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ApertureValue) as RationalIFDEntry; + var exifStructure = exif.Structure; - if (entry != null) + if (exifStructure != null) { - double val = entry.Value.Numerator; - val /= entry.Value.Denominator; - item.Aperture = val; - } - - entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ShutterSpeedValue) as RationalIFDEntry; - - if (entry != null) - { - double val = entry.Value.Numerator; - val /= entry.Value.Denominator; - item.ShutterSpeed = val; + var entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ApertureValue) as RationalIFDEntry; + + if (entry != null) + { + double val = entry.Value.Numerator; + val /= entry.Value.Denominator; + item.Aperture = val; + } + + entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ShutterSpeedValue) as RationalIFDEntry; + + if (entry != null) + { + double val = entry.Value.Numerator; + val /= entry.Value.Denominator; + item.ShutterSpeed = val; + } } } } } - } - item.CameraMake = image.ImageTag.Make; - item.CameraModel = image.ImageTag.Model; + if (image != null) + { + item.CameraMake = image.ImageTag.Make; + item.CameraModel = image.ImageTag.Model; - item.Width = image.Properties.PhotoWidth; - item.Height = image.Properties.PhotoHeight; + item.Width = image.Properties.PhotoWidth; + item.Height = image.Properties.PhotoHeight; - var rating = image.ImageTag.Rating; - if (rating.HasValue) - { - item.CommunityRating = rating; - } - else - { - item.CommunityRating = null; - } + var rating = image.ImageTag.Rating; + if (rating.HasValue) + { + item.CommunityRating = rating; + } + else + { + item.CommunityRating = null; + } - item.Overview = image.ImageTag.Comment; + item.Overview = image.ImageTag.Comment; - if (!string.IsNullOrWhiteSpace(image.ImageTag.Title)) - { - item.Name = image.ImageTag.Title; - } + if (!string.IsNullOrWhiteSpace(image.ImageTag.Title)) + { + item.Name = image.ImageTag.Title; + } - var dateTaken = image.ImageTag.DateTime; - if (dateTaken.HasValue) - { - item.DateCreated = dateTaken.Value; - item.PremiereDate = dateTaken.Value; - item.ProductionYear = dateTaken.Value.Year; - } + var dateTaken = image.ImageTag.DateTime; + if (dateTaken.HasValue) + { + item.DateCreated = dateTaken.Value; + item.PremiereDate = dateTaken.Value; + item.ProductionYear = dateTaken.Value.Year; + } - item.Genres = image.ImageTag.Genres.ToList(); - item.Tags = image.ImageTag.Keywords; - item.Software = image.ImageTag.Software; + item.Genres = image.ImageTag.Genres.ToList(); + item.Tags = image.ImageTag.Keywords; + item.Software = image.ImageTag.Software; - if (image.ImageTag.Orientation == TagLib.Image.ImageOrientation.None) - { - item.Orientation = null; - } - else - { - MediaBrowser.Model.Drawing.ImageOrientation orientation; - if (Enum.TryParse(image.ImageTag.Orientation.ToString(), true, out orientation)) - { - item.Orientation = orientation; - } - } + if (image.ImageTag.Orientation == TagLib.Image.ImageOrientation.None) + { + item.Orientation = null; + } + else + { + MediaBrowser.Model.Drawing.ImageOrientation orientation; + if (Enum.TryParse(image.ImageTag.Orientation.ToString(), true, out orientation)) + { + item.Orientation = orientation; + } + } - item.ExposureTime = image.ImageTag.ExposureTime; - item.FocalLength = image.ImageTag.FocalLength; + item.ExposureTime = image.ImageTag.ExposureTime; + item.FocalLength = image.ImageTag.FocalLength; - item.Latitude = image.ImageTag.Latitude; - item.Longitude = image.ImageTag.Longitude; - item.Altitude = image.ImageTag.Altitude; + item.Latitude = image.ImageTag.Latitude; + item.Longitude = image.ImageTag.Longitude; + item.Altitude = image.ImageTag.Altitude; - if (image.ImageTag.ISOSpeedRatings.HasValue) - { - item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value); - } - else - { - item.IsoSpeedRating = null; + if (image.ImageTag.ISOSpeedRatings.HasValue) + { + item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value); + } + else + { + item.IsoSpeedRating = null; + } + } } } } + catch (Exception e) + { + _logger.ErrorException("Image Provider - Error reading image tag for {0}", e, item.Path); + } } - catch (Exception e) + + if (!item.Width.HasValue || !item.Height.HasValue) { - _logger.ErrorException("Image Provider - Error reading image tag for {0}", e, item.Path); + var size = _imageProcessor.GetImageSize(item.Path); + + item.Width = Convert.ToInt32(size.Width); + item.Height = Convert.ToInt32(size.Height); } const ItemUpdateType result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 1854829a24..5ef910e519 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1642,6 +1642,8 @@ namespace Emby.Server.Implementations.Dto return null; } + _logger.Info("Getting image size for item type {0}", item.GetType().Name); + try { size = _imageProcessor.GetImageSize(imageInfo); @@ -1673,22 +1675,6 @@ namespace Emby.Server.Implementations.Dto return null; } - var photo = item as Photo; - if (photo != null && photo.Orientation.HasValue) - { - switch (photo.Orientation.Value) - { - case ImageOrientation.LeftBottom: - case ImageOrientation.LeftTop: - case ImageOrientation.RightBottom: - case ImageOrientation.RightTop: - var temp = height; - height = width; - width = temp; - break; - } - } - return width / height; } } diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index f5a1fe2462..3e05653438 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -360,7 +360,7 @@ namespace Emby.Server.Implementations.HttpServer if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration)) { AddAgeHeader(responseHeaders, lastDateModified); - AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration, noCache); + AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration); var result = new HttpResult(new byte[] { }, contentType ?? "text/html", HttpStatusCode.NotModified); @@ -370,7 +370,7 @@ namespace Emby.Server.Implementations.HttpServer } } - AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration, noCache); + AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration); return null; } @@ -555,7 +555,7 @@ namespace Emby.Server.Implementations.HttpServer /// /// Adds the caching responseHeaders. /// - private void AddCachingHeaders(IDictionary responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, bool noCache) + private void AddCachingHeaders(IDictionary responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration) { // Don't specify both last modified and Etag, unless caching unconditionally. They are redundant // https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching @@ -565,11 +565,11 @@ namespace Emby.Server.Implementations.HttpServer responseHeaders["Last-Modified"] = lastDateModified.Value.ToString("r"); } - if (!noCache && cacheDuration.HasValue) + if (cacheDuration.HasValue) { responseHeaders["Cache-Control"] = "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds); } - else if (!noCache && !string.IsNullOrEmpty(cacheKey)) + else if (!string.IsNullOrEmpty(cacheKey)) { responseHeaders["Cache-Control"] = "public"; } @@ -579,15 +579,15 @@ namespace Emby.Server.Implementations.HttpServer responseHeaders["pragma"] = "no-cache, no-store, must-revalidate"; } - AddExpiresHeader(responseHeaders, cacheKey, cacheDuration, noCache); + AddExpiresHeader(responseHeaders, cacheKey, cacheDuration); } /// /// Adds the expires header. /// - private void AddExpiresHeader(IDictionary responseHeaders, string cacheKey, TimeSpan? cacheDuration, bool noCache) + private void AddExpiresHeader(IDictionary responseHeaders, string cacheKey, TimeSpan? cacheDuration) { - if (!noCache && cacheDuration.HasValue) + if (cacheDuration.HasValue) { responseHeaders["Expires"] = DateTime.UtcNow.Add(cacheDuration.Value).ToString("r"); } diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index 54faa14432..f74c019947 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -32,6 +32,14 @@ namespace MediaBrowser.Controller.Channels return base.IsVisible(user); } + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 16; + value /= 9; + + return value; + } + [IgnoreDataMember] public override bool SupportsInheritedParentImages { diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index d7b68d1e7e..542fa5e08f 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -117,8 +117,6 @@ namespace MediaBrowser.Controller.Drawing IImageEncoder ImageEncoder { get; set; } - void SaveImageSize(string path, DateTime imageDateModified, ImageSize size); - bool SupportsTransparency(string path); } } diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index 9452446a14..9936b10362 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -21,11 +21,6 @@ namespace MediaBrowser.Controller.Drawing public static IImageProcessor ImageProcessor { get; set; } - public static void SaveImageSize(string path, DateTime dateModified, ImageSize size) - { - ImageProcessor.SaveImageSize(path, dateModified, size); - } - private static ImageSize GetSizeEstimate(ImageProcessingOptions options) { if (options.Width.HasValue && options.Height.HasValue) diff --git a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs index cdb6f3f619..d2b4569baf 100644 --- a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs +++ b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Audio public override double? GetDefaultPrimaryImageAspectRatio() { - return null; + return 1; } } } diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs index a61862f280..d2459f208c 100644 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs @@ -42,5 +42,13 @@ namespace MediaBrowser.Controller.Entities return false; } } + + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 16; + value /= 9; + + return value; + } } } diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index a83e084db5..16630efe42 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -31,6 +31,14 @@ namespace MediaBrowser.Controller.Entities PhysicalFolderIds = EmptyGuidArray; } + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 16; + value /= 9; + + return value; + } + [IgnoreDataMember] public override bool SupportsPlayedStatus { diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 4e78a7fa5e..6dc85f3e53 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -22,6 +22,11 @@ namespace MediaBrowser.Controller.Entities return GetUserDataKeys()[0]; } + public override double? GetDefaultPrimaryImageAspectRatio() + { + return 1; + } + /// /// Returns the folder containing the item. /// If the item is a folder, it returns the folder itself diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs index bbaec14a15..c940b59531 100644 --- a/MediaBrowser.Controller/Entities/GameSystem.cs +++ b/MediaBrowser.Controller/Entities/GameSystem.cs @@ -44,6 +44,14 @@ namespace MediaBrowser.Controller.Entities } } + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 16; + value /= 9; + + return value; + } + /// /// Gets or sets the game system. /// diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 790f8938e4..569a0dfb8b 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -25,6 +25,11 @@ namespace MediaBrowser.Controller.Entities return GetUserDataKeys()[0]; } + public override double? GetDefaultPrimaryImageAspectRatio() + { + return 1; + } + /// /// Returns the folder containing the item. /// If the item is a folder, it returns the folder itself diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index 8e9eac50cd..11db633bad 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -62,6 +62,35 @@ namespace MediaBrowser.Controller.Entities return true; } + public override double? GetDefaultPrimaryImageAspectRatio() + { + if (Width.HasValue && Height.HasValue) + { + double width = Width.Value; + double height = Height.Value; + + if (Orientation.HasValue) + { + switch (Orientation.Value) + { + case ImageOrientation.LeftBottom: + case ImageOrientation.LeftTop: + case ImageOrientation.RightBottom: + case ImageOrientation.RightTop: + var temp = height; + height = width; + width = temp; + break; + } + } + + width /= Height.Value; + return width; + } + + return base.GetDefaultPrimaryImageAspectRatio(); + } + public int? Width { get; set; } public int? Height { get; set; } public string CameraMake { get; set; } diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs index af9d8c801d..52d743e361 100644 --- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs +++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs @@ -30,5 +30,10 @@ namespace MediaBrowser.Controller.Entities return false; } } + + public override double? GetDefaultPrimaryImageAspectRatio() + { + return 1; + } } } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index e9a794e79c..36bbf6886a 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -254,6 +254,11 @@ namespace MediaBrowser.Controller.Entities } } + public override double? GetDefaultPrimaryImageAspectRatio() + { + return 1; + } + /// /// Gets the configuration directory path. /// diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 66174034d0..57eeafe914 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -58,6 +58,14 @@ namespace MediaBrowser.Controller.Entities } } + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 16; + value /= 9; + + return value; + } + public override int GetChildCount(User user) { return GetChildren(user, true).Count; diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 7d820b007a..49b967104e 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -32,6 +32,14 @@ namespace MediaBrowser.Controller.Entities } } + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 2; + value /= 3; + + return value; + } + [IgnoreDataMember] public override bool SupportsAncestors { -- cgit v1.2.3 From 978eedbcb7a778248acd03b7f924260db70cd406 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Sep 2017 01:06:15 -0400 Subject: improve support for compressed xmltv --- Emby.Dlna/Didl/DidlBuilder.cs | 12 +- Emby.Dlna/PlayTo/PlayToController.cs | 7 +- Emby.Server.Implementations/Archiving/ZipClient.cs | 17 +++ .../Emby.Server.Implementations.csproj | 4 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 42 ++++--- Emby.Server.Implementations/packages.config | 2 +- .../MediaEncoding/EncodingHelper.cs | 29 +++-- .../MediaEncoding/EncodingJobInfo.cs | 98 +++++++++++++-- .../MediaEncoding/EncodingJobOptions.cs | 15 +-- MediaBrowser.Model/Dlna/CodecProfile.cs | 21 +++- MediaBrowser.Model/Dlna/StreamBuilder.cs | 54 ++++---- MediaBrowser.Model/Dlna/StreamInfo.cs | 136 +++++++++++++++++---- MediaBrowser.Model/IO/IZipClient.cs | 2 + .../MediaBrowser.Server.Mono.csproj | 5 +- MediaBrowser.Server.Mono/packages.config | 2 +- .../MediaBrowser.ServerApplication.csproj | 5 +- MediaBrowser.ServerApplication/packages.config | 2 +- 17 files changed, 327 insertions(+), 126 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 1cb9a24fbc..5e200428a7 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -209,8 +209,8 @@ namespace Emby.Dlna.Didl var targetHeight = streamInfo.TargetHeight; var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, - streamInfo.TargetVideoCodec, - streamInfo.TargetAudioCodec, + streamInfo.TargetVideoCodec.FirstOrDefault(), + streamInfo.TargetAudioCodec.FirstOrDefault(), targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, @@ -353,8 +353,8 @@ namespace Emby.Dlna.Didl } var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container, - streamInfo.TargetAudioCodec, - streamInfo.TargetVideoCodec, + streamInfo.TargetAudioCodec.FirstOrDefault(), + streamInfo.TargetVideoCodec.FirstOrDefault(), streamInfo.TargetAudioBitrate, targetWidth, targetHeight, @@ -554,7 +554,7 @@ namespace Emby.Dlna.Didl } var mediaProfile = _profile.GetAudioMediaProfile(streamInfo.Container, - streamInfo.TargetAudioCodec, + streamInfo.TargetAudioCodec.FirstOrDefault(), targetChannels, targetAudioBitrate, targetSampleRate, @@ -567,7 +567,7 @@ namespace Emby.Dlna.Didl : mediaProfile.MimeType; var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container, - streamInfo.TargetAudioCodec, + streamInfo.TargetAudioCodec.FirstOrDefault(), targetAudioBitrate, targetSampleRate, targetChannels, diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 95b164212e..ba1d3a6de2 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -13,6 +13,7 @@ using MediaBrowser.Model.System; using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -515,7 +516,7 @@ namespace Emby.Dlna.PlayTo { return new ContentFeatureBuilder(profile) .BuildAudioHeader(streamInfo.Container, - streamInfo.TargetAudioCodec, + streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioBitrate, streamInfo.TargetAudioSampleRate, streamInfo.TargetAudioChannels, @@ -529,8 +530,8 @@ namespace Emby.Dlna.PlayTo { var list = new ContentFeatureBuilder(profile) .BuildVideoHeader(streamInfo.Container, - streamInfo.TargetVideoCodec, - streamInfo.TargetAudioCodec, + streamInfo.TargetVideoCodec.FirstOrDefault(), + streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetWidth, streamInfo.TargetHeight, streamInfo.TargetVideoBitDepth, diff --git a/Emby.Server.Implementations/Archiving/ZipClient.cs b/Emby.Server.Implementations/Archiving/ZipClient.cs index 3218d56c63..d7d37bb61c 100644 --- a/Emby.Server.Implementations/Archiving/ZipClient.cs +++ b/Emby.Server.Implementations/Archiving/ZipClient.cs @@ -4,6 +4,7 @@ using SharpCompress.Archives.Rar; using SharpCompress.Archives.SevenZip; using SharpCompress.Archives.Tar; using SharpCompress.Readers; +using SharpCompress.Readers.GZip; using SharpCompress.Readers.Zip; namespace Emby.Server.Implementations.Archiving @@ -72,6 +73,22 @@ namespace Emby.Server.Implementations.Archiving } } + public void ExtractAllFromGz(Stream source, string targetPath, bool overwriteExistingFiles) + { + using (var reader = GZipReader.Open(source)) + { + var options = new ExtractionOptions(); + options.ExtractFullPath = true; + + if (overwriteExistingFiles) + { + options.Overwrite = true; + } + + reader.WriteAllToDirectory(targetPath, options); + } + } + /// /// Extracts all from7z. /// diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index ccff29eefd..41a62a417d 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -667,8 +667,8 @@ ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll True - - ..\packages\SharpCompress.0.14.0\lib\net45\SharpCompress.dll + + ..\packages\SharpCompress.0.18.2\lib\net45\SharpCompress.dll ..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index fb8308cda5..55500df6e5 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -65,14 +65,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { - return path; + return UnzipIfNeeded(path, path); } var cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; var cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); if (_fileSystem.FileExists(cacheFile)) { - return UnzipIfNeeded(path, cacheFile); + //return UnzipIfNeeded(path, cacheFile); + return cacheFile; } _logger.Info("Downloading xmltv listings from {0}", path); @@ -112,28 +113,29 @@ namespace Emby.Server.Implementations.LiveTv.Listings } _logger.Debug("Returning xmltv path {0}", cacheFile); - return UnzipIfNeeded(path, cacheFile); + return cacheFile; + //return UnzipIfNeeded(path, cacheFile); } private string UnzipIfNeeded(string originalUrl, string file) { - //var ext = Path.GetExtension(originalUrl); - - //if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) - //{ - // using (var stream = _fileSystem.OpenRead(file)) - // { - // var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); - // _fileSystem.CreateDirectory(tempFolder); - - // _zipClient.ExtractAllFromZip(stream, tempFolder, true); - - // return _fileSystem.GetFiles(tempFolder, true) - // .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase)) - // .Select(i => i.FullName) - // .FirstOrDefault(); - // } - //} + var ext = Path.GetExtension(originalUrl.Split('?')[0]); + + if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) + { + using (var stream = _fileSystem.OpenRead(file)) + { + var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(tempFolder); + + _zipClient.ExtractAllFromGz(stream, tempFolder, true); + + return _fileSystem.GetFiles(tempFolder, true) + .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase)) + .Select(i => i.FullName) + .FirstOrDefault(); + } + } return file; } diff --git a/Emby.Server.Implementations/packages.config b/Emby.Server.Implementations/packages.config index c27b8ac261..d27722fef8 100644 --- a/Emby.Server.Implementations/packages.config +++ b/Emby.Server.Implementations/packages.config @@ -2,7 +2,7 @@ - + diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 642a42c8e2..7be3c37542 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -691,22 +691,26 @@ namespace MediaBrowser.Controller.MediaEncoding param += string.Format(" -r {0}", framerate.Value.ToString(_usCulture)); } - var request = state.BaseRequest; + var targetVideoCodec = state.ActualOutputVideoCodec; - if (!string.IsNullOrEmpty(request.Profile)) + var request = state.BaseRequest; + var profile = state.GetRequestedProfiles(targetVideoCodec).FirstOrDefault(); + if (!string.IsNullOrEmpty(profile)) { if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx - param += " -profile:v " + request.Profile; + param += " -profile:v " + profile; } } - if (!string.IsNullOrEmpty(request.Level)) + var level = state.GetRequestedLevel(targetVideoCodec); + + if (!string.IsNullOrEmpty(level)) { - var level = NormalizeTranscodingLevel(state.OutputVideoCodec, request.Level); + level = NormalizeTranscodingLevel(state.OutputVideoCodec, level); // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 @@ -756,7 +760,6 @@ namespace MediaBrowser.Controller.MediaEncoding { param += " -level " + level; } - } if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) @@ -834,18 +837,21 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } + var requestedProfiles = state.GetRequestedProfiles(videoStream.Codec); + // If client is requesting a specific video profile, it must match the source - if (!string.IsNullOrEmpty(request.Profile)) + if (requestedProfiles.Length > 0) { if (string.IsNullOrEmpty(videoStream.Profile)) { //return false; } - if (!string.IsNullOrEmpty(videoStream.Profile) && !string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) + var requestedProfile = requestedProfiles[0]; + if (!string.IsNullOrEmpty(videoStream.Profile) && !string.Equals(requestedProfile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) { var currentScore = GetVideoProfileScore(videoStream.Profile); - var requestedScore = GetVideoProfileScore(request.Profile); + var requestedScore = GetVideoProfileScore(requestedProfile); if (currentScore == -1 || currentScore > requestedScore) { @@ -910,11 +916,12 @@ namespace MediaBrowser.Controller.MediaEncoding } // If a specific level was requested, the source must match or be less than - if (!string.IsNullOrEmpty(request.Level)) + var level = state.GetRequestedLevel(videoStream.Codec); + if (!string.IsNullOrEmpty(level)) { double requestLevel; - if (double.TryParse(request.Level, NumberStyles.Any, _usCulture, out requestLevel)) + if (double.TryParse(level, NumberStyles.Any, _usCulture, out requestLevel)) { if (!videoStream.Level.HasValue) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index fb8aa9767a..450bbf7c18 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -180,6 +180,61 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } + public string[] GetRequestedProfiles(string codec) + { + if (!string.IsNullOrWhiteSpace(BaseRequest.Profile)) + { + return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries); + } + + if (!string.IsNullOrWhiteSpace(codec)) + { + var profile = BaseRequest.GetOption(codec, "profile"); + + if (!string.IsNullOrWhiteSpace(profile)) + { + return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries); + } + } + + return new string[] { }; + } + + public string GetRequestedLevel(string codec) + { + if (!string.IsNullOrWhiteSpace(BaseRequest.Level)) + { + return BaseRequest.Level; + } + + if (!string.IsNullOrWhiteSpace(codec)) + { + return BaseRequest.GetOption(codec, "level"); + } + + return null; + } + + public int? GetRequestedMaxRefFrames(string codec) + { + if (!string.IsNullOrWhiteSpace(BaseRequest.Level)) + { + return BaseRequest.MaxRefFrames; + } + + if (!string.IsNullOrWhiteSpace(codec)) + { + var value = BaseRequest.GetOption(codec, "maxrefframes"); + int result; + if (!string.IsNullOrWhiteSpace(value) && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result)) + { + return result; + } + } + + return null; + } + public bool IsVideoRequest { get; set; } public TranscodingJobType TranscodingType { get; set; } @@ -188,7 +243,7 @@ namespace MediaBrowser.Controller.MediaEncoding _logger = logger; TranscodingType = jobType; RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - PlayableStreamFileNames = new string[]{}; + PlayableStreamFileNames = new string[] { }; SupportedAudioCodecs = new List(); SupportedVideoCodecs = new List(); SupportedSubtitleCodecs = new List(); @@ -338,12 +393,19 @@ namespace MediaBrowser.Controller.MediaEncoding { get { - var stream = VideoStream; - var request = BaseRequest; + if (BaseRequest.Static) + { + return VideoStream == null ? null : VideoStream.Level; + } + + var level = GetRequestedLevel(ActualOutputVideoCodec); + double result; + if (!string.IsNullOrWhiteSpace(level) && double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out result)) + { + return result; + } - return !string.IsNullOrEmpty(request.Level) && !request.Static - ? double.Parse(request.Level, CultureInfo.InvariantCulture) - : stream == null ? null : stream.Level; + return null; } } @@ -367,8 +429,12 @@ namespace MediaBrowser.Controller.MediaEncoding { get { - var stream = VideoStream; - return stream == null || !BaseRequest.Static ? null : stream.RefFrames; + if (BaseRequest.Static) + { + return VideoStream == null ? null : VideoStream.RefFrames; + } + + return null; } } @@ -423,10 +489,18 @@ namespace MediaBrowser.Controller.MediaEncoding { get { - var stream = VideoStream; - return !string.IsNullOrEmpty(BaseRequest.Profile) && !BaseRequest.Static - ? BaseRequest.Profile - : stream == null ? null : stream.Profile; + if (BaseRequest.Static) + { + return VideoStream == null ? null : VideoStream.Profile; + } + + var requestedProfile = GetRequestedProfiles(ActualOutputVideoCodec).FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(requestedProfile)) + { + return requestedProfile; + } + + return null; } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index cb675ba689..bac2a6e65a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; @@ -39,18 +40,16 @@ namespace MediaBrowser.Controller.MediaEncoding MaxWidth = info.MaxWidth; MaxHeight = info.MaxHeight; MaxFramerate = info.MaxFramerate; - Profile = info.VideoProfile; ItemId = info.ItemId; MediaSourceId = info.MediaSourceId; - AudioCodec = info.TargetAudioCodec; + AudioCodec = info.TargetAudioCodec.FirstOrDefault(); MaxAudioChannels = info.MaxAudioChannels; AudioBitRate = info.AudioBitrate; AudioSampleRate = info.TargetAudioSampleRate; DeviceProfile = deviceProfile; - VideoCodec = info.TargetVideoCodec; + VideoCodec = info.TargetVideoCodec.FirstOrDefault(); VideoBitRate = info.VideoBitrate; AudioStreamIndex = info.AudioStreamIndex; - MaxRefFrames = info.MaxRefFrames; MaxVideoBitDepth = info.MaxVideoBitDepth; SubtitleMethod = info.SubtitleDeliveryMethod; Context = info.Context; @@ -60,11 +59,7 @@ namespace MediaBrowser.Controller.MediaEncoding { SubtitleStreamIndex = info.SubtitleStreamIndex; } - - if (info.VideoLevel.HasValue) - { - Level = info.VideoLevel.Value.ToString(_usCulture); - } + StreamOptions = info.StreamOptions; } } @@ -231,7 +226,7 @@ namespace MediaBrowser.Controller.MediaEncoding SetOption(qualifier + "-" + name, value); } - public Dictionary StreamOptions { get; private set; } + public Dictionary StreamOptions { get; set; } public void SetOption(string name, string value) { diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index d75547adb1..6d143962dd 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -36,7 +36,12 @@ namespace MediaBrowser.Model.Dlna return ContainerProfile.ContainsContainer(Container, container); } - public bool ContainsCodec(string codec, string container) + public bool ContainsAnyCodec(string codec, string container) + { + return ContainsAnyCodec(ContainerProfile.SplitValue(codec), container); + } + + public bool ContainsAnyCodec(string[] codec, string container) { if (!ContainsContainer(container)) { @@ -44,8 +49,20 @@ namespace MediaBrowser.Model.Dlna } var codecs = GetCodecs(); + if (codecs.Length == 0) + { + return true; + } + + foreach (var val in codec) + { + if (ListHelper.ContainsIgnoreCase(codecs, val)) + { + return true; + } + } - return codecs.Length == 0 || ListHelper.ContainsIgnoreCase(codecs, ContainerProfile.SplitValue(codec)[0]); + return false; } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 3b68db8023..dfc9317fd2 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -283,7 +283,7 @@ namespace MediaBrowser.Model.Dlna var conditions = new List(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec, item.Container)) + if (i.Type == CodecType.Audio && i.ContainsAnyCodec(audioCodec, item.Container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) @@ -375,7 +375,7 @@ namespace MediaBrowser.Model.Dlna var audioCodecProfiles = new List(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec, transcodingProfile.Container)) + if (i.Type == CodecType.Audio && i.ContainsAnyCodec(transcodingProfile.AudioCodec, transcodingProfile.Container)) { audioCodecProfiles.Add(i); } @@ -772,7 +772,7 @@ namespace MediaBrowser.Model.Dlna var isFirstAppliedCodecProfile = true; foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec, transcodingProfile.Container)) + if (i.Type == CodecType.Video && i.ContainsAnyCodec(transcodingProfile.VideoCodec, transcodingProfile.Container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) @@ -797,7 +797,7 @@ namespace MediaBrowser.Model.Dlna var transcodingVideoCodecs = ContainerProfile.SplitValue(transcodingProfile.VideoCodec); foreach (var transcodingVideoCodec in transcodingVideoCodecs) { - if (i.ContainsCodec(transcodingVideoCodec, transcodingProfile.Container)) + if (i.ContainsAnyCodec(transcodingVideoCodec, transcodingProfile.Container)) { ApplyTranscodingConditions(playlistItem, i.Conditions, transcodingVideoCodec, !isFirstAppliedCodecProfile); isFirstAppliedCodecProfile = false; @@ -810,7 +810,7 @@ namespace MediaBrowser.Model.Dlna var audioTranscodingConditions = new List(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.VideoAudio && i.ContainsCodec(playlistItem.TargetAudioCodec, transcodingProfile.Container)) + if (i.Type == CodecType.VideoAudio && i.ContainsAnyCodec(playlistItem.TargetAudioCodec, transcodingProfile.Container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) @@ -899,8 +899,10 @@ namespace MediaBrowser.Model.Dlna return 192000; } - private int GetAudioBitrate(string subProtocol, long? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream) + private int GetAudioBitrate(string subProtocol, long? maxTotalBitrate, int? targetAudioChannels, string[] targetAudioCodecs, MediaStream audioStream) { + var targetAudioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; + int defaultBitrate = audioStream == null ? 192000 : audioStream.BitRate ?? GetDefaultAudioBitrateIfUnknown(audioStream); // Reduce the bitrate if we're downmixing @@ -1064,7 +1066,7 @@ namespace MediaBrowser.Model.Dlna conditions = new List(); foreach (CodecProfile i in profile.CodecProfiles) { - if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec, container)) + if (i.Type == CodecType.Video && i.ContainsAnyCodec(videoCodec, container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) @@ -1120,7 +1122,7 @@ namespace MediaBrowser.Model.Dlna foreach (CodecProfile i in profile.CodecProfiles) { - if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec, container)) + if (i.Type == CodecType.VideoAudio && i.ContainsAnyCodec(audioCodec, container)) { bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) @@ -1260,13 +1262,13 @@ namespace MediaBrowser.Model.Dlna } // Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion - return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, false) ?? - GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, true) ?? + return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, false) ?? + GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, true) ?? new SubtitleProfile - { - Method = SubtitleDeliveryMethod.Encode, - Format = subtitleStream.Codec - }; + { + Method = SubtitleDeliveryMethod.Encode, + Format = subtitleStream.Codec + }; } private static bool IsSubtitleEmbedSupported(MediaStream subtitleStream, SubtitleProfile subtitleProfile, string transcodingSubProtocol, string transcodingContainer) @@ -1555,7 +1557,7 @@ namespace MediaBrowser.Model.Dlna } case ProfileConditionValue.RefFrames: { - if (qualifiedOnly) + if (string.IsNullOrWhiteSpace(qualifier)) { continue; } @@ -1565,15 +1567,15 @@ namespace MediaBrowser.Model.Dlna { if (condition.Condition == ProfileConditionType.Equals) { - item.MaxRefFrames = num; + item.SetOption(qualifier, "maxrefframes", StringHelper.ToStringCultureInvariant(num)); } else if (condition.Condition == ProfileConditionType.LessThanEqual) { - item.MaxRefFrames = Math.Min(num, item.MaxRefFrames ?? num); + item.SetOption(qualifier, "maxrefframes", StringHelper.ToStringCultureInvariant(Math.Min(num, item.GetTargetRefFrames(qualifier) ?? num))); } else if (condition.Condition == ProfileConditionType.GreaterThanEqual) { - item.MaxRefFrames = Math.Max(num, item.MaxRefFrames ?? num); + item.SetOption(qualifier, "maxrefframes", StringHelper.ToStringCultureInvariant(Math.Max(num, item.GetTargetRefFrames(qualifier) ?? num))); } } break; @@ -1605,12 +1607,16 @@ namespace MediaBrowser.Model.Dlna } case ProfileConditionValue.VideoProfile: { - if (qualifiedOnly) + if (string.IsNullOrWhiteSpace(qualifier)) { continue; } - item.VideoProfile = (value ?? string.Empty).Split('|')[0]; + if (!string.IsNullOrWhiteSpace(value)) + { + // change from split by | to comma + item.SetOption(qualifier, "profile", string.Join(",", value.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries))); + } break; } case ProfileConditionValue.Height: @@ -1690,7 +1696,7 @@ namespace MediaBrowser.Model.Dlna } case ProfileConditionValue.VideoLevel: { - if (qualifiedOnly) + if (string.IsNullOrWhiteSpace(qualifier)) { continue; } @@ -1700,15 +1706,15 @@ namespace MediaBrowser.Model.Dlna { if (condition.Condition == ProfileConditionType.Equals) { - item.VideoLevel = num; + item.SetOption(qualifier, "level", StringHelper.ToStringCultureInvariant(num)); } else if (condition.Condition == ProfileConditionType.LessThanEqual) { - item.VideoLevel = Math.Min(num, item.VideoLevel ?? num); + item.SetOption(qualifier, "level", StringHelper.ToStringCultureInvariant(Math.Min(num, item.GetTargetVideoLevel(qualifier) ?? num))); } else if (condition.Condition == ProfileConditionType.GreaterThanEqual) { - item.VideoLevel = Math.Max(num, item.VideoLevel ?? num); + item.SetOption(qualifier, "level", StringHelper.ToStringCultureInvariant(Math.Max(num, item.GetTargetVideoLevel(qualifier) ?? num))); } } break; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 3e7ff9c3d2..fe5aaa739a 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -64,8 +64,6 @@ namespace MediaBrowser.Model.Dlna public long StartPositionTicks { get; set; } - public string VideoProfile { get; set; } - public int? SegmentLength { get; set; } public int? MinSegments { get; set; } public bool BreakOnNonKeyFrames { get; set; } @@ -88,13 +86,10 @@ namespace MediaBrowser.Model.Dlna public int? VideoBitrate { get; set; } - public int? VideoLevel { get; set; } - public int? MaxWidth { get; set; } public int? MaxHeight { get; set; } public int? MaxVideoBitDepth { get; set; } - public int? MaxRefFrames { get; set; } public float? MaxFramerate { get; set; } @@ -274,11 +269,34 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("StartTimeTicks", StringHelper.ToStringCultureInvariant(startPositionTicks))); } - list.Add(new NameValuePair("Level", item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : string.Empty)); + if (isDlna) + { + // hack alert + // dlna needs to be update to support the qualified params + var level = item.GetTargetVideoLevel("h264"); + + list.Add(new NameValuePair("Level", level.HasValue ? StringHelper.ToStringCultureInvariant(level.Value) : string.Empty)); + } + + if (isDlna) + { + // hack alert + // dlna needs to be update to support the qualified params + var refframes = item.GetTargetRefFrames("h264"); + + list.Add(new NameValuePair("MaxRefFrames", refframes.HasValue ? StringHelper.ToStringCultureInvariant(refframes.Value) : string.Empty)); + } - list.Add(new NameValuePair("MaxRefFrames", item.MaxRefFrames.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxRefFrames.Value) : string.Empty)); list.Add(new NameValuePair("MaxVideoBitDepth", item.MaxVideoBitDepth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxVideoBitDepth.Value) : string.Empty)); - list.Add(new NameValuePair("Profile", item.VideoProfile ?? string.Empty)); + + if (isDlna) + { + // hack alert + // dlna needs to be update to support the qualified params + var profile = item.GetOption("h264", "profile"); + + list.Add(new NameValuePair("Profile", profile ?? string.Empty)); + } // no longer used list.Add(new NameValuePair("Cabac", string.Empty)); @@ -559,8 +577,19 @@ namespace MediaBrowser.Model.Dlna { get { - MediaStream stream = TargetVideoStream; - return stream == null || !IsDirectStream ? null : stream.RefFrames; + if (IsDirectStream) + { + return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + } + + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrWhiteSpace(videoCodec)) + { + return GetTargetRefFrames(videoCodec); + } + + return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; } } @@ -585,11 +614,54 @@ namespace MediaBrowser.Model.Dlna { get { - MediaStream stream = TargetVideoStream; - return VideoLevel.HasValue && !IsDirectStream - ? VideoLevel - : stream == null ? null : stream.Level; + if (IsDirectStream) + { + return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + } + + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrWhiteSpace(videoCodec)) + { + return GetTargetVideoLevel(videoCodec); + } + + return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + } + } + + public double? GetTargetVideoLevel(string codec) + { + var value = GetOption(codec, "level"); + if (string.IsNullOrWhiteSpace(value)) + { + return null; } + + double result; + if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result)) + { + return result; + } + + return null; + } + + public int? GetTargetRefFrames(string codec) + { + var value = GetOption(codec, "maxrefframes"); + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + int result; + if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result)) + { + return result; + } + + return null; } /// @@ -613,10 +685,19 @@ namespace MediaBrowser.Model.Dlna { get { - MediaStream stream = TargetVideoStream; - return !string.IsNullOrEmpty(VideoProfile) && !IsDirectStream - ? VideoProfile - : stream == null ? null : stream.Profile; + if (IsDirectStream) + { + return TargetVideoStream == null ? null : TargetVideoStream.Profile; + } + + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrWhiteSpace(videoCodec)) + { + return GetOption(videoCodec, "profile"); + } + + return TargetVideoStream == null ? null : TargetVideoStream.Profile; } } @@ -676,7 +757,7 @@ namespace MediaBrowser.Model.Dlna /// /// Predicts the audio codec that will be in the output stream /// - public string TargetAudioCodec + public string[] TargetAudioCodec { get { @@ -686,22 +767,22 @@ namespace MediaBrowser.Model.Dlna if (IsDirectStream) { - return inputCodec; + return string.IsNullOrWhiteSpace(inputCodec) ? new string[] { } : new[] { inputCodec }; } foreach (string codec in AudioCodecs) { if (StringHelper.EqualsIgnoreCase(codec, inputCodec)) { - return codec; + return string.IsNullOrWhiteSpace(codec) ? new string[] { } : new[] { codec }; } } - return AudioCodecs.Length == 0 ? null : AudioCodecs[0]; + return AudioCodecs; } } - public string TargetVideoCodec + public string[] TargetVideoCodec { get { @@ -711,18 +792,18 @@ namespace MediaBrowser.Model.Dlna if (IsDirectStream) { - return inputCodec; + return string.IsNullOrWhiteSpace(inputCodec) ? new string[] { } : new[] { inputCodec }; } foreach (string codec in VideoCodecs) { if (StringHelper.EqualsIgnoreCase(codec, inputCodec)) { - return codec; + return string.IsNullOrWhiteSpace(codec) ? new string[] { } : new[] { codec }; } } - return VideoCodecs.Length == 0 ? null : VideoCodecs[0]; + return VideoCodecs; } } @@ -813,7 +894,8 @@ namespace MediaBrowser.Model.Dlna return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } - var videoCodec = TargetVideoCodec; + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; if (!string.IsNullOrWhiteSpace(videoCodec)) { if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Model/IO/IZipClient.cs b/MediaBrowser.Model/IO/IZipClient.cs index ac57d58a65..2dc4880c2f 100644 --- a/MediaBrowser.Model/IO/IZipClient.cs +++ b/MediaBrowser.Model/IO/IZipClient.cs @@ -23,6 +23,8 @@ namespace MediaBrowser.Model.IO /// if set to true [overwrite existing files]. void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles); + void ExtractAllFromGz(Stream source, string targetPath, bool overwriteExistingFiles); + /// /// Extracts all from zip. /// diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index d2ce0b40de..365977530e 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -55,9 +55,8 @@ ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll True - - ..\packages\SharpCompress.0.14.0\lib\net45\SharpCompress.dll - True + + ..\packages\SharpCompress.0.18.2\lib\net45\SharpCompress.dll ..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll diff --git a/MediaBrowser.Server.Mono/packages.config b/MediaBrowser.Server.Mono/packages.config index cff873f1f7..dfa3dc75d3 100644 --- a/MediaBrowser.Server.Mono/packages.config +++ b/MediaBrowser.Server.Mono/packages.config @@ -2,7 +2,7 @@ - + diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 23db82cf1b..9e4f524898 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -77,9 +77,8 @@ ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll True - - ..\packages\SharpCompress.0.14.0\lib\net45\SharpCompress.dll - True + + ..\packages\SharpCompress.0.18.2\lib\net45\SharpCompress.dll ..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 85d2613bbc..c7b98700e8 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,7 +1,7 @@  - + -- cgit v1.2.3 From d43508a8989240aabdad7225073e0231f5634380 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Sep 2017 15:15:01 -0400 Subject: update applyconditions --- .../MediaEncoding/EncodingHelper.cs | 3 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 54 +++++++++++----------- 2 files changed, 29 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 7be3c37542..368c0cf321 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1367,7 +1367,8 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.DeInterlace("h264") && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { - if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase)) + // If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle + if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase) && (state.VideoStream.RealFrameRate ?? 60) <= 30) { filters.Add("yadif=1:-1:0"); } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index dfc9317fd2..67d9b834f4 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -777,16 +777,28 @@ namespace MediaBrowser.Model.Dlna bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { - bool? isSecondaryAudio = audioStream == null ? null : item.IsSecondaryAudio(audioStream); - int? inputAudioBitrate = audioStream == null ? null : audioStream.BitRate; - int? audioChannels = audioStream == null ? null : audioStream.Channels; - string audioProfile = audioStream == null ? null : audioStream.Profile; - int? inputAudioSampleRate = audioStream == null ? null : audioStream.SampleRate; - int? inputAudioBitDepth = audioStream == null ? null : audioStream.BitDepth; + int? width = videoStream == null ? null : videoStream.Width; + int? height = videoStream == null ? null : videoStream.Height; + int? bitDepth = videoStream == null ? null : videoStream.BitDepth; + int? videoBitrate = videoStream == null ? null : videoStream.BitRate; + double? videoLevel = videoStream == null ? null : videoStream.Level; + string videoProfile = videoStream == null ? null : videoStream.Profile; + float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; + bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; + bool? isInterlaced = videoStream == null ? (bool?)null : videoStream.IsInterlaced; + string videoCodecTag = videoStream == null ? null : videoStream.CodecTag; + bool? isAvc = videoStream == null ? null : videoStream.IsAVC; - if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio)) + TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : item.Timestamp; + int? packetLength = videoStream == null ? null : videoStream.PacketLength; + int? refFrames = videoStream == null ? null : videoStream.RefFrames; + + int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio); + int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video); + + if (!conditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)) { - LogConditionFailure(options.Profile, "VideoAudioCodecProfile", applyCondition, item); + LogConditionFailure(options.Profile, "VideoCodecProfile", applyCondition, item); applyConditions = false; break; } @@ -815,26 +827,14 @@ namespace MediaBrowser.Model.Dlna bool applyConditions = true; foreach (ProfileCondition applyCondition in i.ApplyConditions) { - int? width = videoStream == null ? null : videoStream.Width; - int? height = videoStream == null ? null : videoStream.Height; - int? bitDepth = videoStream == null ? null : videoStream.BitDepth; - int? videoBitrate = videoStream == null ? null : videoStream.BitRate; - double? videoLevel = videoStream == null ? null : videoStream.Level; - string videoProfile = videoStream == null ? null : videoStream.Profile; - float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; - bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; - bool? isInterlaced = videoStream == null ? (bool?)null : videoStream.IsInterlaced; - string videoCodecTag = videoStream == null ? null : videoStream.CodecTag; - bool? isAvc = videoStream == null ? null : videoStream.IsAVC; - - TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : item.Timestamp; - int? packetLength = videoStream == null ? null : videoStream.PacketLength; - int? refFrames = videoStream == null ? null : videoStream.RefFrames; - - int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio); - int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video); + bool? isSecondaryAudio = audioStream == null ? null : item.IsSecondaryAudio(audioStream); + int? inputAudioBitrate = audioStream == null ? null : audioStream.BitRate; + int? audioChannels = audioStream == null ? null : audioStream.Channels; + string audioProfile = audioStream == null ? null : audioStream.Profile; + int? inputAudioSampleRate = audioStream == null ? null : audioStream.SampleRate; + int? inputAudioBitDepth = audioStream == null ? null : audioStream.BitDepth; - if (!conditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)) + if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio)) { LogConditionFailure(options.Profile, "VideoCodecProfile", applyCondition, item); applyConditions = false; -- cgit v1.2.3 From f55b138e1dab42ef691374f872ff22ee3b947f55 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Sep 2017 10:52:01 -0400 Subject: update deinterlace param --- .../LiveTv/TunerHosts/BaseTunerHost.cs | 3 +++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 9 +++++++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 4 ++-- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 5 ++--- MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 13 +++++++++++-- 5 files changed, 27 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 4b4f61d535..787dcb5d3c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -247,7 +247,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts try { var liveStream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false); + var startTime = DateTime.UtcNow; await liveStream.Open(cancellationToken).ConfigureAwait(false); + var endTime = DateTime.UtcNow; + Logger.Info("Live stream opened after {0}ms", (endTime - startTime).TotalMilliseconds); return liveStream; } catch (Exception ex) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index f974b5c2c7..b9a58a0115 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -347,6 +347,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoCodec = "h264"; videoBitrate = 1000000; } + else + { + // This is for android tv's 1200 condition. Remove once not needed anymore so that we can avoid possible side effects of dummying up this data + if ((channelInfo.IsHD ?? true)) + { + width = 1920; + height = 1080; + } + } if (channelInfo != null) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index c530d48c2a..bf3febaf29 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _tempFilePath = Path.Combine(appPaths.TranscodingTempPath, UniqueId + ".ts"); } - protected override async Task OpenInternal(CancellationToken openCancellationToken) + protected override Task OpenInternal(CancellationToken openCancellationToken) { _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); @@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun //OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsTranscoding = true; - await taskCompletionSource.Task.ConfigureAwait(false); + return taskCompletionSource.Task; //await Task.Delay(5000).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 368c0cf321..ee7b9f0800 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -799,13 +799,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (videoStream.IsInterlaced) { - if (state.DeInterlace(videoStream.Codec)) + if (state.DeInterlace(videoStream.Codec, false)) { return false; } } - if (videoStream.IsAnamorphic ?? false) { if (request.RequireNonAnamorphic) @@ -1365,7 +1364,7 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwupload"); } - if (state.DeInterlace("h264") && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (state.DeInterlace("h264", true) && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase) && (state.VideoStream.RealFrameRate ?? 60) <= 30) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 450bbf7c18..cf067ddf41 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -161,7 +161,7 @@ namespace MediaBrowser.Controller.MediaEncoding public int? OutputAudioBitrate; public int? OutputAudioChannels; - public bool DeInterlace(string videoCodec) + public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced) { // Support general param if (BaseRequest.DeInterlace) @@ -177,6 +177,15 @@ namespace MediaBrowser.Controller.MediaEncoding } } + if (forceDeinterlaceIfSourceIsInterlaced) + { + var videoStream = VideoStream; + if (videoStream != null && videoStream.IsInterlaced) + { + return true; + } + } + return false; } @@ -559,7 +568,7 @@ namespace MediaBrowser.Controller.MediaEncoding return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced; } - if (DeInterlace(ActualOutputVideoCodec)) + if (DeInterlace(ActualOutputVideoCodec, true)) { return false; } -- cgit v1.2.3 From 539fecd08b752a50ebdbcef45b51a998f1390167 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Sep 2017 13:04:06 -0400 Subject: rework live stream creation --- MediaBrowser.Controller/IO/StreamHelper.cs | 5 -- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 +- MediaBrowser.Controller/LiveTv/ITunerHost.cs | 15 +++- MediaBrowser.Controller/LiveTv/LiveStream.cs | 87 ---------------------- .../MediaBrowser.Controller.csproj | 1 - MediaBrowser.Server.Mono/MonoAppHost.cs | 2 +- MediaBrowser.Server.Mono/Program.cs | 2 - MediaBrowser.ServerApplication/MainStartup.cs | 2 - MediaBrowser.ServerApplication/WindowsAppHost.cs | 1 - 9 files changed, 16 insertions(+), 101 deletions(-) delete mode 100644 MediaBrowser.Controller/LiveTv/LiveStream.cs (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/IO/StreamHelper.cs b/MediaBrowser.Controller/IO/StreamHelper.cs index af97a0233f..106fec41fc 100644 --- a/MediaBrowser.Controller/IO/StreamHelper.cs +++ b/MediaBrowser.Controller/IO/StreamHelper.cs @@ -6,11 +6,6 @@ namespace MediaBrowser.Controller.IO { public static class StreamHelper { - public static void CopyTo(Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken) - { - CopyTo(source, destination, bufferSize, null, cancellationToken); - } - public static void CopyTo(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken) { byte[] buffer = new byte[bufferSize]; diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 42c31c6299..be85e115c4 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -383,7 +383,7 @@ namespace MediaBrowser.Controller.LiveTv event EventHandler> SeriesTimerCreated; string GetEmbyTvActiveRecordingPath(string id); - Task GetEmbyTvLiveStream(string id); + Task GetEmbyTvLiveStream(string id); ActiveRecordingInfo GetActiveRecordingInfo(string path); diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index fc344298bb..2019259c56 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.LiveTv /// The stream identifier. /// The cancellation token. /// Task<MediaSourceInfo>. - Task GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken); + Task GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken); /// /// Gets the channel stream media sources. /// @@ -56,4 +56,17 @@ namespace MediaBrowser.Controller.LiveTv /// Task. Task Validate(TunerHostInfo info); } + + public interface ILiveStream + { + Task Open(CancellationToken cancellationToken); + Task Close(); + int ConsumerCount { get; } + string OriginalStreamId { get; set; } + bool EnableStreamSharing { get; set; } + ITunerHost TunerHost { get; set; } + MediaSourceInfo OpenedMediaSource { get; set; } + string UniqueId { get; } + List SharedStreamIds { get; } + } } diff --git a/MediaBrowser.Controller/LiveTv/LiveStream.cs b/MediaBrowser.Controller/LiveTv/LiveStream.cs deleted file mode 100644 index 20947462e8..0000000000 --- a/MediaBrowser.Controller/LiveTv/LiveStream.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.System; - -namespace MediaBrowser.Controller.LiveTv -{ - public class LiveStream - { - public MediaSourceInfo OriginalMediaSource { get; set; } - public MediaSourceInfo OpenedMediaSource { get; set; } - public int ConsumerCount - { - get { return SharedStreamIds.Count; } - } - public ITunerHost TunerHost { get; set; } - public string OriginalStreamId { get; set; } - public bool EnableStreamSharing { get; set; } - public string UniqueId = Guid.NewGuid().ToString("N"); - - public List SharedStreamIds = new List(); - protected readonly IEnvironmentInfo Environment; - protected readonly IFileSystem FileSystem; - const int StreamCopyToBufferSize = 81920; - - public LiveStream(MediaSourceInfo mediaSource, IEnvironmentInfo environment, IFileSystem fileSystem) - { - OriginalMediaSource = mediaSource; - Environment = environment; - FileSystem = fileSystem; - OpenedMediaSource = mediaSource; - EnableStreamSharing = true; - } - - public Task Open(CancellationToken cancellationToken) - { - return OpenInternal(cancellationToken); - } - - protected virtual Task OpenInternal(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public virtual Task Close() - { - return Task.FromResult(true); - } - - protected Stream GetInputStream(string path, bool allowAsyncFileRead) - { - var fileOpenOptions = FileOpenOptions.SequentialScan; - - if (allowAsyncFileRead) - { - fileOpenOptions |= FileOpenOptions.Asynchronous; - } - - return FileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, fileOpenOptions); - } - - protected async Task DeleteTempFile(string path, int retryCount = 0) - { - try - { - FileSystem.DeleteFile(path); - return; - } - catch - { - - } - - if (retryCount > 20) - { - return; - } - - await Task.Delay(500).ConfigureAwait(false); - await DeleteTempFile(path, retryCount + 1).ConfigureAwait(false); - } - } -} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 5ef763b62b..b33993859b 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -145,7 +145,6 @@ - diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs index fe684d928d..312f147323 100644 --- a/MediaBrowser.Server.Mono/MonoAppHost.cs +++ b/MediaBrowser.Server.Mono/MonoAppHost.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Server.Mono get { // A restart script must be provided - return false; + return StartupOptions.ContainsOption("-restartpath") && StartupOptions.ContainsOption("-ffmpeg"); } } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 566a84da2c..3267a77b95 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -12,8 +12,6 @@ using System.Reflection; using System.Text.RegularExpressions; using System.Threading.Tasks; using Emby.Drawing; -using Emby.Server.Core.Cryptography; -using Emby.Server.Core; using Emby.Server.Implementations; using Emby.Server.Implementations.EnvironmentInfo; using Emby.Server.Implementations.IO; diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index d17d9ee435..70b03aa44b 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -16,9 +16,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using Emby.Server.Core.Cryptography; using Emby.Drawing; -using Emby.Server.Core; using Emby.Server.Implementations; using Emby.Server.Implementations.Browser; using Emby.Server.Implementations.EnvironmentInfo; diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs index 19079fbc92..9896b75e33 100644 --- a/MediaBrowser.ServerApplication/WindowsAppHost.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -6,7 +6,6 @@ using System.Reflection; using System.Runtime.InteropServices.ComTypes; using Emby.Server.CinemaMode; using Emby.Server.Connect; -using Emby.Server.Core; using Emby.Server.Implementations; using Emby.Server.Implementations.EntryPoints; using Emby.Server.Implementations.FFMpeg; -- cgit v1.2.3 From 134e74414d2644f1c345a2ef8876504aaaa69027 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Sep 2017 02:13:05 -0400 Subject: update translations --- .../MediaEncoding/EncodingHelper.cs | 36 ++++++---------------- SharedVersion.cs | 2 +- 2 files changed, 11 insertions(+), 27 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ee7b9f0800..861f4467df 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1531,11 +1531,18 @@ namespace MediaBrowser.Controller.MediaEncoding /// System.Int32. public int GetNumberOfThreads(EncodingJobInfo state, EncodingOptions encodingOptions, bool isWebm) { - var threads = GetNumberOfThreadsInternal(state, encodingOptions, isWebm); + if (isWebm) + { + // Recommended per docs + return Math.Max(Environment.ProcessorCount - 1, 2); + } + + var threads = state.BaseRequest.CpuCoreLimit ?? encodingOptions.EncodingThreadCount; - if (state.BaseRequest.CpuCoreLimit.HasValue && state.BaseRequest.CpuCoreLimit.Value > 0) + // Automatic + if (threads <= 0 || threads >= Environment.ProcessorCount) { - threads = Math.Min(threads, state.BaseRequest.CpuCoreLimit.Value); + return 0; } return threads; @@ -1957,29 +1964,6 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - /// - /// Gets the number of threads. - /// - /// System.Int32. - private int GetNumberOfThreadsInternal(EncodingJobInfo state, EncodingOptions encodingOptions, bool isWebm) - { - var threads = encodingOptions.EncodingThreadCount; - - if (isWebm) - { - // Recommended per docs - return Math.Max(Environment.ProcessorCount - 1, 2); - } - - // Automatic - if (threads == -1) - { - return 0; - } - - return threads; - } - public string GetSubtitleEmbedArguments(EncodingJobInfo state) { if (state.SubtitleStream == null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Embed) diff --git a/SharedVersion.cs b/SharedVersion.cs index e1a18d590d..ea2c949247 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.32.10")] +[assembly: AssemblyVersion("3.2.32.11")] -- cgit v1.2.3 From 4e4c145855bb2f58492f62b9bfbb6a3f7c1d232f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Sep 2017 16:10:13 -0400 Subject: update hls query string --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 10 ++++++---- MediaBrowser.Model/Dlna/StreamBuilder.cs | 7 ++++++- MediaBrowser.Model/Dlna/StreamInfo.cs | 8 ++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 861f4467df..6be68043fd 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -346,7 +346,8 @@ namespace MediaBrowser.Controller.MediaEncoding "Constrained High" }; - return Array.FindIndex(list.ToArray(), t => string.Equals(t, profile, StringComparison.OrdinalIgnoreCase)); + // strip spaces because they may be stripped out on the query string + return Array.FindIndex(list.ToArray(), t => string.Equals(t.Replace(" ", ""), profile.Replace(" ", ""), StringComparison.OrdinalIgnoreCase)); } public string GetInputPathArgument(EncodingJobInfo state) @@ -831,7 +832,7 @@ namespace MediaBrowser.Controller.MediaEncoding } // Source and target codecs must match - if (string.IsNullOrEmpty(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase)) + if (string.IsNullOrWhiteSpace(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase)) { return false; } @@ -841,13 +842,14 @@ namespace MediaBrowser.Controller.MediaEncoding // If client is requesting a specific video profile, it must match the source if (requestedProfiles.Length > 0) { - if (string.IsNullOrEmpty(videoStream.Profile)) + if (string.IsNullOrWhiteSpace(videoStream.Profile)) { //return false; } var requestedProfile = requestedProfiles[0]; - if (!string.IsNullOrEmpty(videoStream.Profile) && !string.Equals(requestedProfile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) + // strip spaces because they may be stripped out on the query string as well + if (!string.IsNullOrWhiteSpace(videoStream.Profile) && !requestedProfiles.Contains(videoStream.Profile.Replace(" ", ""), StringComparer.OrdinalIgnoreCase)) { var currentScore = GetVideoProfileScore(videoStream.Profile); var requestedScore = GetVideoProfileScore(requestedProfile); diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 67d9b834f4..95a80c34c0 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1615,7 +1615,12 @@ namespace MediaBrowser.Model.Dlna if (!string.IsNullOrWhiteSpace(value)) { // change from split by | to comma - item.SetOption(qualifier, "profile", string.Join(",", value.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries))); + + // strip spaces to avoid having to encode + var values = value + .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + + item.SetOption(qualifier, "profile", string.Join(",", values)); } break; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 2019acd0d2..5a059e91d2 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -297,7 +297,10 @@ namespace MediaBrowser.Model.Dlna // dlna needs to be update to support the qualified params var profile = item.GetOption("h264", "profile"); - list.Add(new NameValuePair("Profile", profile ?? string.Empty)); + // Avoid having to encode + profile = (profile ?? string.Empty).Replace(" ", ""); + + list.Add(new NameValuePair("Profile", profile)); } // no longer used @@ -372,7 +375,8 @@ namespace MediaBrowser.Model.Dlna continue; } - list.Add(new NameValuePair(pair.Key, pair.Value)); + // strip spaces to avoid having to encode h264 profile names + list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", ""))); } } -- cgit v1.2.3 From 085470394e60fa919581b2f19dc234eeb985993a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 Oct 2017 13:26:09 -0400 Subject: update home screen sections --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 2 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 8 +--- Emby.Server.Implementations/TV/TVSeriesManager.cs | 36 +++------------ MediaBrowser.Api/UserLibrary/ItemsService.cs | 52 ++++++++++++++++++++++ .../Entities/UserViewBuilder.cs | 15 +++---- MediaBrowser.Controller/TV/ITVSeriesManager.cs | 2 +- .../Manager/ItemImageProvider.cs | 4 +- 7 files changed, 69 insertions(+), 50 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 47d199e6e6..7db282dc86 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -1101,7 +1101,7 @@ namespace Emby.Dlna.ContentDirectory StartIndex = query.StartIndex, UserId = query.User.Id.ToString("N") - }, new List { (Folder)parent }, query.DtoOptions); + }, new List { parent }, query.DtoOptions); return ToResult(result); } diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 56b10a7e6a..c99b601c90 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -333,13 +333,7 @@ namespace Emby.Server.Implementations.IO NotifyFilters.Attributes; newWatcher.Created += watcher_Changed; - - // Seeing mono crashes on background threads we can't catch, testing if this might help - if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) - { - newWatcher.Deleted += watcher_Changed; - } - + newWatcher.Deleted += watcher_Changed; newWatcher.Renamed += watcher_Changed; newWatcher.Changed += watcher_Changed; diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 0b81f7e93b..ec2d8c4fc4 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -56,37 +56,15 @@ namespace Emby.Server.Implementations.TV return GetResult(GetNextUpEpisodes(request, user, new[] { presentationUniqueKey }, dtoOptions), request); } - if (limit.HasValue) - { - limit = limit.Value + 10; - } - - var items = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Episode).Name }, - OrderBy = new[] { new Tuple(ItemSortBy.DatePlayed, SortOrder.Descending) }, - SeriesPresentationUniqueKey = presentationUniqueKey, - Limit = limit, - ParentId = parentIdGuid, - Recursive = true, - DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions - { - Fields = new ItemFields[] - { - ItemFields.SeriesPresentationUniqueKey - } - }, - GroupBySeriesPresentationUniqueKey = true - - }).Cast().Select(GetUniqueSeriesKey); - - // Avoid implicitly captured closure - var episodes = GetNextUpEpisodes(request, user, items, dtoOptions); + var parents = user.RootFolder.GetChildren(user, true) + .Where(i => i is Folder) + .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N"))) + .ToList(); - return GetResult(episodes, request); + return GetNextUp(request, parents, dtoOptions); } - public QueryResult GetNextUp(NextUpQuery request, List parentsFolders, DtoOptions dtoOptions) + public QueryResult GetNextUp(NextUpQuery request, List parentsFolders, DtoOptions dtoOptions) { var user = _userManager.GetUserById(request.UserId); @@ -134,7 +112,7 @@ namespace Emby.Server.Implementations.TV }, GroupBySeriesPresentationUniqueKey = true - }, parentsFolders.Cast().ToList()).Cast().Select(GetUniqueSeriesKey); + }, parentsFolders).Cast().Select(GetUniqueSeriesKey); // Avoid implicitly captured closure var episodes = GetNextUpEpisodes(request, user, items, dtoOptions); diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 5919c50d48..5fe386f1ab 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -26,6 +26,11 @@ namespace MediaBrowser.Api.UserLibrary { } + [Route("/Users/{UserId}/Items/Resume", "GET", Summary = "Gets items based on a query.")] + public class GetResumeItems : BaseItemsRequest, IReturn> + { + } + /// /// Class ItemsService /// @@ -79,6 +84,53 @@ namespace MediaBrowser.Api.UserLibrary _authContext = authContext; } + public object Get(GetResumeItems request) + { + var user = _userManager.GetUserById(request.UserId); + + var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId); + + var options = GetDtoOptions(_authContext, request); + + var ancestorIds = new List(); + + var excludeFolderIds = user.Configuration.LatestItemsExcludes; + if (!parentIdGuid.HasValue && excludeFolderIds.Length > 0) + { + ancestorIds = user.RootFolder.GetChildren(user, true) + .Where(i => i is Folder) + .Where(i => !excludeFolderIds.Contains(i.Id.ToString("N"))) + .Select(i => i.Id.ToString("N")) + .ToList(); + } + + var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user) + { + OrderBy = new[] { ItemSortBy.DatePlayed }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(), + IsResumable = true, + StartIndex = request.StartIndex, + Limit = request.Limit, + ParentId = parentIdGuid, + Recursive = true, + DtoOptions = options, + MediaTypes = request.GetMediaTypes(), + IsVirtualItem = false, + CollapseBoxSetItems = false, + EnableTotalRecordCount = request.EnableTotalRecordCount, + AncestorIds = ancestorIds.ToArray() + }); + + var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user); + + var result = new QueryResult + { + TotalRecordCount = itemsResult.TotalRecordCount, + Items = returnItems + }; + + return ToOptimizedSerializedResultUsingCache(result); + } + /// /// Gets the specified request. /// diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 3ab82a1030..43adc4af68 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -238,12 +238,9 @@ namespace MediaBrowser.Controller.Entities { if (queryParent is UserView) { - return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), queryParent, query); - } - else - { - return GetResult(queryParent.GetChildren(user, true), queryParent, query); + return GetResult(GetMediaFolders(user).OfType().SelectMany(i => i.GetChildren(user, true)), queryParent, query); } + return GetResult(queryParent.GetChildren(user, true), queryParent, query); } } } @@ -1681,7 +1678,7 @@ namespace MediaBrowser.Controller.Entities return true; } - private IEnumerable GetMediaFolders(User user) + private IEnumerable GetMediaFolders(User user) { if (user == null) { @@ -1696,7 +1693,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i)); } - private List GetMediaFolders(User user, IEnumerable viewTypes) + private List GetMediaFolders(User user, IEnumerable viewTypes) { if (user == null) { @@ -1717,14 +1714,14 @@ namespace MediaBrowser.Controller.Entities }).ToList(); } - private List GetMediaFolders(Folder parent, User user, IEnumerable viewTypes) + private List GetMediaFolders(Folder parent, User user, IEnumerable viewTypes) { if (parent == null || parent is UserView) { return GetMediaFolders(user, viewTypes); } - return new List { parent }; + return new List { parent }; } private async Task> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query) diff --git a/MediaBrowser.Controller/TV/ITVSeriesManager.cs b/MediaBrowser.Controller/TV/ITVSeriesManager.cs index 0bcb9ae5b7..fd41094ee4 100644 --- a/MediaBrowser.Controller/TV/ITVSeriesManager.cs +++ b/MediaBrowser.Controller/TV/ITVSeriesManager.cs @@ -15,6 +15,6 @@ namespace MediaBrowser.Controller.TV /// /// Gets the next up. /// - QueryResult GetNextUp(NextUpQuery request, List parentsFolders, DtoOptions options); + QueryResult GetNextUp(NextUpQuery request, List parentsFolders, DtoOptions options); } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index a6d4d4c334..00fd54271c 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -204,9 +204,7 @@ namespace MediaBrowser.Providers.Manager private bool HasImage(IHasMetadata item, ImageType type) { - var image = item.GetImageInfo(type, 0); - - return image != null; + return item.HasImage(type); } /// -- cgit v1.2.3 From a452bc23b299b26cff3ff585862796c04ac5bc93 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 Oct 2017 20:13:12 -0400 Subject: adjust params when burning in subtitles --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 6 ++++-- MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 6be68043fd..8b612f809d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -530,7 +530,8 @@ namespace MediaBrowser.Controller.MediaEncoding { var seconds = Math.Round(TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds); - var setPtsParam = state.CopyTimestamps + // hls always copies timestamps + var setPtsParam = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive ? string.Empty : string.Format(",setpts=PTS -{0}/TB", seconds.ToString(_usCulture)); @@ -1083,7 +1084,8 @@ namespace MediaBrowser.Controller.MediaEncoding } } - if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && !state.CopyTimestamps) + var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive; + if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && !isCopyingTimestamps) { var seconds = TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index cf067ddf41..506fce3ca9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -163,6 +163,14 @@ namespace MediaBrowser.Controller.MediaEncoding 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) { @@ -179,8 +187,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (forceDeinterlaceIfSourceIsInterlaced) { - var videoStream = VideoStream; - if (videoStream != null && videoStream.IsInterlaced) + if (isInputInterlaced) { return true; } -- cgit v1.2.3 From 1da8509ae5b09cb421ece67421f2a88544a2c940 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 Oct 2017 20:13:43 -0400 Subject: update playback settings --- Emby.Server.Implementations/Dto/DtoService.cs | 1 + MediaBrowser.Controller/Entities/BasePluginFolder.cs | 12 ++++++------ MediaBrowser.Controller/Entities/CollectionFolder.cs | 12 ++++++------ MediaBrowser.Controller/Entities/UserView.cs | 12 ++++++------ MediaBrowser.Controller/Entities/Video.cs | 8 ++++++++ SharedVersion.cs | 2 +- 6 files changed, 28 insertions(+), 19 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 5ef910e519..9f08c6462d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1642,6 +1642,7 @@ namespace Emby.Server.Implementations.Dto return null; } + return null; _logger.Info("Getting image size for item type {0}", item.GetType().Name); try diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs index d2459f208c..c06f1cef4c 100644 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs @@ -43,12 +43,12 @@ namespace MediaBrowser.Controller.Entities } } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; + //public override double? GetDefaultPrimaryImageAspectRatio() + //{ + // double value = 16; + // value /= 9; - return value; - } + // return value; + //} } } diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 16630efe42..5fb9e517c8 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -31,13 +31,13 @@ namespace MediaBrowser.Controller.Entities PhysicalFolderIds = EmptyGuidArray; } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; + //public override double? GetDefaultPrimaryImageAspectRatio() + //{ + // double value = 16; + // value /= 9; - return value; - } + // return value; + //} [IgnoreDataMember] public override bool SupportsPlayedStatus diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 57eeafe914..2152e65cfb 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -58,13 +58,13 @@ namespace MediaBrowser.Controller.Entities } } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; + //public override double? GetDefaultPrimaryImageAspectRatio() + //{ + // double value = 16; + // value /= 9; - return value; - } + // return value; + //} public override int GetChildCount(User user) { diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index ffb601dc46..8693d867cc 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -78,6 +78,14 @@ namespace MediaBrowser.Controller.Entities } } + public override double? GetDefaultPrimaryImageAspectRatio() + { + double value = 16; + value /= 9; + + return value; + } + public override string CreatePresentationUniqueKey() { if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) diff --git a/SharedVersion.cs b/SharedVersion.cs index a3ccb0b7a1..5be0a16569 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.32.15")] +[assembly: AssemblyVersion("3.2.32.16")] -- cgit v1.2.3