aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/azure-pipelines-package.yml22
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj8
-rw-r--r--Emby.Server.Implementations/IO/ManagedFileSystem.cs10
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs44
-rw-r--r--Emby.Server.Implementations/Localization/Core/de.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/th.json4
-rw-r--r--Jellyfin.Api/Jellyfin.Api.csproj2
-rw-r--r--Jellyfin.Data/Jellyfin.Data.csproj4
-rw-r--r--Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj4
-rw-r--r--Jellyfin.Server.Implementations/Users/UserManager.cs8
-rw-r--r--Jellyfin.Server/Jellyfin.Server.csproj4
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs5
-rw-r--r--MediaBrowser.Api/System/ActivityLogService.cs5
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj4
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs305
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj2
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj4
-rw-r--r--MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs2
-rw-r--r--tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj2
-rw-r--r--tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj2
21 files changed, 277 insertions, 170 deletions
diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml
index 5539b16ab..68ec427cb 100644
--- a/.ci/azure-pipelines-package.yml
+++ b/.ci/azure-pipelines-package.yml
@@ -139,3 +139,25 @@ jobs:
sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber)
rm $0
exit
+
+- job: PublishNuget
+ displayName: 'Publish NuGet packages'
+ dependsOn:
+ - BuildPackage
+ condition: and((succeeded'BuildPackage'), startsWith(variables['Build.SourceBranch'], 'refs/tags'))
+
+ pool:
+ vmImage: 'ubuntu-latest'
+
+ steps:
+ - task: NuGetCommand@2
+ inputs:
+ command: 'pack'
+ packagesToPack: Jellyfin.Data/Jellyfin.Data.csproj;MediaBrowser.Common/MediaBrowser.Common.csproj;MediaBrowser.Controller/MediaBrowser.Controller.csproj;MediaBrowser.Model/MediaBrowser.Model.csproj;Emby.Naming/Emby.Naming.csproj
+ packDestination: '$(Build.ArtifactStagingDirectory)'
+
+ - task: NuGetCommand@2
+ inputs:
+ command: 'push'
+ packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg'
+ includeNugetOrg: 'true'
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index f7ad59c10..4351b9aa5 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -34,10 +34,10 @@
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
- <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
<PackageReference Include="Mono.Nat" Version="2.0.1" />
<PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
<PackageReference Include="ServiceStack.Text.Core" Version="5.9.0" />
diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index a3a3f91b7..ab6483bf9 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -245,6 +245,16 @@ namespace Emby.Server.Implementations.IO
if (info is FileInfo fileInfo)
{
result.Length = fileInfo.Length;
+
+ // Issue #2354 get the size of files behind symbolic links
+ if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
+ {
+ using (Stream thisFileStream = File.OpenRead(fileInfo.FullName))
+ {
+ result.Length = thisFileStream.Length;
+ }
+ }
+
result.DirectoryName = fileInfo.DirectoryName;
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 77d44e131..c27b73c74 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -341,7 +341,7 @@ namespace Emby.Server.Implementations.Library
if (item is LiveTvProgram)
{
_logger.LogDebug(
- "Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
+ "Removing item, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
item.GetType().Name,
item.Name ?? "Unknown name",
item.Path ?? string.Empty,
@@ -350,7 +350,7 @@ namespace Emby.Server.Implementations.Library
else
{
_logger.LogInformation(
- "Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
+ "Removing item, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
item.GetType().Name,
item.Name ?? "Unknown name",
item.Path ?? string.Empty,
@@ -368,7 +368,12 @@ namespace Emby.Server.Implementations.Library
continue;
}
- _logger.LogDebug("Deleting path {MetadataPath}", metadataPath);
+ _logger.LogDebug(
+ "Deleting metadata path, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
+ item.GetType().Name,
+ item.Name ?? "Unknown name",
+ metadataPath,
+ item.Id);
try
{
@@ -392,7 +397,13 @@ namespace Emby.Server.Implementations.Library
{
try
{
- _logger.LogDebug("Deleting path {path}", fileSystemInfo.FullName);
+ _logger.LogInformation(
+ "Deleting item path, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
+ item.GetType().Name,
+ item.Name ?? "Unknown name",
+ fileSystemInfo.FullName,
+ item.Id);
+
if (fileSystemInfo.IsDirectory)
{
Directory.Delete(fileSystemInfo.FullName, true);
@@ -3000,21 +3011,6 @@ namespace Emby.Server.Implementations.Library
});
}
- private static bool ValidateNetworkPath(string path)
- {
- // if (Environment.OSVersion.Platform == PlatformID.Win32NT)
- //{
- // // We can't validate protocol-based paths, so just allow them
- // if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)
- // {
- // return Directory.Exists(path);
- // }
- //}
-
- // Without native support for unc, we cannot validate this when running under mono
- return true;
- }
-
private const string ShortcutFileExtension = ".mblink";
public void AddMediaPath(string virtualFolderName, MediaPathInfo pathInfo)
@@ -3041,11 +3037,6 @@ namespace Emby.Server.Implementations.Library
throw new FileNotFoundException("The path does not exist.");
}
- if (!string.IsNullOrWhiteSpace(pathInfo.NetworkPath) && !ValidateNetworkPath(pathInfo.NetworkPath))
- {
- throw new FileNotFoundException("The network path does not exist.");
- }
-
var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
@@ -3084,11 +3075,6 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(pathInfo));
}
- if (!string.IsNullOrWhiteSpace(pathInfo.NetworkPath) && !ValidateNetworkPath(pathInfo.NetworkPath))
- {
- throw new FileNotFoundException("The network path does not exist.");
- }
-
var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index 82df43be1..a6e9779c9 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/Emby.Server.Implementations/Localization/Core/de.json
@@ -3,7 +3,7 @@
"AppDeviceValues": "App: {0}, Gerät: {1}",
"Application": "Anwendung",
"Artists": "Interpreten",
- "AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich authentifiziert",
+ "AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
"Books": "Bücher",
"CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen",
"Channels": "Kanäle",
diff --git a/Emby.Server.Implementations/Localization/Core/th.json b/Emby.Server.Implementations/Localization/Core/th.json
index 32538ac03..576aaeb1b 100644
--- a/Emby.Server.Implementations/Localization/Core/th.json
+++ b/Emby.Server.Implementations/Localization/Core/th.json
@@ -67,5 +67,7 @@
"Artists": "นักแสดง",
"Application": "แอปพลิเคชั่น",
"AppDeviceValues": "App: {0}, อุปกรณ์: {1}",
- "Albums": "อัลบั้ม"
+ "Albums": "อัลบั้ม",
+ "ScheduledTaskStartedWithName": "{0} เริ่มต้น",
+ "ScheduledTaskFailedWithName": "{0} ล้มเหลว"
}
diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj
index 93c4612b6..3693d5122 100644
--- a/Jellyfin.Api/Jellyfin.Api.csproj
+++ b/Jellyfin.Api/Jellyfin.Api.csproj
@@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
- <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.5" />
+ <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
</ItemGroup>
diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj
index 58d1ba2f3..8ce0f3848 100644
--- a/Jellyfin.Data/Jellyfin.Data.csproj
+++ b/Jellyfin.Data/Jellyfin.Data.csproj
@@ -19,8 +19,8 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.5" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.5" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.6" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.6" />
</ItemGroup>
</Project>
diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
index dcac1b34b..21748ca19 100644
--- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
+++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
@@ -24,11 +24,11 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.5">
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
- <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.5">
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs
index 9aff808db..e3a7d5467 100644
--- a/Jellyfin.Server.Implementations/Users/UserManager.cs
+++ b/Jellyfin.Server.Implementations/Users/UserManager.cs
@@ -671,7 +671,13 @@ namespace Jellyfin.Server.Implementations.Users
public void UpdatePolicy(Guid userId, UserPolicy policy)
{
var dbContext = _dbProvider.CreateContext();
- var user = dbContext.Users.Find(userId) ?? throw new ArgumentException("No user exists with given Id!");
+ var user = dbContext.Users
+ .Include(u => u.Permissions)
+ .Include(u => u.Preferences)
+ .Include(u => u.AccessSchedules)
+ .Include(u => u.ProfileImage)
+ .FirstOrDefault(u => u.Id == userId)
+ ?? throw new ArgumentException("No user exists with given Id!");
// The default number of login attempts is 3, but for some god forsaken reason it's sent to the server as "0"
int? maxLoginAttempts = policy.LoginAttemptsBeforeLockout switch
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index 6a2d252ab..b1bd38cff 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -41,8 +41,8 @@
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0" />
- <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.6" />
<PackageReference Include="prometheus-net" Version="3.6.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="3.6.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 8426a9a4f..575b1157a 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -895,6 +895,11 @@ namespace MediaBrowser.Api.Images
// Handle image/png; charset=utf-8
mimeType = mimeType.Split(';').FirstOrDefault();
var userDataPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
+ if (user.ProfileImage != null)
+ {
+ _userManager.ClearProfileImage(user);
+ }
+
user.ProfileImage = new Jellyfin.Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType)));
await _providerManager
diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs
index 7ca31c21a..4afa6e114 100644
--- a/MediaBrowser.Api/System/ActivityLogService.cs
+++ b/MediaBrowser.Api/System/ActivityLogService.cs
@@ -56,7 +56,10 @@ namespace MediaBrowser.Api.System
DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
- entries => entries.Where(entry => entry.DateCreated >= minDate));
+ entries => entries.Where(entry => entry.DateCreated >= minDate
+ && (!request.HasUserId.HasValue || (request.HasUserId.Value
+ ? entry.UserId != Guid.Empty
+ : entry.UserId == Guid.Empty))));
var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit);
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index c9ca153c7..7380f39fd 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -17,8 +17,8 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.6" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
</ItemGroup>
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 73e966344..67f17f7a5 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.6" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 534e0c372..ffbda42c3 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Jellyfin.Data.Enums;
@@ -449,41 +450,59 @@ namespace MediaBrowser.Controller.MediaEncoding
var arg = new StringBuilder();
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty;
var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty;
- bool isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
- bool isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
- bool isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
- bool isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
+ var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
+ var isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
+ var isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
+ var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
+ var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
- if (state.IsVideoRequest
- && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ if (!IsCopyCodec(outputVideoCodec))
{
- if (isVaapiDecoder)
+ if (state.IsVideoRequest
+ && IsVaapiSupported(state)
+ && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
{
- arg.Append("-hwaccel_output_format vaapi ")
- .Append("-vaapi_device ")
- .Append(encodingOptions.VaapiDevice)
- .Append(" ");
- }
- else if (!isVaapiDecoder && isVaapiEncoder)
- {
- arg.Append("-vaapi_device ")
- .Append(encodingOptions.VaapiDevice)
- .Append(" ");
+ if (isVaapiDecoder)
+ {
+ arg.Append("-hwaccel_output_format vaapi ")
+ .Append("-vaapi_device ")
+ .Append(encodingOptions.VaapiDevice)
+ .Append(" ");
+ }
+ else if (!isVaapiDecoder && isVaapiEncoder)
+ {
+ arg.Append("-vaapi_device ")
+ .Append(encodingOptions.VaapiDevice)
+ .Append(" ");
+ }
}
- }
- if (state.IsVideoRequest
- && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
- {
- var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
-
- if (!hasTextSubs)
+ if (state.IsVideoRequest
+ && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
- if (isQsvEncoder)
+ var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+
+ if (isQsvEncoder)
{
if (isQsvDecoder)
{
- arg.Append("-hwaccel qsv -init_hw_device qsv=hw ");
+ if (isLinux)
+ {
+ if (hasGraphicalSubs)
+ {
+ arg.Append("-init_hw_device qsv=hw -filter_hw_device hw ");
+ }
+ else
+ {
+ arg.Append("-hwaccel qsv -init_hw_device qsv=hw ");
+ }
+ }
+
+ if (isWindows)
+ {
+ arg.Append("-hwaccel qsv -init_hw_device qsv=hw ");
+ }
}
// While using SW decoder
else
@@ -806,6 +825,34 @@ namespace MediaBrowser.Controller.MediaEncoding
break;
}
}
+ else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase))
+ {
+ switch (encodingOptions.EncoderPreset)
+ {
+ case "veryslow":
+ case "slow":
+ case "slower":
+ param += "-quality quality";
+ break;
+
+ case "medium":
+ param += "-quality balanced";
+ break;
+
+ case "fast":
+ case "faster":
+ case "veryfast":
+ case "superfast":
+ case "ultrafast":
+ param += "-quality speed";
+ break;
+
+ default:
+ param += "-quality speed";
+ break;
+ }
+ }
else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // webm
{
// Values 0-3, 0 being highest quality but slower
@@ -1555,28 +1602,28 @@ namespace MediaBrowser.Controller.MediaEncoding
var index = outputSizeParam.IndexOf("hwdownload", StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
- outputSizeParam = "," + outputSizeParam.Substring(index);
+ outputSizeParam = outputSizeParam.Substring(index);
}
else
{
index = outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
- outputSizeParam = "," + outputSizeParam.Substring(index);
+ outputSizeParam = outputSizeParam.Substring(index);
}
else
{
index = outputSizeParam.IndexOf("yadif", StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
- outputSizeParam = "," + outputSizeParam.Substring(index);
+ outputSizeParam = outputSizeParam.Substring(index);
}
else
{
index = outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
- outputSizeParam = "," + outputSizeParam.Substring(index);
+ outputSizeParam = outputSizeParam.Substring(index);
}
}
}
@@ -1585,43 +1632,30 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoSizeParam = string.Empty;
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty;
+ var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
// Setup subtitle scaling
if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue)
{
- videoSizeParam = string.Format(
- CultureInfo.InvariantCulture,
- "scale={0}:{1}",
- state.VideoStream.Width.Value,
- state.VideoStream.Height.Value);
+ // Adjust the size of graphical subtitles to fit the video stream.
+ var videoStream = state.VideoStream;
+ var inputWidth = videoStream?.Width;
+ var inputHeight = videoStream?.Height;
+ var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight);
- // For QSV, feed it into hardware encoder now
- if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
+ if (width.HasValue && height.HasValue)
{
- videoSizeParam += ",hwupload=extra_hw_frames=64";
- }
-
- // For VAAPI and CUVID decoder
- // these encoders cannot automatically adjust the size of graphical subtitles to fit the output video,
- // thus needs to be manually adjusted.
- if (videoDecoder.IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1
- || (IsVaapiSupported(state) && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
- && (videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
- || outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)))
- {
- var videoStream = state.VideoStream;
- var inputWidth = videoStream?.Width;
- var inputHeight = videoStream?.Height;
- var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight);
-
- if (width.HasValue && height.HasValue)
- {
- videoSizeParam = string.Format(
+ videoSizeParam = string.Format(
CultureInfo.InvariantCulture,
- "scale={0}:{1}",
+ "scale={0}x{1}",
width.Value,
height.Value);
- }
+ }
+
+ // For QSV, feed it into hardware encoder now
+ if (isLinux && string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
+ {
+ videoSizeParam += ",hwupload=extra_hw_frames=64";
}
}
@@ -1634,7 +1668,10 @@ namespace MediaBrowser.Controller.MediaEncoding
: state.SubtitleStream.Index;
// 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}\"";
+ // Always put the scaler before the overlay for better performance
+ var retStr = !string.IsNullOrEmpty(outputSizeParam) ?
+ " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" :
+ " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\"";
// When the input may or may not be hardware VAAPI decodable
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
@@ -1644,7 +1681,6 @@ namespace MediaBrowser.Controller.MediaEncoding
[sub]: SW scaling subtitle to FixedOutputSize
[base][sub]: SW overlay
*/
- outputSizeParam = outputSizeParam.TrimStart(',');
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3},hwdownload[base];[base][sub]overlay,format=nv12,hwupload\"";
}
@@ -1657,7 +1693,6 @@ namespace MediaBrowser.Controller.MediaEncoding
[sub]: SW scaling subtitle to FixedOutputSize
[base][sub]: SW overlay
*/
- outputSizeParam = outputSizeParam.TrimStart(',');
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"";
}
else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
@@ -1666,14 +1701,13 @@ namespace MediaBrowser.Controller.MediaEncoding
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.
+ Currently only supports linux.
*/
- if (videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1)
+ if (isLinux)
{
- 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}\"";
+ retStr = !string.IsNullOrEmpty(outputSizeParam) ?
+ " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\"" :
+ " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv\"";
}
}
@@ -1745,10 +1779,8 @@ namespace MediaBrowser.Controller.MediaEncoding
requestedMaxWidth,
requestedMaxHeight);
- var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
-
if ((string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
- || (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && !hasTextSubs))
+ || string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
&& width.HasValue
&& height.HasValue)
{
@@ -1769,15 +1801,20 @@ namespace MediaBrowser.Controller.MediaEncoding
filters.Add(
string.Format(
CultureInfo.InvariantCulture,
- "{0}=w={1}:h={2}:format=nv12",
+ "{0}=w={1}:h={2}:format=nv12{3}",
qsv_or_vaapi ? "vpp_qsv" : "scale_vaapi",
outputWidth,
- outputHeight));
+ outputHeight,
+ (qsv_or_vaapi && state.DeInterlace("h264", true)) ? ":deinterlace=1" : string.Empty));
}
else
{
- // set w=0:h=0 for vpp_qsv to keep the original dimensions, otherwise it will fail.
- filters.Add(string.Format(CultureInfo.InvariantCulture, "{0}format=nv12", qsv_or_vaapi ? "vpp_qsv=w=0:h=0:" : "scale_vaapi="));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}=format=nv12{1}",
+ qsv_or_vaapi ? "vpp_qsv" : "scale_vaapi",
+ (qsv_or_vaapi && state.DeInterlace("h264", true)) ? ":deinterlace=1" : string.Empty));
}
}
else if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1
@@ -1998,8 +2035,6 @@ namespace MediaBrowser.Controller.MediaEncoding
var inputHeight = videoStream?.Height;
var threeDFormat = state.MediaSource.Video3DFormat;
- var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
-
// When the input may or may not be hardware VAAPI decodable
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
@@ -2010,20 +2045,16 @@ namespace MediaBrowser.Controller.MediaEncoding
// When the input may or may not be hardware QSV decodable
else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{
- if (!hasTextSubs)
- {
- filters.Add("format=nv12|qsv");
- filters.Add("hwupload=extra_hw_frames=64");
- }
+ filters.Add("format=nv12|qsv");
+ filters.Add("hwupload=extra_hw_frames=64");
}
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
- else if (videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
+ else if (IsVaapiSupported(state) && videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
&& string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
{
var codec = videoStream.Codec.ToLowerInvariant();
- var isColorDepth10 = !string.IsNullOrEmpty(videoStream.Profile) && (videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase)
- || videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase));
+ var isColorDepth10 = IsColorDepth10(state);
// Assert 10-bit hardware VAAPI decodable
if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
@@ -2054,31 +2085,32 @@ namespace MediaBrowser.Controller.MediaEncoding
{
filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_vaapi"));
}
- else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
- {
- if (!hasTextSubs)
- {
- filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_qsv"));
- }
- }
}
// Add software deinterlace filter before scaling filter
- if (((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true))
- && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
- && !string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
- || (hasTextSubs && state.DeInterlace("h264", true) && string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)))
+ if (state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true))
{
+ var deintParam = string.Empty;
var inputFramerate = videoStream?.RealFrameRate;
// 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, "yadif_bob", StringComparison.OrdinalIgnoreCase) && (inputFramerate ?? 60) <= 30)
{
- filters.Add("yadif=1:-1:0");
+ deintParam = "yadif=1:-1:0";
}
else
{
- filters.Add("yadif=0:-1:0");
+ deintParam = "yadif=0:-1:0";
+ }
+
+ if (!string.IsNullOrEmpty(deintParam))
+ {
+ if (!string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)
+ && videoDecoder.IndexOf("h264_cuvid", StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ filters.Add(deintParam);
+ }
}
}
@@ -2290,7 +2322,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{
inputModifier += " " + videoDecoder;
- if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1)
+ if (!IsCopyCodec(state.OutputVideoCodec)
+ && (videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1)
{
var videoStream = state.VideoStream;
var inputWidth = videoStream?.Width;
@@ -2303,11 +2336,19 @@ namespace MediaBrowser.Controller.MediaEncoding
&& width.HasValue
&& height.HasValue)
{
- inputModifier += string.Format(
- CultureInfo.InvariantCulture,
- " -resize {0}x{1}",
- width.Value,
- height.Value);
+ if (width.HasValue && height.HasValue)
+ {
+ inputModifier += string.Format(
+ CultureInfo.InvariantCulture,
+ " -resize {0}x{1}",
+ width.Value,
+ height.Value);
+ }
+
+ if (state.DeInterlace("h264", true))
+ {
+ inputModifier += " -deint 1";
+ }
}
}
}
@@ -2553,8 +2594,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(videoStream.Codec) && !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
{
- var isColorDepth10 = !string.IsNullOrEmpty(videoStream.Profile)
- && (videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase) || videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase));
+ var isColorDepth10 = IsColorDepth10(state);
// Only hevc and vp9 formats have 10-bit hardware decoder support now.
if (isColorDepth10 && !(string.Equals(videoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase)
@@ -2631,13 +2671,6 @@ namespace MediaBrowser.Controller.MediaEncoding
case "h264":
if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
{
- // cuvid decoder does not support 10-bit input.
- if ((videoStream.BitDepth ?? 8) > 8)
- {
- encodingOptions.HardwareDecodingCodecs = Array.Empty<string>();
- return null;
- }
-
return "-c:v h264_cuvid";
}
@@ -2904,21 +2937,24 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec)
{
- var isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
+ var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1);
var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va");
if ((isDxvaSupported || IsVaapiSupported(state)) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase))
{
- if (!isWindows)
+ if (isLinux)
{
return "-hwaccel vaapi";
}
- else if (isWindows8orLater)
+
+ if (isWindows && isWindows8orLater)
{
return "-hwaccel d3d11va";
}
- else
+
+ if (isWindows && !isWindows8orLater)
{
return "-hwaccel dxva2";
}
@@ -3187,5 +3223,42 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase);
}
+
+ public static bool IsColorDepth10(EncodingJobInfo state)
+ {
+ var result = false;
+ var videoStream = state.VideoStream;
+
+ if (videoStream != null)
+ {
+ if (!string.IsNullOrEmpty(videoStream.PixelFormat))
+ {
+ result = videoStream.PixelFormat.Contains("p10", StringComparison.OrdinalIgnoreCase);
+ if (result)
+ {
+ return true;
+ }
+ }
+
+ if (!string.IsNullOrEmpty(videoStream.Profile))
+ {
+ result = videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase)
+ || videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase)
+ || videoStream.Profile.Contains("Profile 2", StringComparison.OrdinalIgnoreCase);
+ if (result)
+ {
+ return true;
+ }
+ }
+
+ result = (videoStream.BitDepth ?? 8) == 10;
+ if (result)
+ {
+ return true;
+ }
+ }
+
+ return result;
+ }
}
}
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 83bd0c07e..902e29b20 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -23,7 +23,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
- <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.6" />
<PackageReference Include="System.Globalization" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
</ItemGroup>
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 446e27df6..42c7cec53 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -16,8 +16,8 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.5" />
- <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
+ <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
<PackageReference Include="PlaylistsNET" Version="1.0.6" />
<PackageReference Include="TvDbSharper" Version="3.2.0" />
diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs
index 196e801c0..df48629d0 100644
--- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs
@@ -375,7 +375,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
if (!string.IsNullOrEmpty(actor.Image))
{
- personInfo.ImageUrl = TvdbUtils.TvdbImageBaseUrl + actor.Image;
+ personInfo.ImageUrl = TvdbUtils.BannerUrl + actor.Image;
}
if (!string.IsNullOrWhiteSpace(personInfo.Name))
diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
index 219020888..132050e7b 100644
--- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
+++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
@@ -16,7 +16,7 @@
<PackageReference Include="AutoFixture" Version="4.13.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.12.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.12.0" />
- <PackageReference Include="Microsoft.Extensions.Options" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Options" Version="3.1.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj
index a767c0039..8309faebd 100644
--- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj
+++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj
@@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.5" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />