diff options
Diffstat (limited to 'MediaBrowser.Controller')
8 files changed, 96 insertions, 190 deletions
diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs index eb181dcc4..5566421cb 100644 --- a/MediaBrowser.Controller/Devices/IDeviceManager.cs +++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs @@ -44,26 +44,28 @@ namespace MediaBrowser.Controller.Devices /// </summary> /// <param name="id">The identifier.</param> /// <returns>DeviceInfo.</returns> - Task<DeviceInfo> GetDevice(string id); + DeviceInfo GetDevice(string id); /// <summary> /// Gets devices based on the provided query. /// </summary> /// <param name="query">The device query.</param> /// <returns>A <see cref="Task{QueryResult}"/> representing the retrieval of the devices.</returns> - Task<QueryResult<Device>> GetDevices(DeviceQuery query); + QueryResult<Device> GetDevices(DeviceQuery query); - Task<QueryResult<DeviceInfo>> GetDeviceInfos(DeviceQuery query); + QueryResult<DeviceInfo> GetDeviceInfos(DeviceQuery query); /// <summary> /// Gets the devices. /// </summary> /// <param name="userId">The user's id, or <c>null</c>.</param> /// <returns>IEnumerable<DeviceInfo>.</returns> - Task<QueryResult<DeviceInfo>> GetDevicesForUser(Guid? userId); + QueryResult<DeviceInfo> GetDevicesForUser(Guid? userId); Task DeleteDevice(Device device); + Task UpdateDevice(Device device); + /// <summary> /// Determines whether this instance [can access device] the specified user identifier. /// </summary> @@ -74,6 +76,6 @@ namespace MediaBrowser.Controller.Devices Task UpdateDeviceOptions(string deviceId, string deviceName); - Task<DeviceOptions> GetDeviceOptions(string deviceId); + DeviceOptions GetDeviceOptions(string deviceId); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7b6f364f7..634f34681 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities /// The supported image extensions. /// </summary> public static readonly string[] SupportedImageExtensions - = new[] { ".png", ".jpg", ".jpeg", ".webp", ".tbn", ".gif" }; + = new[] { ".png", ".jpg", ".jpeg", ".webp", ".tbn", ".gif", ".svg" }; private static readonly List<string> _supportedExtensions = new List<string>(SupportedImageExtensions) { @@ -487,6 +487,8 @@ namespace MediaBrowser.Controller.Entities public static IMediaSourceManager MediaSourceManager { get; set; } + public static IMediaSegmentManager MediaSegmentManager { get; set; } + /// <summary> /// Gets or sets the name of the forced sort. /// </summary> @@ -1116,7 +1118,10 @@ namespace MediaBrowser.Controller.Entities RunTimeTicks = item.RunTimeTicks, Container = item.Container, Size = item.Size, - Type = type + Type = type, + HasSegments = MediaSegmentManager.IsTypeSupported(item) + && (protocol is null or MediaProtocol.File) + && MediaSegmentManager.HasSegments(item.Id) }; if (string.IsNullOrEmpty(info.Path)) diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index d7ccfd8ae..a07187d2f 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -112,37 +112,31 @@ namespace MediaBrowser.Controller.Entities.Movies return true; } - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) + private IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user) { - var children = base.GetChildren(user, includeLinkedChildren, query); - - if (string.Equals(DisplayOrder, "SortName", StringComparison.OrdinalIgnoreCase)) + if (!Enum.TryParse<ItemSortBy>(DisplayOrder, out var sortBy)) { - // Sort by name - return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); + sortBy = ItemSortBy.PremiereDate; } - if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase)) + if (sortBy == ItemSortBy.Default) { - // Sort by release date - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); + return items; } - // Default sorting - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); + return LibraryManager.Sort(items, user, new[] { sortBy }, SortOrder.Ascending); + } + + public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) + { + var children = base.GetChildren(user, includeLinkedChildren, query); + return Sort(children, user).ToList(); } public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { var children = base.GetRecursiveChildren(user, query); - - if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase)) - { - // Sort by release date - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); - } - - return children; + return Sort(children, user).ToList(); } public BoxSetInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 083f12746..181b9be2b 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -238,6 +238,7 @@ namespace MediaBrowser.Controller.Entities.TV if (series is not null) { id.SeriesProviderIds = series.ProviderIds; + id.SeriesDisplayOrder = series.DisplayOrder; } return id; diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs index 7dfda73bf..6c58064ce 100644 --- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -65,11 +65,6 @@ namespace MediaBrowser.Controller.Extensions public const string SqliteCacheSizeKey = "sqlite:cacheSize"; /// <summary> - /// Disable second level cache of sqlite. - /// </summary> - public const string SqliteDisableSecondLevelCacheKey = "sqlite:disableSecondLevelCache"; - - /// <summary> /// Gets a value indicating whether the application should host static web content from the <see cref="IConfiguration"/>. /// </summary> /// <param name="configuration">The configuration to retrieve the value from.</param> @@ -133,15 +128,5 @@ namespace MediaBrowser.Controller.Extensions /// <returns>The sqlite cache size.</returns> public static int? GetSqliteCacheSize(this IConfiguration configuration) => configuration.GetValue<int?>(SqliteCacheSizeKey); - - /// <summary> - /// Gets whether second level cache disabled from the <see cref="IConfiguration" />. - /// </summary> - /// <param name="configuration">The configuration to read the setting from.</param> - /// <returns>Whether second level cache disabled.</returns> - public static bool GetSqliteSecondLevelCacheDisabled(this IConfiguration configuration) - { - return configuration.GetValue<bool>(SqliteDisableSecondLevelCacheKey); - } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index c068cf055..64864bad0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -108,7 +108,6 @@ namespace MediaBrowser.Controller.MediaEncoding // AAC, FLAC, ALAC, libopus, libvorbis encoders all support at least 8 channels private static readonly Dictionary<string, int> _audioTranscodeChannelLookup = new(StringComparer.OrdinalIgnoreCase) { - { "wmav2", 2 }, { "libmp3lame", 2 }, { "libfdk_aac", 6 }, { "ac3", 6 }, @@ -410,27 +409,6 @@ namespace MediaBrowser.Controller.MediaEncoding return GetMjpegEncoder(state, encodingOptions); } - if (string.Equals(codec, "vp8", StringComparison.OrdinalIgnoreCase) - || string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) - { - return "libvpx"; - } - - if (string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)) - { - return "libvpx-vp9"; - } - - if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) - { - return "wmv2"; - } - - if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase)) - { - return "libtheora"; - } - if (_validationRegex.IsMatch(codec)) { return codec.ToLowerInvariant(); @@ -750,11 +728,6 @@ namespace MediaBrowser.Controller.MediaEncoding return "libvorbis"; } - if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase)) - { - return "wmav2"; - } - if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) { return "libopus"; @@ -1342,7 +1315,7 @@ namespace MediaBrowser.Controller.MediaEncoding // Apply aac_adtstoasc bitstream filter when media source is in mpegts. if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase) - && (string.Equals(mediaSourceContainer, "mpegts", StringComparison.OrdinalIgnoreCase) + && (string.Equals(mediaSourceContainer, "ts", StringComparison.OrdinalIgnoreCase) || string.Equals(mediaSourceContainer, "aac", StringComparison.OrdinalIgnoreCase) || string.Equals(mediaSourceContainer, "hls", StringComparison.OrdinalIgnoreCase))) { @@ -1381,20 +1354,6 @@ namespace MediaBrowser.Controller.MediaEncoding // Currently use the same buffer size for all encoders int bufsize = bitrate * 2; - if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoCodec, "libvpx-vp9", StringComparison.OrdinalIgnoreCase)) - { - // When crf is used with vpx, b:v becomes a max rate - // https://trac.ffmpeg.org/wiki/Encode/VP8 - // https://trac.ffmpeg.org/wiki/Encode/VP9 - return FormattableString.Invariant($" -maxrate:v {bitrate} -bufsize:v {bufsize} -b:v {bitrate}"); - } - - if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) - { - return FormattableString.Invariant($" -b:v {bitrate}"); - } - if (string.Equals(videoCodec, "libsvtav1", StringComparison.OrdinalIgnoreCase)) { return FormattableString.Invariant($" -b:v {bitrate} -bufsize {bufsize}"); @@ -1930,93 +1889,6 @@ namespace MediaBrowser.Controller.MediaEncoding break; } } - else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // vp8 - { - // Values 0-3, 0 being highest quality but slower - var profileScore = 0; - - var qmin = "0"; - var qmax = "50"; - var crf = "10"; - - if (isVc1) - { - profileScore++; - } - - // Max of 2 - profileScore = Math.Min(profileScore, 2); - - // http://www.webmproject.org/docs/encoder-parameters/ - param += string.Format( - CultureInfo.InvariantCulture, - " -speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", - profileScore.ToString(CultureInfo.InvariantCulture), - crf, - qmin, - qmax); - } - else if (string.Equals(videoEncoder, "libvpx-vp9", StringComparison.OrdinalIgnoreCase)) // vp9 - { - // When `-deadline` is set to `good` or `best`, `-cpu-used` ranges from 0-5. - // When `-deadline` is set to `realtime`, `-cpu-used` ranges from 0-15. - // Resources: - // * https://trac.ffmpeg.org/wiki/Encode/VP9 - // * https://superuser.com/questions/1586934 - // * https://developers.google.com/media/vp9 - param += encodingOptions.EncoderPreset switch - { - "veryslow" => " -deadline best -cpu-used 0", - "slower" => " -deadline best -cpu-used 2", - "slow" => " -deadline best -cpu-used 3", - "medium" => " -deadline good -cpu-used 0", - "fast" => " -deadline good -cpu-used 1", - "faster" => " -deadline good -cpu-used 2", - "veryfast" => " -deadline good -cpu-used 3", - "superfast" => " -deadline good -cpu-used 4", - "ultrafast" => " -deadline good -cpu-used 5", - _ => " -deadline good -cpu-used 1" - }; - - // TODO: until VP9 gets its own CRF setting, base CRF on H.265. - int h265Crf = encodingOptions.H265Crf; - int defaultVp9Crf = 31; - if (h265Crf >= 0 && h265Crf <= 51) - { - // This conversion factor is chosen to match the default CRF for H.265 to the - // recommended 1080p CRF from Google. The factor also maps the logarithmic CRF - // scale of x265 [0, 51] to that of VP9 [0, 63] relatively well. - - // Resources: - // * https://developers.google.com/media/vp9/settings/vod - const float H265ToVp9CrfConversionFactor = 1.12F; - - var vp9Crf = Convert.ToInt32(h265Crf * H265ToVp9CrfConversionFactor); - - // Encoder allows for CRF values in the range [0, 63]. - vp9Crf = Math.Clamp(vp9Crf, 0, 63); - - param += FormattableString.Invariant($" -crf {vp9Crf}"); - } - else - { - param += FormattableString.Invariant($" -crf {defaultVp9Crf}"); - } - - param += " -row-mt 1 -profile 1"; - } - else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) - { - param += " -mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; - } - else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) // asf/wmv - { - param += " -qmin 2"; - } - else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase)) - { - param += " -mbd 2"; - } param += GetVideoBitrateParam(state, videoEncoder); @@ -3151,7 +3023,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return string.Format( CultureInfo.InvariantCulture, - @"scale=-1:{1}:fast_bilinear,scale,crop,pad=max({0}\,iw):max({1}\,ih):(ow-iw)/2:(oh-ih)/2:black@0,crop={0}:{1}", + @"scale,scale=-1:{1}:fast_bilinear,crop,pad=max({0}\,iw):max({1}\,ih):(ow-iw)/2:(oh-ih)/2:black@0,crop={0}:{1}", outWidth.Value, outHeight.Value); } @@ -3950,7 +3822,7 @@ namespace MediaBrowser.Controller.MediaEncoding // sw => hw if (doOclTonemap) { - mainFilters.Add("hwupload=derive_device=d3d11va:extra_hw_frames=16"); + mainFilters.Add("hwupload=derive_device=d3d11va:extra_hw_frames=24"); mainFilters.Add("format=d3d11"); mainFilters.Add("hwmap=derive_device=opencl:mode=read"); } @@ -5423,8 +5295,8 @@ namespace MediaBrowser.Controller.MediaEncoding { // INPUT videotoolbox/memory surface(vram/uma) // this will pass-through automatically if in/out format matches. - mainFilters.Insert(0, "format=nv12|p010le|videotoolbox_vld"); mainFilters.Insert(0, "hwupload"); + mainFilters.Insert(0, "format=nv12|p010le|videotoolbox_vld"); } return (mainFilters, subFilters, overlayFilters); @@ -6457,12 +6329,6 @@ namespace MediaBrowser.Controller.MediaEncoding if (is8bitSwFormatsVt) { - if (string.Equals("avc", videoStream.Codec, StringComparison.OrdinalIgnoreCase) - || string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) - { - return GetHwaccelType(state, options, "h264", bitDepth, useHwSurface); - } - if (string.Equals("vp8", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) { return GetHwaccelType(state, options, "vp8", bitDepth, useHwSurface); @@ -6471,6 +6337,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (is8_10bitSwFormatsVt) { + if (string.Equals("avc", videoStream.Codec, StringComparison.OrdinalIgnoreCase) + || string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + return GetHwaccelType(state, options, "h264", bitDepth, useHwSurface); + } + if (string.Equals("hevc", videoStream.Codec, StringComparison.OrdinalIgnoreCase) || string.Equals("h265", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) { @@ -6592,24 +6464,15 @@ namespace MediaBrowser.Controller.MediaEncoding #nullable enable public static int GetNumberOfThreads(EncodingJobInfo? state, EncodingOptions encodingOptions, string? outputVideoCodec) { - // VP8 and VP9 encoders must have their thread counts set. - bool mustSetThreadCount = string.Equals(outputVideoCodec, "libvpx", StringComparison.OrdinalIgnoreCase) - || string.Equals(outputVideoCodec, "libvpx-vp9", StringComparison.OrdinalIgnoreCase); - var threads = state?.BaseRequest.CpuCoreLimit ?? encodingOptions.EncodingThreadCount; if (threads <= 0) { // Automatically set thread count - return mustSetThreadCount ? Math.Max(Environment.ProcessorCount - 1, 1) : 0; - } - - if (threads >= Environment.ProcessorCount) - { - return Environment.ProcessorCount; + return 0; } - return threads; + return Math.Min(threads, Environment.ProcessorCount); } #nullable disable diff --git a/MediaBrowser.Controller/MediaSegements/IMediaSegmentManager.cs b/MediaBrowser.Controller/MediaSegements/IMediaSegmentManager.cs new file mode 100644 index 000000000..4fcf084e1 --- /dev/null +++ b/MediaBrowser.Controller/MediaSegements/IMediaSegmentManager.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.MediaSegments; + +namespace MediaBrowser.Controller; + +/// <summary> +/// Defines methods for interacting with media segments. +/// </summary> +public interface IMediaSegmentManager +{ + /// <summary> + /// Returns if this item supports media segments. + /// </summary> + /// <param name="baseItem">The base Item to check.</param> + /// <returns>True if supported otherwise false.</returns> + bool IsTypeSupported(BaseItem baseItem); + + /// <summary> + /// Creates a new Media Segment associated with an Item. + /// </summary> + /// <param name="mediaSegment">The segment to create.</param> + /// <param name="segmentProviderId">The id of the Provider who created this segment.</param> + /// <returns>The created Segment entity.</returns> + Task<MediaSegmentDto> CreateSegmentAsync(MediaSegmentDto mediaSegment, string segmentProviderId); + + /// <summary> + /// Deletes a single media segment. + /// </summary> + /// <param name="segmentId">The <see cref="MediaSegment.Id"/> to delete.</param> + /// <returns>a task.</returns> + Task DeleteSegmentAsync(Guid segmentId); + + /// <summary> + /// Obtains all segments accociated with the itemId. + /// </summary> + /// <param name="itemId">The id of the <see cref="BaseItem"/>.</param> + /// <param name="typeFilter">filteres all media segments of the given type to be included. If null all types are included.</param> + /// <returns>An enumerator of <see cref="MediaSegmentDto"/>'s.</returns> + Task<IEnumerable<MediaSegmentDto>> GetSegmentsAsync(Guid itemId, IEnumerable<MediaSegmentType>? typeFilter); + + /// <summary> + /// Gets information about any media segments stored for the given itemId. + /// </summary> + /// <param name="itemId">The id of the <see cref="BaseItem"/>.</param> + /// <returns>True if there are any segments stored for the item, otherwise false.</returns> + /// TODO: this should be async but as the only caller BaseItem.GetVersionInfo isn't async, this is also not. Venson. + bool HasSegments(Guid itemId); +} diff --git a/MediaBrowser.Controller/Providers/SeasonInfo.cs b/MediaBrowser.Controller/Providers/SeasonInfo.cs index 1edceb0e4..3af5ec2a3 100644 --- a/MediaBrowser.Controller/Providers/SeasonInfo.cs +++ b/MediaBrowser.Controller/Providers/SeasonInfo.cs @@ -1,4 +1,5 @@ #pragma warning disable CA2227, CS1591 +#nullable disable using System; using System.Collections.Generic; @@ -13,5 +14,7 @@ namespace MediaBrowser.Controller.Providers } public Dictionary<string, string> SeriesProviderIds { get; set; } + + public string SeriesDisplayOrder { get; set; } } } |
