diff options
Diffstat (limited to 'MediaBrowser.Controller')
7 files changed, 91 insertions, 30 deletions
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 78f859069..bd96059e3 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -155,7 +155,7 @@ namespace MediaBrowser.Controller.Entities public bool EnableGroupByMetadataKey { get; set; } public bool? HasChapterImages { get; set; } - public ValueTuple<string, SortOrder>[] OrderBy { get; set; } + public IReadOnlyList<(string, SortOrder)> OrderBy { get; set; } public DateTime? MinDateCreated { get; set; } public DateTime? MinDateLastSaved { get; set; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 76cb9a651..2475b2b7e 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -226,14 +226,16 @@ namespace MediaBrowser.Controller.Entities.TV query.AncestorWithPresentationUniqueKey = null; query.SeriesPresentationUniqueKey = seriesKey; - if (query.OrderBy.Length == 0) + if (query.OrderBy.Count == 0) { query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(); } + if (query.IncludeItemTypes.Length == 0) { query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; } + query.IsVirtualItem = false; return LibraryManager.GetItemsResult(query); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 454bdc4ae..435a1e8da 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -450,14 +450,16 @@ namespace MediaBrowser.Controller.Entities return SortAndPage(items, totalRecordLimit, query, libraryManager, true); } - public static QueryResult<BaseItem> SortAndPage(IEnumerable<BaseItem> items, + public static QueryResult<BaseItem> SortAndPage( + IEnumerable<BaseItem> items, int? totalRecordLimit, InternalItemsQuery query, - ILibraryManager libraryManager, bool enableSorting) + ILibraryManager libraryManager, + bool enableSorting) { if (enableSorting) { - if (query.OrderBy.Length > 0) + if (query.OrderBy.Count > 0) { items = libraryManager.Sort(items, query.User, query.OrderBy); } diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index ce4e3f530..eb735d31a 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -9,7 +9,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Library { /// <summary> - /// Interface IUserDataManager + /// Interface IUserDataManager. /// </summary> public interface IUserDataManager { @@ -26,13 +26,11 @@ namespace MediaBrowser.Controller.Library /// <param name="userData">The user data.</param> /// <param name="reason">The reason.</param> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> void SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken); void SaveUserData(User userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken); UserItemData GetUserData(User user, BaseItem item); - UserItemData GetUserData(string userId, BaseItem item); UserItemData GetUserData(Guid userId, BaseItem item); /// <summary> diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index eea2e3a71..8d92c9f6f 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Controller.Library event EventHandler<GenericEventArgs<User>> UserLockedOut; /// <summary> - /// Gets a User by Id. + /// Gets a user by Id. /// </summary> /// <param name="id">The id.</param> /// <returns>The user with the specified Id, or <c>null</c> if the user doesn't exist.</returns> @@ -57,13 +57,6 @@ namespace MediaBrowser.Controller.Library User GetUserById(Guid id); /// <summary> - /// Gets the user by identifier. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>User.</returns> - User GetUserById(string id); - - /// <summary> /// Gets the name of the user by. /// </summary> /// <param name="name">The name.</param> diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 0664bdd98..897e22018 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -467,6 +467,27 @@ namespace MediaBrowser.Controller.MediaEncoding .Append(' '); } + if (state.IsVideoRequest + && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + { + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); + var outputVideoCodec = GetVideoEncoder(state, encodingOptions); + + if (encodingOptions.EnableHardwareEncoding && outputVideoCodec.Contains("qsv", StringComparison.OrdinalIgnoreCase)) + { + if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)) + { + arg.Append("-hwaccel qsv "); + } + else + { + arg.Append("-init_hw_device qsv=hw -filter_hw_device hw "); + } + } + + arg.Append(videoDecoder + " "); + } + arg.Append("-i ") .Append(GetInputPathArgument(state)); @@ -1562,6 +1583,7 @@ namespace MediaBrowser.Controller.MediaEncoding var videoSizeParam = string.Empty; + // Setup subtitle scaling if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue) { videoSizeParam = string.Format( @@ -1570,7 +1592,11 @@ namespace MediaBrowser.Controller.MediaEncoding state.VideoStream.Width.Value, state.VideoStream.Height.Value); - videoSizeParam += ":force_original_aspect_ratio=decrease"; + //For QSV, feed it into hardware encoder now + if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + videoSizeParam += ",hwupload=extra_hw_frames=64"; + } } var mapPrefix = state.SubtitleStream.IsExternal ? @@ -1581,9 +1607,31 @@ namespace MediaBrowser.Controller.MediaEncoding ? 0 : state.SubtitleStream.Index; + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options); + + // Setup default filtergraph utilizing FFMpeg overlay() and FFMpeg scale() (see the return of this function for index reference) + var retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\""; + + if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + /* + QSV in FFMpeg can now setup hardware overlay for transcodes. + For software decoding and hardware encoding option, frames must be hwuploaded into hardware + with fixed frame size. + */ + if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)) + { + retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\""; + } + else + { + retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]hwupload=extra_hw_frames=64[v];[v][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\""; + } + } + return string.Format( CultureInfo.InvariantCulture, - " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"", + retStr, mapPrefix, subtitleStreamIndex, state.VideoStream.Index, @@ -1647,31 +1695,34 @@ namespace MediaBrowser.Controller.MediaEncoding requestedMaxWidth, requestedMaxHeight); - if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) + if ((string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) && width.HasValue && height.HasValue) { - // Work around vaapi's reduced scaling features - var scaler = "scale_vaapi"; - // Given the input dimensions (inputWidth, inputHeight), determine the output dimensions // (outputWidth, outputHeight). The user may request precise output dimensions or maximum // output dimensions. Output dimensions are guaranteed to be even. var outputWidth = width.Value; var outputHeight = height.Value; + var vaapi_or_qsv = string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ? "qsv" : "vaapi"; if (!videoWidth.HasValue || outputWidth != videoWidth.Value || !videoHeight.HasValue || outputHeight != videoHeight.Value) { + // Force nv12 pixel format to enable 10-bit to 8-bit colour conversion. filters.Add( string.Format( CultureInfo.InvariantCulture, - "{0}=w={1}:h={2}", - scaler, + "scale_{0}=w={1}:h={2}:format=nv12", + vaapi_or_qsv, outputWidth, outputHeight)); + } + else + { + filters.Add(string.Format(CultureInfo.InvariantCulture, "scale_{0}=format=nv12", vaapi_or_qsv)); } } else if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 @@ -1914,10 +1965,26 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwupload"); } - if (state.DeInterlace("h264", true) - && string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options); + + // If we are software decoding, and hardware encoding + if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) + && (string.IsNullOrEmpty(videoDecoder) || !videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase))) + { + filters.Add("format=nv12|qsv"); + filters.Add("hwupload=extra_hw_frames=64"); + } + + if (state.DeInterlace("h264", true)) { - filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_vaapi")); + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + { + filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_vaapi")); + } + else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_qsv")); + } } if ((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true)) @@ -1940,8 +2007,6 @@ namespace MediaBrowser.Controller.MediaEncoding var inputHeight = videoStream?.Height; var threeDFormat = state.MediaSource.Video3DFormat; - var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options); - filters.AddRange(GetScalingFilters(inputWidth, inputHeight, threeDFormat, videoDecoder, outputVideoCodec, request.Width, request.Height, request.MaxWidth, request.MaxHeight)); var output = string.Empty; @@ -2134,6 +2199,7 @@ namespace MediaBrowser.Controller.MediaEncoding } var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); + if (!string.IsNullOrEmpty(videoDecoder)) { inputModifier += " " + videoDecoder; diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index b45043f92..3b08e72b9 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -181,7 +181,7 @@ namespace MediaBrowser.Controller.Playlists { Recursive = true, IsFolder = false, - OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(), + OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, MediaTypes = new[] { mediaType }, EnableTotalRecordCount = false, DtoOptions = options |
