aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj18
-rw-r--r--src/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs47
-rw-r--r--src/Jellyfin.Drawing.Skia/SkiaEncoder.cs8
-rw-r--r--src/Jellyfin.Drawing/ImageProcessor.cs40
-rw-r--r--src/Jellyfin.Drawing/Jellyfin.Drawing.csproj8
-rw-r--r--src/Jellyfin.Extensions/AlphanumericComparator.cs43
-rw-r--r--src/Jellyfin.Extensions/Jellyfin.Extensions.csproj12
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs34
-rw-r--r--src/Jellyfin.Extensions/Json/JsonDefaults.cs1
-rw-r--r--src/Jellyfin.Extensions/StringExtensions.cs2
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj12
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj14
12 files changed, 102 insertions, 137 deletions
diff --git a/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
index c686b229a..3b0333299 100644
--- a/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
+++ b/src/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
@@ -16,11 +16,11 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="BlurHashSharp" Version="1.2.0" />
- <PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.2.0" />
- <PackageReference Include="SkiaSharp" Version="2.88.3" />
- <PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.3" />
- <PackageReference Include="SkiaSharp.Svg" Version="1.60.0" />
+ <PackageReference Include="BlurHashSharp" />
+ <PackageReference Include="BlurHashSharp.SkiaSharp" />
+ <PackageReference Include="SkiaSharp" />
+ <PackageReference Include="SkiaSharp.NativeAssets.Linux" />
+ <PackageReference Include="SkiaSharp.Svg" />
</ItemGroup>
<ItemGroup>
@@ -31,13 +31,13 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
- <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<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.435" PrivateAssets="All" />
- <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ <PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
</Project>
diff --git a/src/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs b/src/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs
deleted file mode 100644
index 5bb42fb99..000000000
--- a/src/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using MediaBrowser.Model.Drawing;
-using SkiaSharp;
-
-namespace Jellyfin.Drawing.Skia;
-
-/// <summary>
-/// Static helper class for drawing 'played' indicators.
-/// </summary>
-public static class PlayedIndicatorDrawer
-{
- private const int OffsetFromTopRightCorner = 38;
-
- /// <summary>
- /// Draw a 'played' indicator in the top right corner of a canvas.
- /// </summary>
- /// <param name="canvas">The canvas to draw the indicator on.</param>
- /// <param name="imageSize">
- /// The dimensions of the image to draw the indicator on. The width is used to determine the x-position of the
- /// indicator.
- /// </param>
- public static void DrawPlayedIndicator(SKCanvas canvas, ImageDimensions imageSize)
- {
- var x = imageSize.Width - OffsetFromTopRightCorner;
-
- using var paint = new SKPaint
- {
- Color = SKColor.Parse("#CC00A4DC"),
- Style = SKPaintStyle.Fill
- };
-
- canvas.DrawCircle(x, OffsetFromTopRightCorner, 20, paint);
-
- paint.Color = new SKColor(255, 255, 255, 255);
- paint.TextSize = 30;
- paint.IsAntialias = true;
-
- // or:
- // var emojiChar = 0x1F680;
- const string Text = "✔️";
- var emojiChar = StringUtilities.GetUnicodeCharacterCode(Text, SKTextEncoding.Utf32);
-
- // ask the font manager for a font with that character
- paint.Typeface = SKFontManager.Default.MatchCharacter(emojiChar);
-
- canvas.DrawText(Text, (float)x - 12, OffsetFromTopRightCorner + 12, paint);
- }
-}
diff --git a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
index ddb8a98d4..6da77ad95 100644
--- a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
+++ b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
@@ -399,7 +399,7 @@ public class SkiaEncoder : IImageEncoder
var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer);
var blur = options.Blur ?? 0;
- var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
+ var hasIndicator = options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
using var bitmap = GetBitmap(inputPath, autoOrient, orientation);
if (bitmap is null)
@@ -522,11 +522,7 @@ public class SkiaEncoder : IImageEncoder
{
var currentImageSize = new ImageDimensions(imageWidth, imageHeight);
- if (options.AddPlayedIndicator)
- {
- PlayedIndicatorDrawer.DrawPlayedIndicator(canvas, currentImageSize);
- }
- else if (options.UnplayedCount.HasValue)
+ if (options.UnplayedCount.HasValue)
{
UnplayedCountIndicator.DrawUnplayedCountIndicator(canvas, currentImageSize, options.UnplayedCount.Value);
}
diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs
index b381c9ae7..533baba4f 100644
--- a/src/Jellyfin.Drawing/ImageProcessor.cs
+++ b/src/Jellyfin.Drawing/ImageProcessor.cs
@@ -5,10 +5,12 @@ using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.MediaEncoding;
@@ -36,7 +38,8 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
private readonly IFileSystem _fileSystem;
private readonly IServerApplicationPaths _appPaths;
private readonly IImageEncoder _imageEncoder;
- private readonly IMediaEncoder _mediaEncoder;
+
+ private readonly SemaphoreSlim _parallelEncodingLimit;
private bool _disposed;
@@ -48,18 +51,27 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
/// <param name="fileSystem">The filesystem.</param>
/// <param name="imageEncoder">The image encoder.</param>
/// <param name="mediaEncoder">The media encoder.</param>
+ /// <param name="config">The configuration.</param>
public ImageProcessor(
ILogger<ImageProcessor> logger,
IServerApplicationPaths appPaths,
IFileSystem fileSystem,
IImageEncoder imageEncoder,
- IMediaEncoder mediaEncoder)
+ IMediaEncoder mediaEncoder,
+ IServerConfigurationManager config)
{
_logger = logger;
_fileSystem = fileSystem;
_imageEncoder = imageEncoder;
- _mediaEncoder = mediaEncoder;
_appPaths = appPaths;
+
+ var semaphoreCount = config.Configuration.ParallelImageEncodingLimit;
+ if (semaphoreCount < 1)
+ {
+ semaphoreCount = 2 * Environment.ProcessorCount;
+ }
+
+ _parallelEncodingLimit = new(semaphoreCount, semaphoreCount);
}
private string ResizedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "resized-images");
@@ -188,7 +200,6 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
quality,
dateModified,
outputFormat,
- options.AddPlayedIndicator,
options.PercentPlayed,
options.UnplayedCount,
options.Blur,
@@ -199,7 +210,18 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
{
if (!File.Exists(cacheFilePath))
{
- string resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
+ // Limit number of parallel (more precisely: concurrent) image encodings to prevent a high memory usage
+ await _parallelEncodingLimit.WaitAsync().ConfigureAwait(false);
+
+ string resultPath;
+ try
+ {
+ resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
+ }
+ finally
+ {
+ _parallelEncodingLimit.Release();
+ }
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{
@@ -270,7 +292,6 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
int quality,
DateTime dateModified,
ImageFormat format,
- bool addPlayedIndicator,
double percentPlayed,
int? unwatchedCount,
int? blur,
@@ -325,11 +346,6 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
filename.Append(fillHeight.Value);
}
- if (addPlayedIndicator)
- {
- filename.Append(",pl=true");
- }
-
if (percentPlayed > 0)
{
filename.Append(",p=");
@@ -563,6 +579,8 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
disposable.Dispose();
}
+ _parallelEncodingLimit?.Dispose();
+
_disposed = true;
}
}
diff --git a/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj b/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj
index a5bc8eaa7..e0963ac34 100644
--- a/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj
+++ b/src/Jellyfin.Drawing/Jellyfin.Drawing.csproj
@@ -23,13 +23,13 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
- <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<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.435" PrivateAssets="All" />
- <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ <PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
</Project>
diff --git a/src/Jellyfin.Extensions/AlphanumericComparator.cs b/src/Jellyfin.Extensions/AlphanumericComparator.cs
index 1b19752bb..6e451d40e 100644
--- a/src/Jellyfin.Extensions/AlphanumericComparator.cs
+++ b/src/Jellyfin.Extensions/AlphanumericComparator.cs
@@ -86,47 +86,12 @@ namespace Jellyfin.Extensions
{
return 1;
}
- else if (span1Len >= 20) // Number is probably too big for a ulong
- {
- // Trim all the first digits that are the same
- int i = 0;
- while (i < span1Len && span1[i] == span2[i])
- {
- i++;
- }
-
- // If there are no more digits it's the same number
- if (i == span1Len)
- {
- continue;
- }
-
- // Only need to compare the most significant digit
- span1 = span1.Slice(i, 1);
- span2 = span2.Slice(i, 1);
- }
-
- if (!ulong.TryParse(span1, out var num1)
- || !ulong.TryParse(span2, out var num2))
- {
- return 0;
- }
- else if (num1 < num2)
- {
- return -1;
- }
- else if (num1 > num2)
- {
- return 1;
- }
}
- else
+
+ int result = span1.CompareTo(span2, StringComparison.InvariantCulture);
+ if (result != 0)
{
- int result = span1.CompareTo(span2, StringComparison.InvariantCulture);
- if (result != 0)
- {
- return result;
- }
+ return result;
}
} while (pos1 < len1 && pos2 < len2);
diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
index 9fed8cbd9..4f80aa941 100644
--- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
+++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
@@ -29,18 +29,18 @@
<ItemGroup>
- <PackageReference Include="Diacritics" Version="3.3.14" />
+ <PackageReference Include="Diacritics" />
</ItemGroup>
<!-- Code Analyzers-->
- <ItemGroup>
- <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<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.435" PrivateAssets="All" />
- <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ <PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
</Project>
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs
new file mode 100644
index 000000000..2936fe4d6
--- /dev/null
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Buffers;
+using System.Buffers.Text;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Jellyfin.Extensions.Json.Converters;
+
+/// <summary>
+/// Converts a string to a boolean.
+/// This is needed for FFprobe.
+/// </summary>
+public class JsonBoolStringConverter : JsonConverter<bool>
+{
+ /// <inheritdoc />
+ public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.String)
+ {
+ ReadOnlySpan<byte> utf8Span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
+ if (Utf8Parser.TryParse(utf8Span, out bool val, out _, 'l'))
+ {
+ return val;
+ }
+ }
+
+ return reader.GetBoolean();
+ }
+
+ /// <inheritdoc />
+ public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
+ => writer.WriteBooleanValue(value);
+}
diff --git a/src/Jellyfin.Extensions/Json/JsonDefaults.cs b/src/Jellyfin.Extensions/Json/JsonDefaults.cs
index 97cbee971..4d56ca615 100644
--- a/src/Jellyfin.Extensions/Json/JsonDefaults.cs
+++ b/src/Jellyfin.Extensions/Json/JsonDefaults.cs
@@ -39,7 +39,6 @@ namespace Jellyfin.Extensions.Json
new JsonFlagEnumConverterFactory(),
new JsonStringEnumConverter(),
new JsonNullableStructConverterFactory(),
- new JsonBoolNumberConverter(),
new JsonDateTimeConverter(),
new JsonStringConverter()
}
diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs
index f30b63945..7c6124875 100644
--- a/src/Jellyfin.Extensions/StringExtensions.cs
+++ b/src/Jellyfin.Extensions/StringExtensions.cs
@@ -12,7 +12,7 @@ namespace Jellyfin.Extensions
{
// Matches non-conforming unicode chars
// https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/
- private static readonly Regex _nonConformingUnicode = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])|(\ufffd)");
+ private static readonly Regex _nonConformingUnicode = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])|(\ufffd)", RegexOptions.Compiled);
/// <summary>
/// Removes the diacritics character from the strings.
diff --git a/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj b/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj
index 32f80812a..3f4f55ee4 100644
--- a/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj
+++ b/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj
@@ -6,14 +6,14 @@
</PropertyGroup>
<!-- Code Analyzers-->
- <ItemGroup>
- <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<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.435" PrivateAssets="All" />
- <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ <PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
@@ -23,7 +23,7 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
</ItemGroup>
<ItemGroup>
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj
index b11bdc477..71572bcf6 100644
--- a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj
@@ -6,22 +6,22 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="NEbml" Version="0.11.0" />
+ <PackageReference Include="NEbml" />
</ItemGroup>
<!-- Code Analyzers-->
- <ItemGroup>
- <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<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.435" PrivateAssets="All" />
- <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ <PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
</ItemGroup>
<ItemGroup>