From 8a456bf8957923b934873bab89e3984512a5425b Mon Sep 17 00:00:00 2001
From: Dmitry Lyzo <56478732+dmitrylyzo@users.noreply.github.com>
Date: Mon, 23 Sep 2024 18:01:45 +0300
Subject: [PATCH 1/5] Escape quotes in the subtitle path (#12690)
---
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 517d135d3bd1..7ae1fbbb1060 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -1104,7 +1104,11 @@ public string EscapeSubtitleFilterPath(string path)
// https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping
// We need to double escape
- return path.Replace('\\', '/').Replace(":", "\\:", StringComparison.Ordinal).Replace("'", @"'\\\''", StringComparison.Ordinal);
+ return path
+ .Replace('\\', '/')
+ .Replace(":", "\\:", StringComparison.Ordinal)
+ .Replace("'", @"'\\\''", StringComparison.Ordinal)
+ .Replace("\"", "\\\"", StringComparison.Ordinal);
}
///
From a0204ada2f97b73f932e1ec40befd6cfa75e8e16 Mon Sep 17 00:00:00 2001
From: Nyanmisaka
Date: Mon, 23 Sep 2024 23:02:31 +0800
Subject: [PATCH 2/5] Fix intel Xe kernel driver cannot be used with QSV
(#12691)
---
.../MediaEncoding/EncodingHelper.cs | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index e9e8ed61820d..b05d2ffb7bbf 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -72,6 +72,7 @@ public partial class EncodingHelper
private readonly Version _minFFmpegAlteredVaVkInterop = new Version(7, 0, 1);
private readonly Version _minFFmpegQsvVppTonemapOption = new Version(7, 0, 1);
private readonly Version _minFFmpegQsvVppOutRangeOption = new Version(7, 0, 1);
+ private readonly Version _minFFmpegVaapiDeviceVendorId = new Version(7, 0, 1);
private static readonly Regex _validationRegex = new(ValidationRegex, RegexOptions.Compiled);
@@ -872,13 +873,15 @@ private string GetD3d11vaDeviceArgs(int deviceIndex, string deviceVendorId, stri
options);
}
- private string GetVaapiDeviceArgs(string renderNodePath, string driver, string kernelDriver, string srcDeviceAlias, string alias)
+ private string GetVaapiDeviceArgs(string renderNodePath, string driver, string kernelDriver, string vendorId, string srcDeviceAlias, string alias)
{
alias ??= VaapiAlias;
+ var haveVendorId = !string.IsNullOrEmpty(vendorId)
+ && _mediaEncoder.EncoderVersion >= _minFFmpegVaapiDeviceVendorId;
- // 'renderNodePath' has higher priority than 'kernelDriver'
+ // Priority: 'renderNodePath' > 'vendorId' > 'kernelDriver'
var driverOpts = string.IsNullOrEmpty(renderNodePath)
- ? (string.IsNullOrEmpty(kernelDriver) ? string.Empty : ",kernel_driver=" + kernelDriver)
+ ? (haveVendorId ? $",vendor_id={vendorId}" : (string.IsNullOrEmpty(kernelDriver) ? string.Empty : $",kernel_driver={kernelDriver}"))
: renderNodePath;
// 'driver' behaves similarly to env LIBVA_DRIVER_NAME
@@ -913,7 +916,7 @@ private string GetQsvDeviceArgs(string renderNodePath, string alias)
if (OperatingSystem.IsLinux())
{
// derive qsv from vaapi device
- return GetVaapiDeviceArgs(renderNodePath, "iHD", "i915", null, VaapiAlias) + arg + "@" + VaapiAlias;
+ return GetVaapiDeviceArgs(renderNodePath, "iHD", "i915", "0x8086", null, VaapiAlias) + arg + "@" + VaapiAlias;
}
if (OperatingSystem.IsWindows())
@@ -1008,14 +1011,14 @@ public string GetInputVideoHwaccelArgs(EncodingJobInfo state, EncodingOptions op
if (_mediaEncoder.IsVaapiDeviceInteliHD)
{
- args.Append(GetVaapiDeviceArgs(options.VaapiDevice, "iHD", null, null, VaapiAlias));
+ args.Append(GetVaapiDeviceArgs(options.VaapiDevice, "iHD", null, null, null, VaapiAlias));
}
else if (_mediaEncoder.IsVaapiDeviceInteli965)
{
// Only override i965 since it has lower priority than iHD in libva lookup.
Environment.SetEnvironmentVariable("LIBVA_DRIVER_NAME", "i965");
Environment.SetEnvironmentVariable("LIBVA_DRIVER_NAME_JELLYFIN", "i965");
- args.Append(GetVaapiDeviceArgs(options.VaapiDevice, "i965", null, null, VaapiAlias));
+ args.Append(GetVaapiDeviceArgs(options.VaapiDevice, "i965", null, null, null, VaapiAlias));
}
var filterDevArgs = string.Empty;
@@ -1039,7 +1042,7 @@ public string GetInputVideoHwaccelArgs(EncodingJobInfo state, EncodingOptions op
&& Environment.OSVersion.Version >= _minKernelVersionAmdVkFmtModifier)
{
args.Append(GetDrmDeviceArgs(options.VaapiDevice, DrmAlias));
- args.Append(GetVaapiDeviceArgs(null, null, null, DrmAlias, VaapiAlias));
+ args.Append(GetVaapiDeviceArgs(null, null, null, null, DrmAlias, VaapiAlias));
args.Append(GetVulkanDeviceArgs(0, null, DrmAlias, VulkanAlias));
// libplacebo wants an explicitly set vulkan filter device.
@@ -1047,7 +1050,7 @@ public string GetInputVideoHwaccelArgs(EncodingJobInfo state, EncodingOptions op
}
else
{
- args.Append(GetVaapiDeviceArgs(options.VaapiDevice, null, null, null, VaapiAlias));
+ args.Append(GetVaapiDeviceArgs(options.VaapiDevice, null, null, null, null, VaapiAlias));
filterDevArgs = GetFilterHwDeviceArgs(VaapiAlias);
if (doOclTonemap)
From 0539fdc5e3a164b694d12d8d3f8437e2cc5b6457 Mon Sep 17 00:00:00 2001
From: gnattu
Date: Mon, 23 Sep 2024 23:09:08 +0800
Subject: [PATCH 3/5] Fix libx264/libx265 auto preset (#12692)
---
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index b05d2ffb7bbf..557eb5e329f7 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -1444,7 +1444,13 @@ private string GetEncoderParam(EncoderPreset? preset, EncoderPreset defaultPrese
var encoderPreset = preset ?? defaultPreset;
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase) || isLibX265)
{
- param += " -preset " + encoderPreset.ToString().ToLowerInvariant();
+ var presetString = encoderPreset switch
+ {
+ EncoderPreset.auto => EncoderPreset.veryfast.ToString().ToLowerInvariant(),
+ _ => encoderPreset.ToString().ToLowerInvariant()
+ };
+
+ param += " -preset " + presetString;
int encodeCrf = encodingOptions.H264Crf;
if (isLibX265)
From 3c639c2e80f2a17eea3f5f1a70c1b287bc99aba4 Mon Sep 17 00:00:00 2001
From: Cody Robibero
Date: Mon, 23 Sep 2024 09:09:23 -0600
Subject: [PATCH 4/5] Tweak Trickplay migration for speed (#12643)
---
.../Trickplay/TrickplayManager.cs | 8 ++-
.../Migrations/Routines/MoveTrickplayFiles.cs | 57 ++++++++++++++-----
.../Trickplay/ITrickplayManager.cs | 4 +-
.../Trickplay/TrickplayMoveImagesTask.cs | 51 ++++++++++-------
4 files changed, 82 insertions(+), 38 deletions(-)
diff --git a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs
index 861037c1fe37..73e31279f4be 100644
--- a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs
+++ b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs
@@ -455,16 +455,18 @@ public async Task> GetTrickplayResolutions(Guid i
}
///
- public async Task> GetTrickplayItemsAsync()
+ public async Task> GetTrickplayItemsAsync(int limit, int offset)
{
- List trickplayItems;
+ IReadOnlyList trickplayItems;
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
await using (dbContext.ConfigureAwait(false))
{
trickplayItems = await dbContext.TrickplayInfos
.AsNoTracking()
- .Select(i => i.ItemId)
+ .OrderBy(i => i.ItemId)
+ .Skip(offset)
+ .Take(limit)
.ToListAsync()
.ConfigureAwait(false);
}
diff --git a/Jellyfin.Server/Migrations/Routines/MoveTrickplayFiles.cs b/Jellyfin.Server/Migrations/Routines/MoveTrickplayFiles.cs
index 301541b6ce40..c1a9e88949b2 100644
--- a/Jellyfin.Server/Migrations/Routines/MoveTrickplayFiles.cs
+++ b/Jellyfin.Server/Migrations/Routines/MoveTrickplayFiles.cs
@@ -1,10 +1,15 @@
using System;
+using System.Diagnostics;
using System.Globalization;
using System.IO;
+using System.Linq;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Common;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Trickplay;
using MediaBrowser.Model.IO;
+using Microsoft.Extensions.Logging;
namespace Jellyfin.Server.Migrations.Routines;
@@ -16,6 +21,7 @@ public class MoveTrickplayFiles : IMigrationRoutine
private readonly ITrickplayManager _trickplayManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
+ private readonly ILogger _logger;
///
/// Initializes a new instance of the class.
@@ -23,11 +29,13 @@ public class MoveTrickplayFiles : IMigrationRoutine
/// Instance of the interface.
/// Instance of the interface.
/// Instance of the interface.
- public MoveTrickplayFiles(ITrickplayManager trickplayManager, IFileSystem fileSystem, ILibraryManager libraryManager)
+ /// The logger.
+ public MoveTrickplayFiles(ITrickplayManager trickplayManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILogger logger)
{
_trickplayManager = trickplayManager;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
+ _logger = logger;
}
///
@@ -42,26 +50,49 @@ public MoveTrickplayFiles(ITrickplayManager trickplayManager, IFileSystem fileSy
///
public void Perform()
{
- var trickplayItems = _trickplayManager.GetTrickplayItemsAsync().GetAwaiter().GetResult();
- foreach (var itemId in trickplayItems)
+ const int Limit = 100;
+ int itemCount = 0, offset = 0, previousCount;
+
+ var sw = Stopwatch.StartNew();
+ var trickplayQuery = new InternalItemsQuery
{
- var resolutions = _trickplayManager.GetTrickplayResolutions(itemId).GetAwaiter().GetResult();
- var item = _libraryManager.GetItemById(itemId);
- if (item is null)
- {
- continue;
- }
+ MediaTypes = [MediaType.Video],
+ SourceTypes = [SourceType.Library],
+ IsVirtualItem = false,
+ IsFolder = false
+ };
- foreach (var resolution in resolutions)
+ do
+ {
+ var trickplayInfos = _trickplayManager.GetTrickplayItemsAsync(Limit, offset).GetAwaiter().GetResult();
+ previousCount = trickplayInfos.Count;
+ offset += Limit;
+
+ trickplayQuery.ItemIds = trickplayInfos.Select(i => i.ItemId).Distinct().ToArray();
+ var items = _libraryManager.GetItemList(trickplayQuery);
+ foreach (var trickplayInfo in trickplayInfos)
{
- var oldPath = GetOldTrickplayDirectory(item, resolution.Key);
- var newPath = _trickplayManager.GetTrickplayDirectory(item, resolution.Value.TileWidth, resolution.Value.TileHeight, resolution.Value.Width, false);
+ var item = items.OfType