aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/IImageEncoder.cs7
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs40
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs25
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs26
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs2
-rw-r--r--MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs5
-rw-r--r--MediaBrowser.Controller/Library/IIntroProvider.cs6
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs33
-rw-r--r--MediaBrowser.Controller/Library/IMetadataFileSaver.cs5
-rw-r--r--MediaBrowser.Controller/Library/IMetadataSaver.cs6
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs2
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs2
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs127
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs6
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs6
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs25
-rw-r--r--MediaBrowser.Controller/Persistence/IRepository.cs16
-rw-r--r--MediaBrowser.Controller/Persistence/IUserDataRepository.cs3
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs6
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs6
22 files changed, 152 insertions, 208 deletions
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index e6923b55ca..85a99d62cc 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -53,7 +53,7 @@ namespace MediaBrowser.Controller.Channels
query.ChannelIds = new Guid[] { Id };
// Don't blow up here because it could cause parent screens with other content to fail
- return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).Result;
+ return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).GetAwaiter().GetResult();
}
catch
{
diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
index 4e67cfee4f..e5c8ebfaf9 100644
--- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs
+++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
@@ -74,5 +74,12 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="options">The options to use when creating the collage.</param>
/// <param name="libraryName">Optional. </param>
void CreateImageCollage(ImageCollageOptions options, string? libraryName);
+
+ /// <summary>
+ /// Creates a new splashscreen image.
+ /// </summary>
+ /// <param name="posters">The list of poster paths.</param>
+ /// <param name="backdrops">The list of backdrop paths.</param>
+ void CreateSplashscreen(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops);
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 915971adc9..c527328583 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
@@ -886,7 +887,7 @@ namespace MediaBrowser.Controller.Entities
return Name;
}
- public string GetInternalMetadataPath()
+ public virtual string GetInternalMetadataPath()
{
var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath;
@@ -1286,7 +1287,7 @@ namespace MediaBrowser.Controller.Entities
{
if (IsFileProtocol)
{
- requiresSave = await RefreshedOwnedItems(options, GetFileSystemChildren(options.DirectoryService).ToList(), cancellationToken).ConfigureAwait(false);
+ requiresSave = await RefreshedOwnedItems(options, GetFileSystemChildren(options.DirectoryService), cancellationToken).ConfigureAwait(false);
}
await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh
@@ -1363,7 +1364,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="fileSystemChildren">The list of filesystem children.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns>
- protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder))
{
@@ -1380,7 +1381,7 @@ namespace MediaBrowser.Controller.Entities
return directoryService.GetFileSystemEntries(path);
}
- private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
var newExtraIds = extras.Select(i => i.Id).ToArray();
@@ -2041,27 +2042,32 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Validates that images within the item are still on the filesystem.
/// </summary>
- /// <param name="directoryService">The directory service to use.</param>
/// <returns><c>true</c> if the images validate, <c>false</c> if not.</returns>
- public bool ValidateImages(IDirectoryService directoryService)
+ public bool ValidateImages()
{
- var allFiles = ImageInfos
- .Where(i => i.IsLocalFile)
- .Select(i => System.IO.Path.GetDirectoryName(i.Path))
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .SelectMany(path => directoryService.GetFilePaths(path))
- .ToList();
+ List<ItemImageInfo> deletedImages = null;
+ foreach (var imageInfo in ImageInfos)
+ {
+ if (!imageInfo.IsLocalFile)
+ {
+ continue;
+ }
- var deletedImages = ImageInfos
- .Where(image => image.IsLocalFile && !allFiles.Contains(image.Path, StringComparison.OrdinalIgnoreCase))
- .ToList();
+ if (File.Exists(imageInfo.Path))
+ {
+ continue;
+ }
+
+ (deletedImages ??= new List<ItemImageInfo>()).Add(imageInfo);
+ }
- if (deletedImages.Count > 0)
+ var anyImagesRemoved = deletedImages?.Count > 0;
+ if (anyImagesRemoved)
{
RemoveImages(deletedImages);
}
- return deletedImages.Count > 0;
+ return anyImagesRemoved;
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 55551e70ee..cb5ff6eec5 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -783,11 +783,10 @@ namespace MediaBrowser.Controller.Entities
returnItems = returnItems.Skip(startIndex.Value);
}
- return new QueryResult<BaseItem>
- {
- TotalRecordCount = totalCount,
- Items = returnItems.ToArray()
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ returnItems.ToArray());
}
private bool RequiresPostFiltering2(InternalItemsQuery query)
@@ -849,6 +848,18 @@ namespace MediaBrowser.Controller.Entities
return true;
}
+ if (query.HasThemeSong.HasValue)
+ {
+ Logger.LogDebug("Query requires post-filtering due to HasThemeSong");
+ return true;
+ }
+
+ if (query.HasThemeVideo.HasValue)
+ {
+ Logger.LogDebug("Query requires post-filtering due to HasThemeVideo");
+ return true;
+ }
+
// Filter by VideoType
if (query.VideoTypes.Length > 0)
{
@@ -965,7 +976,7 @@ namespace MediaBrowser.Controller.Entities
query.ChannelIds = new[] { ChannelId };
// Don't blow up here because it could cause parent screens with other content to fail
- return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).Result;
+ return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).GetAwaiter().GetResult();
}
catch
{
@@ -1586,7 +1597,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => i.Item2 != null);
}
- protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var changesFound = false;
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index fe44f1169e..279206da48 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -238,12 +238,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> ConvertToResult(List<BaseItem> items)
{
- var arr = items.ToArray();
- return new QueryResult<BaseItem>
- {
- Items = arr,
- TotalRecordCount = arr.Length
- };
+ return new QueryResult<BaseItem>(items);
}
private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
@@ -414,16 +409,6 @@ namespace MediaBrowser.Controller.Entities
return _libraryManager.GetItemsResult(query);
}
- private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
- where T : BaseItem
- {
- return new QueryResult<BaseItem>
- {
- Items = result.Items, // TODO Fix The co-variant conversion between T[] and BaseItem[], this can generate runtime issues if T is not BaseItem.
- TotalRecordCount = result.TotalRecordCount
- };
- }
-
private QueryResult<BaseItem> GetResult<T>(
IEnumerable<T> items,
InternalItemsQuery query)
@@ -483,11 +468,10 @@ namespace MediaBrowser.Controller.Entities
itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
}
- return new QueryResult<BaseItem>
- {
- TotalRecordCount = totalCount,
- Items = itemsArray
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ itemsArray);
}
public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager)
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 3e125602aa..5ab7808c36 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -419,7 +419,7 @@ namespace MediaBrowser.Controller.Entities
return updateType;
}
- protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs
index f9285c7682..957ce67443 100644
--- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs
+++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs
@@ -15,6 +15,11 @@ namespace MediaBrowser.Controller.Extensions
public const string DefaultRedirectKey = "DefaultRedirectPath";
/// <summary>
+ /// The key for the address override option.
+ /// </summary>
+ public const string AddressOverrideKey = "PublishedServerUrl";
+
+ /// <summary>
/// The key for a setting that indicates whether the application should host web client content.
/// </summary>
public const string HostWebClientKey = "hostwebclient";
diff --git a/MediaBrowser.Controller/Library/IIntroProvider.cs b/MediaBrowser.Controller/Library/IIntroProvider.cs
index a74d1b9f0b..4a9721acbe 100644
--- a/MediaBrowser.Controller/Library/IIntroProvider.cs
+++ b/MediaBrowser.Controller/Library/IIntroProvider.cs
@@ -24,11 +24,5 @@ namespace MediaBrowser.Controller.Library
/// <param name="user">The user.</param>
/// <returns>IEnumerable{System.String}.</returns>
Task<IEnumerable<IntroInfo>> GetIntros(BaseItem item, Jellyfin.Data.Entities.User user);
-
- /// <summary>
- /// Gets all intro files.
- /// </summary>
- /// <returns>IEnumerable{System.String}.</returns>
- IEnumerable<string> GetAllIntroFiles();
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 8db5283302..313d27ce62 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -138,10 +138,10 @@ namespace MediaBrowser.Controller.Library
/// Validate and refresh the People sub-set of the IBN.
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
/// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress);
+ Task ValidatePeopleAsync(IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
/// Reloads the root media folder.
@@ -151,11 +151,6 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task.</returns>
Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken);
- /// <summary>
- /// Queues the library scan.
- /// </summary>
- void QueueLibraryScan();
-
Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false);
/// <summary>
@@ -182,12 +177,6 @@ namespace MediaBrowser.Controller.Library
Task<IEnumerable<Video>> GetIntros(BaseItem item, User user);
/// <summary>
- /// Gets all intro files.
- /// </summary>
- /// <returns>IEnumerable{System.String}.</returns>
- IEnumerable<string> GetAllIntroFiles();
-
- /// <summary>
/// Adds the parts.
/// </summary>
/// <param name="rules">The rules.</param>
@@ -434,7 +423,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="fileSystemChildren">The file system children.</param>
/// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param>
/// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
- IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService);
+ IEnumerable<BaseItem> FindExtras(BaseItem owner, IReadOnlyList<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService);
/// <summary>
/// Gets the collection folders.
@@ -508,15 +497,6 @@ namespace MediaBrowser.Controller.Library
string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem = null);
/// <summary>
- /// Substitutes the path.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="from">From.</param>
- /// <param name="to">To.</param>
- /// <returns>System.String.</returns>
- string SubstitutePath(string path, string from, string to);
-
- /// <summary>
/// Converts the image to local.
/// </summary>
/// <param name="item">The item.</param>
@@ -587,15 +567,8 @@ namespace MediaBrowser.Controller.Library
int GetCount(InternalItemsQuery query);
- void AddExternalSubtitleStreams(
- List<MediaStream> streams,
- string videoPath,
- string[] files);
-
Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason);
- BaseItem GetParentItem(string parentId, Guid? userId);
-
BaseItem GetParentItem(Guid? parentId, Guid? userId);
}
}
diff --git a/MediaBrowser.Controller/Library/IMetadataFileSaver.cs b/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
index 9c6f03a232..842c687d1d 100644
--- a/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
@@ -13,9 +13,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>System.String.</returns>
string GetSavePath(BaseItem item);
}
-
- public interface IConfigurableProvider
- {
- bool IsEnabled { get; }
- }
}
diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs
index d963fd2491..eed6613459 100644
--- a/MediaBrowser.Controller/Library/IMetadataSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs
@@ -1,6 +1,5 @@
-#nullable disable
-
using System.Threading;
+using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
@@ -29,6 +28,7 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- void Save(BaseItem item, CancellationToken cancellationToken);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ Task SaveAsync(BaseItem item, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 6dc5665b24..46bdca3027 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -188,7 +188,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Recommended programs.</returns>
- QueryResult<BaseItemDto> GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
+ Task<QueryResult<BaseItemDto>> GetRecommendedProgramsAsync(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
/// <summary>
/// Gets the recommended programs internal.
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index e63874f21e..335222da96 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.LiveTv
{
Id = Id.ToString("N", CultureInfo.InvariantCulture),
Protocol = PathProtocol ?? MediaProtocol.File,
- MediaStreams = new List<MediaStream>(),
+ MediaStreams = Array.Empty<MediaStream>(),
Name = Name,
Path = Path,
RunTimeTicks = RunTimeTicks,
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 432159d5d0..e76a478a53 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -52,6 +52,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index bde10dbbfc..f7248acacd 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -12,6 +12,7 @@ using System.Text.RegularExpressions;
using System.Threading;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
@@ -28,7 +29,7 @@ namespace MediaBrowser.Controller.MediaEncoding
private const string VideotoolboxAlias = "vt";
private const string OpenclAlias = "ocl";
private const string CudaAlias = "cu";
-
+ private readonly IApplicationPaths _appPaths;
private readonly IMediaEncoder _mediaEncoder;
private readonly ISubtitleEncoder _subtitleEncoder;
@@ -51,9 +52,11 @@ namespace MediaBrowser.Controller.MediaEncoding
};
public EncodingHelper(
+ IApplicationPaths appPaths,
IMediaEncoder mediaEncoder,
ISubtitleEncoder subtitleEncoder)
{
+ _appPaths = appPaths;
_mediaEncoder = mediaEncoder;
_subtitleEncoder = subtitleEncoder;
}
@@ -81,7 +84,6 @@ namespace MediaBrowser.Controller.MediaEncoding
{ "vaapi", hwEncoder + "_vaapi" },
{ "videotoolbox", hwEncoder + "_videotoolbox" },
{ "v4l2m2m", hwEncoder + "_v4l2m2m" },
- { "omx", hwEncoder + "_omx" },
};
if (!string.IsNullOrEmpty(hwType)
@@ -578,13 +580,13 @@ namespace MediaBrowser.Controller.MediaEncoding
options);
}
- private string GetVaapiDeviceArgs(string renderNodePath, string kernelDriver, string driver, string alias)
+ private string GetVaapiDeviceArgs(string renderNodePath, string driver, string kernelDriver, string alias)
{
alias ??= VaapiAlias;
renderNodePath = renderNodePath ?? "/dev/dri/renderD128";
- var options = string.IsNullOrEmpty(kernelDriver) || string.IsNullOrEmpty(driver)
+ var options = string.IsNullOrEmpty(driver)
? renderNodePath
- : ",kernel_driver=" + kernelDriver + ",driver=" + driver;
+ : ",driver=" + driver + (string.IsNullOrEmpty(kernelDriver) ? string.Empty : ",kernel_driver=" + kernelDriver);
return string.Format(
CultureInfo.InvariantCulture,
@@ -599,7 +601,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (OperatingSystem.IsLinux())
{
// derive qsv from vaapi device
- return GetVaapiDeviceArgs(null, "i915", "iHD", VaapiAlias) + arg + "@" + VaapiAlias;
+ return GetVaapiDeviceArgs(null, "iHD", "i915", VaapiAlias) + arg + "@" + VaapiAlias;
}
if (OperatingSystem.IsWindows())
@@ -688,7 +690,19 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Empty;
}
- args.Append(GetVaapiDeviceArgs(options.VaapiDevice, null, null, VaapiAlias));
+ if (_mediaEncoder.IsVaapiDeviceInteliHD)
+ {
+ args.Append(GetVaapiDeviceArgs(null, "iHD", null, VaapiAlias));
+ }
+ else if (_mediaEncoder.IsVaapiDeviceInteli965)
+ {
+ args.Append(GetVaapiDeviceArgs(null, "i965", null, VaapiAlias));
+ }
+ else
+ {
+ args.Append(GetVaapiDeviceArgs(options.VaapiDevice, null, null, VaapiAlias));
+ }
+
var filterDevArgs = GetFilterHwDeviceArgs(VaapiAlias);
if (isHwTonemapAvailable && IsOpenclFullSupported())
@@ -768,10 +782,6 @@ namespace MediaBrowser.Controller.MediaEncoding
args.Append(GetCudaDeviceArgs(0, CudaAlias))
.Append(GetFilterHwDeviceArgs(CudaAlias));
-
- // workaround for "No decoder surfaces left" error,
- // but will increase vram usage. https://trac.ffmpeg.org/ticket/7562
- args.Append(" -extra_hw_frames 3");
}
else if (string.Equals(optHwaccelType, "amf", StringComparison.OrdinalIgnoreCase))
{
@@ -1080,6 +1090,12 @@ namespace MediaBrowser.Controller.MediaEncoding
var alphaParam = enableAlpha ? ":alpha=1" : string.Empty;
var sub2videoParam = enableSub2video ? ":sub2video=1" : string.Empty;
+ var fontPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
+ var fontParam = string.Format(
+ CultureInfo.InvariantCulture,
+ ":fontsdir='{0}'",
+ _mediaEncoder.EscapeSubtitleFilterPath(fontPath));
+
// TODO
// var fallbackFontPath = Path.Combine(_appPaths.ProgramDataPath, "fonts", "DroidSansFallback.ttf");
// string fallbackFontParam = string.Empty;
@@ -1120,11 +1136,12 @@ namespace MediaBrowser.Controller.MediaEncoding
// TODO: Perhaps also use original_size=1920x800 ??
return string.Format(
CultureInfo.InvariantCulture,
- "subtitles=f='{0}'{1}{2}{3}{4}",
+ "subtitles=f='{0}'{1}{2}{3}{4}{5}",
_mediaEncoder.EscapeSubtitleFilterPath(subtitlePath),
charsetParam,
alphaParam,
sub2videoParam,
+ fontParam,
// fallbackFontParam,
setPtsParam);
}
@@ -1133,11 +1150,12 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
- "subtitles='{0}:si={1}{2}{3}'{4}",
+ "subtitles=f='{0}':si={1}{2}{3}{4}{5}",
_mediaEncoder.EscapeSubtitleFilterPath(mediaPath),
state.InternalSubtitleStreamOffset.ToString(CultureInfo.InvariantCulture),
alphaParam,
sub2videoParam,
+ fontParam,
// fallbackFontParam,
setPtsParam);
}
@@ -1281,11 +1299,6 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -low_power 1";
}
- if (string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
- {
- param += " -pix_fmt nv21";
- }
-
var isVc1 = string.Equals(state.VideoStream?.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
var isLibX265 = string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase);
@@ -1343,29 +1356,37 @@ namespace MediaBrowser.Controller.MediaEncoding
switch (encodingOptions.EncoderPreset)
{
case "veryslow":
-
- param += " -preset slow"; // lossless is only supported on maxwell and newer(2014+)
+ param += " -preset p7";
break;
case "slow":
+ param += " -preset p6";
+ break;
+
case "slower":
- param += " -preset slow";
+ param += " -preset p5";
break;
case "medium":
- param += " -preset medium";
+ param += " -preset p4";
break;
case "fast":
+ param += " -preset p3";
+ break;
+
case "faster":
+ param += " -preset p2";
+ break;
+
case "veryfast":
case "superfast":
case "ultrafast":
- param += " -preset fast";
+ param += " -preset p1";
break;
default:
- param += " -preset default";
+ param += " -preset p4";
break;
}
}
@@ -1571,10 +1592,8 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(profile))
{
- if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
{
- // not supported by h264_omx
param += " -profile:v:0 " + profile;
}
}
@@ -1613,8 +1632,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// NVENC cannot adjust the given level, just throw an error.
// level option may cause corrupted frames on AMD VAAPI.
}
- else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)
- || !string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
+ else if (!string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
{
param += " -level " + level;
}
@@ -2167,6 +2185,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// Important: If this is ever re-enabled, make sure not to use it with wtv because it breaks seeking
if (!string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase)
&& state.TranscodingType != TranscodingJobType.Progressive
+ && state.TranscodingType != TranscodingJobType.Hls
&& !state.EnableBreakOnNonKeyFrames(outputVideoCodec)
&& (state.BaseRequest.StartTimeTicks ?? 0) > 0)
{
@@ -2695,6 +2714,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty;
var isSwDecoder = string.IsNullOrEmpty(vidDecoder);
var isVaapiEncoder = vidEncoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase);
+ var isV4l2Encoder = vidEncoder.Contains("h264_v4l2m2m", StringComparison.OrdinalIgnoreCase);
var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
@@ -2723,6 +2743,10 @@ namespace MediaBrowser.Controller.MediaEncoding
{
outFormat = "nv12";
}
+ else if (isV4l2Encoder)
+ {
+ outFormat = "yuv420p";
+ }
// sw scale
mainFilters.Add(swScaleFilter);
@@ -4268,11 +4292,6 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return GetVideotoolboxVidDecoder(state, options, videoStream, bitDepth);
}
-
- if (string.Equals(options.HardwareAccelerationType, "omx", StringComparison.OrdinalIgnoreCase))
- {
- return GetOmxVidDecoder(state, options, videoStream, bitDepth);
- }
}
var whichCodec = videoStream.Codec;
@@ -4411,7 +4430,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{
if (options.EnableEnhancedNvdecDecoder && isCudaSupported && isCodecAvailable)
{
- return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty) + (isAv1 ? " -c:v av1" : string.Empty);
+ // set -threads 1 to nvdec decoder explicitly since it doesn't implement threading support.
+ return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty);
}
}
@@ -4747,43 +4767,6 @@ namespace MediaBrowser.Controller.MediaEncoding
return null;
}
- public string GetOmxVidDecoder(EncodingJobInfo state, EncodingOptions options, MediaStream videoStream, int bitDepth)
- {
- if (!OperatingSystem.IsLinux()
- || !string.Equals(options.HardwareAccelerationType, "omx", StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- var is8bitSwFormatsOmx = string.Equals("yuv420p", videoStream.PixelFormat, StringComparison.OrdinalIgnoreCase);
-
- if (is8bitSwFormatsOmx)
- {
- if (string.Equals("avc", videoStream.Codec, StringComparison.OrdinalIgnoreCase)
- || string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase))
- {
- return GetHwDecoderName(options, "h264", "mmal", "h264", bitDepth);
- }
-
- if (string.Equals("mpeg2video", videoStream.Codec, StringComparison.OrdinalIgnoreCase))
- {
- return GetHwDecoderName(options, "mpeg2", "mmal", "mpeg2video", bitDepth);
- }
-
- if (string.Equals("mpeg4", videoStream.Codec, StringComparison.OrdinalIgnoreCase))
- {
- return GetHwDecoderName(options, "mpeg4", "mmal", "mpeg4", bitDepth);
- }
-
- if (string.Equals("vc1", videoStream.Codec, StringComparison.OrdinalIgnoreCase))
- {
- return GetHwDecoderName(options, "vc1", "mmal", "vc1", bitDepth);
- }
- }
-
- return null;
- }
-
/// <summary>
/// Gets the number of threads.
/// </summary>
diff --git a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs
index 4e7e266245..a2b6be1e6d 100644
--- a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.MediaEncoding
@@ -17,5 +18,10 @@ namespace MediaBrowser.Controller.MediaEncoding
string mediaSourceId,
int attachmentStreamIndex,
CancellationToken cancellationToken);
+ Task ExtractAllAttachments(
+ string inputFile,
+ MediaSourceInfo mediaSource,
+ string outputPath,
+ CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index fd3eb81056..6bf3e7b469 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -26,6 +26,12 @@ namespace MediaBrowser.Controller.MediaEncoding
string EncoderPath { get; }
/// <summary>
+ /// Gets the probe path.
+ /// </summary>
+ /// <value>The probe path.</value>
+ string ProbePath { get; }
+
+ /// <summary>
/// Gets the version of encoder.
/// </summary>
/// <returns>The version of encoder.</returns>
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 837bf0bb20..24f7b5cd36 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -15,16 +15,9 @@ namespace MediaBrowser.Controller.Persistence
/// <summary>
/// Provides an interface to implement an Item repository.
/// </summary>
- public interface IItemRepository : IRepository
+ public interface IItemRepository : IDisposable
{
/// <summary>
- /// Saves an item.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- void SaveItem(BaseItem item, CancellationToken cancellationToken);
-
- /// <summary>
/// Deletes the item.
/// </summary>
/// <param name="id">The identifier.</param>
@@ -81,7 +74,7 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="id">The identifier.</param>
/// <param name="streams">The streams.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- void SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken);
+ void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken);
/// <summary>
/// Gets the media attachments.
@@ -99,13 +92,6 @@ namespace MediaBrowser.Controller.Persistence
void SaveMediaAttachments(Guid id, IReadOnlyList<MediaAttachment> attachments, CancellationToken cancellationToken);
/// <summary>
- /// Gets the item ids.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <returns>IEnumerable&lt;Guid&gt;.</returns>
- QueryResult<Guid> GetItemIds(InternalItemsQuery query);
-
- /// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
@@ -141,13 +127,6 @@ namespace MediaBrowser.Controller.Persistence
List<string> GetPeopleNames(InternalPeopleQuery query);
/// <summary>
- /// Gets the item ids with path.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <returns>QueryResult&lt;Tuple&lt;Guid, System.String&gt;&gt;.</returns>
- List<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
-
- /// <summary>
/// Gets the item list.
/// </summary>
/// <param name="query">The query.</param>
diff --git a/MediaBrowser.Controller/Persistence/IRepository.cs b/MediaBrowser.Controller/Persistence/IRepository.cs
deleted file mode 100644
index 42f2850762..0000000000
--- a/MediaBrowser.Controller/Persistence/IRepository.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace MediaBrowser.Controller.Persistence
-{
- /// <summary>
- /// Provides a base interface for all the repository interfaces.
- /// </summary>
- public interface IRepository : IDisposable
- {
- /// <summary>
- /// Gets the name of the repository.
- /// </summary>
- /// <value>The name.</value>
- string Name { get; }
- }
-}
diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
index c43acfb6de..f2fb2826a0 100644
--- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
@@ -1,5 +1,6 @@
#nullable disable
+using System;
using System.Collections.Generic;
using System.Threading;
using MediaBrowser.Controller.Entities;
@@ -9,7 +10,7 @@ namespace MediaBrowser.Controller.Persistence
/// <summary>
/// Provides an interface to implement a UserData repository.
/// </summary>
- public interface IUserDataRepository : IRepository
+ public interface IUserDataRepository : IDisposable
{
/// <summary>
/// Saves the user data.
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 9f7a76be64..44bc4a50cb 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -156,7 +156,8 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
- void SaveMetadata(BaseItem item, ItemUpdateType updateType);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType);
/// <summary>
/// Saves the metadata.
@@ -164,7 +165,8 @@ namespace MediaBrowser.Controller.Providers
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <param name="savers">The metadata savers.</param>
- void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers);
/// <summary>
/// Gets the metadata options.
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index 6134c0cf33..c2ca233868 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -39,6 +39,8 @@ namespace MediaBrowser.Controller.Session
AdditionalUsers = Array.Empty<SessionUserInfo>();
PlayState = new PlayerStateInfo();
SessionControllers = Array.Empty<ISessionController>();
+ NowPlayingQueue = Array.Empty<QueueItem>();
+ NowPlayingQueueFullItems = Array.Empty<BaseItemDto>();
}
public PlayerStateInfo PlayState { get; set; }
@@ -219,7 +221,9 @@ namespace MediaBrowser.Controller.Session
}
}
- public QueueItem[] NowPlayingQueue { get; set; }
+ public IReadOnlyList<QueueItem> NowPlayingQueue { get; set; }
+
+ public IReadOnlyList<BaseItemDto> NowPlayingQueueFullItems { get; set; }
public bool HasCustomDeviceName { get; set; }