mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-21 01:24:44 +01:00
Merge branch 'master' into providermanager-cleanup
This commit is contained in:
@@ -62,7 +62,7 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy
|
||||
}
|
||||
}
|
||||
|
||||
private static TheoryData<string, Dictionary<string, string>> GetParts_ValidAuthHeader_Success_Data()
|
||||
public static TheoryData<string, Dictionary<string, string>> GetParts_ValidAuthHeader_Success_Data()
|
||||
{
|
||||
var data = new TheoryData<string, Dictionary<string, string>>();
|
||||
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
<PackageReference Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
@@ -31,7 +34,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -192,7 +192,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Empty((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
|
||||
var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
|
||||
Assert.NotNull(listResult);
|
||||
Assert.Empty(listResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -220,7 +222,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Single((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
|
||||
var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
|
||||
Assert.NotNull(listResult);
|
||||
Assert.Single(listResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +192,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Empty((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
|
||||
var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
|
||||
Assert.NotNull(listResult);
|
||||
Assert.Empty(listResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -220,7 +222,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Single((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
|
||||
var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
|
||||
Assert.NotNull(listResult);
|
||||
Assert.Single(listResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
@@ -26,7 +29,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -12,10 +12,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -26,7 +29,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -7,10 +7,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -21,7 +24,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@@ -17,7 +17,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
@@ -27,7 +27,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
|
||||
const string? input = "123";
|
||||
const int output = 123;
|
||||
var deserialized = JsonSerializer.Deserialize<int>(input, _jsonSerializerOptions);
|
||||
Assert.Equal(deserialized, output);
|
||||
Assert.Equal(output, deserialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,38 @@ namespace Jellyfin.Extensions.Tests
|
||||
{
|
||||
public class StringExtensionsTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("", "")] // Identity edge-case (no diactritics)
|
||||
[InlineData("Indiana Jones", "Indiana Jones")] // Identity (no diactritics)
|
||||
[InlineData("a\ud800b", "ab")] // Invalid UTF-16 char stripping
|
||||
[InlineData("Jön", "Jon")] // Issue #7484
|
||||
[InlineData("Jönssonligan", "Jonssonligan")] // Issue #7484
|
||||
[InlineData("Kieślowski", "Kieslowski")] // Issue #7450
|
||||
[InlineData("Cidadão Kane", "Cidadao Kane")] // Issue #7560
|
||||
[InlineData("운명처럼 널 사랑해", "운명처럼 널 사랑해")] // Issue #6393 (Korean language support)
|
||||
[InlineData("애타는 로맨스", "애타는 로맨스")] // Issue #6393
|
||||
public void RemoveDiacritics_ValidInput_Corrects(string input, string expectedResult)
|
||||
{
|
||||
string result = input.RemoveDiacritics();
|
||||
Assert.Equal(expectedResult, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", false)] // Identity edge-case (no diactritics)
|
||||
[InlineData("Indiana Jones", false)] // Identity (no diactritics)
|
||||
[InlineData("a\ud800b", true)] // Invalid UTF-16 char stripping
|
||||
[InlineData("Jön", true)] // Issue #7484
|
||||
[InlineData("Jönssonligan", true)] // Issue #7484
|
||||
[InlineData("Kieślowski", true)] // Issue #7450
|
||||
[InlineData("Cidadão Kane", true)] // Issue #7560
|
||||
[InlineData("운명처럼 널 사랑해", false)] // Issue #6393 (Korean language support)
|
||||
[InlineData("애타는 로맨스", false)] // Issue #6393
|
||||
public void HasDiacritics_ValidInput_Corrects(string input, bool expectedResult)
|
||||
{
|
||||
bool result = input.HasDiacritics();
|
||||
Assert.Equal(expectedResult, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", '_', 0)]
|
||||
[InlineData("___", '_', 3)]
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@@ -26,7 +26,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Jellyfin.MediaEncoding.Hls.Tests.Playlist
|
||||
Assert.False(DynamicHlsPlaylistGenerator.IsExtractionAllowedForFile(filePath, allowedExtensions));
|
||||
}
|
||||
|
||||
private static TheoryData<int, long, double[]> ComputeEqualLengthSegments_Valid_Success_Data()
|
||||
public static TheoryData<int, long, double[]> ComputeEqualLengthSegments_Valid_Success_Data()
|
||||
{
|
||||
var data = new TheoryData<int, long, double[]>
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Jellyfin.MediaEncoding.Hls.Tests.Playlist
|
||||
return data;
|
||||
}
|
||||
|
||||
private static TheoryData<KeyframeData, int, double[]> ComputeSegments_Valid_Success_Data()
|
||||
public static TheoryData<KeyframeData, int, double[]> ComputeSegments_Valid_Success_Data()
|
||||
{
|
||||
var data = new TheoryData<KeyframeData, int, double[]>
|
||||
{
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@@ -27,7 +27,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -22,10 +22,13 @@
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
@@ -35,7 +38,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -75,6 +75,14 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
|
||||
Assert.Equal(1, res.VideoStream.RefFrames);
|
||||
Assert.Equal("1/1000", res.VideoStream.TimeBase);
|
||||
Assert.Equal(MediaStreamType.Video, res.VideoStream.Type);
|
||||
Assert.Equal(1, res.VideoStream.DvVersionMajor);
|
||||
Assert.Equal(0, res.VideoStream.DvVersionMinor);
|
||||
Assert.Equal(5, res.VideoStream.DvProfile);
|
||||
Assert.Equal(6, res.VideoStream.DvLevel);
|
||||
Assert.Equal(1, res.VideoStream.RpuPresentFlag);
|
||||
Assert.Equal(0, res.VideoStream.ElPresentFlag);
|
||||
Assert.Equal(1, res.VideoStream.BlPresentFlag);
|
||||
Assert.Equal(0, res.VideoStream.DvBlSignalCompatibilityId);
|
||||
|
||||
Assert.Empty(res.Chapters);
|
||||
Assert.Equal("Just color bars", res.Overview);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MediaBrowser.MediaEncoding.Subtitles;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
@@ -15,7 +14,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
using (var stream = File.OpenRead("Test Data/example.ass"))
|
||||
{
|
||||
var parsed = new AssParser(new NullLogger<AssParser>()).Parse(stream, CancellationToken.None);
|
||||
var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "ass");
|
||||
Assert.Single(parsed.TrackEvents);
|
||||
var trackEvent = parsed.TrackEvents[0];
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MediaBrowser.MediaEncoding.Subtitles;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
@@ -15,7 +14,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
using (var stream = File.OpenRead("Test Data/example.srt"))
|
||||
{
|
||||
var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None);
|
||||
var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt");
|
||||
Assert.Equal(2, parsed.TrackEvents.Count);
|
||||
|
||||
var trackEvent1 = parsed.TrackEvents[0];
|
||||
@@ -37,7 +36,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
using (var stream = File.OpenRead("Test Data/example2.srt"))
|
||||
{
|
||||
var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None);
|
||||
var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt");
|
||||
Assert.Equal(2, parsed.TrackEvents.Count);
|
||||
|
||||
var trackEvent1 = parsed.TrackEvents[0];
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using MediaBrowser.MediaEncoding.Subtitles;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
@@ -13,7 +12,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
public class SsaParserTests
|
||||
{
|
||||
private readonly SsaParser _parser = new SsaParser(new NullLogger<AssParser>());
|
||||
private readonly SubtitleEditParser _parser = new SubtitleEditParser(new NullLogger<SubtitleEditParser>());
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Parse_MultipleDialogues_TestData))]
|
||||
@@ -21,7 +20,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa)))
|
||||
{
|
||||
SubtitleTrackInfo subtitleTrackInfo = _parser.Parse(stream, CancellationToken.None);
|
||||
SubtitleTrackInfo subtitleTrackInfo = _parser.Parse(stream, "ssa");
|
||||
|
||||
Assert.Equal(expectedSubtitleTrackEvents.Count, subtitleTrackInfo.TrackEvents.Count);
|
||||
|
||||
@@ -76,7 +75,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
using (var stream = File.OpenRead("Test Data/example.ssa"))
|
||||
{
|
||||
var parsed = _parser.Parse(stream, CancellationToken.None);
|
||||
var parsed = _parser.Parse(stream, "ssa");
|
||||
Assert.Single(parsed.TrackEvents);
|
||||
var trackEvent = parsed.TrackEvents[0];
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
public class SubtitleEncoderTests
|
||||
{
|
||||
internal static TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo> GetReadableFile_Valid_TestData()
|
||||
public static TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo> GetReadableFile_Valid_TestData()
|
||||
{
|
||||
var data = new TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo>();
|
||||
|
||||
|
||||
@@ -47,7 +47,20 @@
|
||||
"tags": {
|
||||
"ENCODER": "Lavc57.107.100 libx264",
|
||||
"DURATION": "00:00:01.000000000"
|
||||
}
|
||||
},
|
||||
"side_data_list": [
|
||||
{
|
||||
"side_data_type": "DOVI configuration record",
|
||||
"dv_version_major": 1,
|
||||
"dv_version_minor": 0,
|
||||
"dv_profile": 5,
|
||||
"dv_level": 6,
|
||||
"rpu_present_flag": 1,
|
||||
"el_present_flag": 0,
|
||||
"bl_present_flag": 1,
|
||||
"dv_bl_signal_compatibility_id": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"chapters": [
|
||||
|
||||
@@ -152,9 +152,9 @@ namespace Jellyfin.Model.Tests.Cryptography
|
||||
[InlineData("$PBKDF2$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty segment
|
||||
[InlineData("$PBKDF2$iterations=1000$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty salt segment
|
||||
[InlineData("$PBKDF2$iterations=1000$69F420$")] // Empty hash segment
|
||||
[InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
|
||||
[InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
|
||||
[InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
|
||||
[InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter
|
||||
[InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter
|
||||
[InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter
|
||||
[InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $
|
||||
[InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment
|
||||
[InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
// Firefox
|
||||
@@ -38,7 +38,7 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
// Safari
|
||||
@@ -89,7 +89,7 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome-NoHLS", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
|
||||
[InlineData("Chrome-NoHLS", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
|
||||
[InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
|
||||
[InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
// TranscodeMedia
|
||||
@@ -131,6 +131,37 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("Null", "mkv-vp9-aac-srt-2600k", null, TranscodeReason.ContainerBitrateExceedsLimit)]
|
||||
[InlineData("Null", "mkv-vp9-ac3-srt-2600k", null, TranscodeReason.ContainerBitrateExceedsLimit)]
|
||||
[InlineData("Null", "mkv-vp9-vorbis-vtt-2600k", null, TranscodeReason.ContainerBitrateExceedsLimit)]
|
||||
// AndroidTV
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
// Tizen 3 Stereo
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-dts-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
[InlineData("Tizen3-stereo", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
// Tizen 4 4K 5.1
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
[InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "")
|
||||
{
|
||||
var options = await GetVideoOptions(deviceName, mediaSource);
|
||||
@@ -146,7 +177,7 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
// Firefox
|
||||
@@ -156,7 +187,7 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
|
||||
[InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
|
||||
[InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
// Safari
|
||||
@@ -198,6 +229,37 @@ namespace Jellyfin.Model.Tests
|
||||
[InlineData("JellyfinMediaPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450
|
||||
[InlineData("JellyfinMediaPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] // #6450
|
||||
[InlineData("JellyfinMediaPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] // #6450
|
||||
// AndroidTV
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
// Tizen 3 Stereo
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-dts-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
[InlineData("Tizen3-stereo", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen3-stereo", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
// Tizen 4 4K 5.1
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
|
||||
[InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
|
||||
[InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
|
||||
public async Task BuildVideoItemWithFirstExplicitStream(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "")
|
||||
{
|
||||
var options = await GetVideoOptions(deviceName, mediaSource);
|
||||
@@ -223,12 +285,26 @@ namespace Jellyfin.Model.Tests
|
||||
// RokuSSPlus
|
||||
[InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
[InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
|
||||
// no streams
|
||||
[InlineData("Chrome", "no-streams", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] // #6450
|
||||
// AndroidTV
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
|
||||
[InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
|
||||
// Tizen 3 Stereo
|
||||
[InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
|
||||
[InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
|
||||
// Tizen 4 4K 5.1
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
|
||||
[InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
|
||||
public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "")
|
||||
{
|
||||
var options = await GetVideoOptions(deviceName, mediaSource);
|
||||
var streamCount = options.MediaSources[0].MediaStreams.Count;
|
||||
options.AudioStreamIndex = streamCount - 2;
|
||||
options.SubtitleStreamIndex = streamCount - 1;
|
||||
if (streamCount > 0)
|
||||
{
|
||||
options.AudioStreamIndex = streamCount - 2;
|
||||
options.SubtitleStreamIndex = streamCount - 1;
|
||||
}
|
||||
|
||||
var streamInfo = BuildVideoItemSimpleTest(options, playMethod, why, transcodeMode, transcodeProtocol);
|
||||
Assert.Equal(streamInfo?.AudioStreamIndex, options.AudioStreamIndex);
|
||||
@@ -262,23 +338,23 @@ namespace Jellyfin.Model.Tests
|
||||
Assert.NotNull(mediaSource);
|
||||
var videoStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Video);
|
||||
var audioStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio);
|
||||
// TODO: check AudioStreamIndex vs options.AudioStreamIndex
|
||||
// TODO: Check AudioStreamIndex vs options.AudioStreamIndex
|
||||
var inputAudioStream = mediaSource.GetDefaultAudioStream(audioStreamIndexInput ?? mediaSource.DefaultAudioStreamIndex);
|
||||
|
||||
var uri = ParseUri(val);
|
||||
|
||||
if (playMethod == PlayMethod.DirectPlay)
|
||||
{
|
||||
// check expected container
|
||||
// Check expected container
|
||||
var containers = ContainerProfile.SplitValue(mediaSource.Container);
|
||||
// TODO: test transcode too
|
||||
// TODO: Test transcode too
|
||||
// Assert.Contains(uri.Extension, containers);
|
||||
|
||||
// check expected video codec (1)
|
||||
// Check expected video codec (1)
|
||||
Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
|
||||
Assert.Single(val.TargetVideoCodec);
|
||||
|
||||
// check expected audio codecs (1)
|
||||
// Check expected audio codecs (1)
|
||||
Assert.Contains(targetAudioStream.Codec, val.TargetAudioCodec);
|
||||
Assert.Single(val.TargetAudioCodec);
|
||||
// Assert.Single(val.AudioCodecs);
|
||||
@@ -294,7 +370,7 @@ namespace Jellyfin.Model.Tests
|
||||
Assert.NotEmpty(val.VideoCodecs);
|
||||
Assert.NotEmpty(val.AudioCodecs);
|
||||
|
||||
// check expected container (todo: this could be a test param)
|
||||
// Check expected container (todo: this could be a test param)
|
||||
if (transcodeProtocol == "http")
|
||||
{
|
||||
// Assert.Equal("webm", val.Container);
|
||||
@@ -327,32 +403,39 @@ namespace Jellyfin.Model.Tests
|
||||
stream => Assert.DoesNotContain(stream.Codec, val.VideoCodecs));
|
||||
}
|
||||
|
||||
// todo: fill out tests here
|
||||
// TODO: Fill out tests here
|
||||
}
|
||||
|
||||
// DirectStream and Remux
|
||||
else
|
||||
{
|
||||
// check expected video codec (1)
|
||||
// Check expected video codec (1)
|
||||
Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
|
||||
Assert.Single(val.TargetVideoCodec);
|
||||
|
||||
if (transcodeMode == "DirectStream")
|
||||
{
|
||||
// Check expected audio codecs (1)
|
||||
if (!targetAudioStream.IsExternal)
|
||||
{
|
||||
// check expected audio codecs (1)
|
||||
Assert.DoesNotContain(targetAudioStream.Codec, val.AudioCodecs);
|
||||
if (val.TranscodeReasons.HasFlag(TranscodeReason.ContainerNotSupported))
|
||||
{
|
||||
Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.DoesNotContain(targetAudioStream.Codec, val.AudioCodecs);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (transcodeMode == "Remux")
|
||||
{
|
||||
// check expected audio codecs (1)
|
||||
// Check expected audio codecs (1)
|
||||
Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
|
||||
Assert.Single(val.AudioCodecs);
|
||||
}
|
||||
|
||||
// video details
|
||||
// Video details
|
||||
var videoStream = targetVideoStream;
|
||||
Assert.False(val.EstimateContentLength);
|
||||
Assert.Equal(TranscodeSeekInfo.Auto, val.TranscodeSeekInfo);
|
||||
@@ -361,10 +444,10 @@ namespace Jellyfin.Model.Tests
|
||||
Assert.Equal(videoStream.BitDepth, val.TargetVideoBitDepth);
|
||||
Assert.InRange(val.VideoBitrate.GetValueOrDefault(), videoStream.BitRate.GetValueOrDefault(), int.MaxValue);
|
||||
|
||||
// audio codec not supported
|
||||
// Audio codec not supported
|
||||
if ((why & TranscodeReason.AudioCodecNotSupported) != 0)
|
||||
{
|
||||
// audio stream specified
|
||||
// Audio stream specified
|
||||
if (options.AudioStreamIndex >= 0)
|
||||
{
|
||||
// TODO:fixme
|
||||
@@ -374,10 +457,10 @@ namespace Jellyfin.Model.Tests
|
||||
}
|
||||
}
|
||||
|
||||
// audio stream not specified
|
||||
// Audio stream not specified
|
||||
else
|
||||
{
|
||||
// TODO:fixme
|
||||
// TODO: Fixme
|
||||
Assert.All(audioStreams, stream =>
|
||||
{
|
||||
if (!stream.IsExternal)
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Jellyfin.Model.Drawing;
|
||||
|
||||
public static class ImageFormatExtensionsTests
|
||||
{
|
||||
private static TheoryData<ImageFormat> GetAllImageFormats()
|
||||
public static TheoryData<ImageFormat> GetAllImageFormats()
|
||||
{
|
||||
var theoryTypes = new TheoryData<ImageFormat>();
|
||||
foreach (var x in Enum.GetValues<ImageFormat>())
|
||||
|
||||
@@ -109,26 +109,37 @@ namespace Jellyfin.Model.Tests.Entities
|
||||
[InlineData(null, null, false, null)]
|
||||
[InlineData(null, 0, false, null)]
|
||||
[InlineData(0, null, false, null)]
|
||||
[InlineData(640, 480, false, "480p")]
|
||||
[InlineData(640, 480, true, "480i")]
|
||||
[InlineData(720, 576, false, "576p")]
|
||||
[InlineData(720, 576, true, "576i")]
|
||||
[InlineData(256, 144, false, "144p")]
|
||||
[InlineData(256, 144, true, "144i")]
|
||||
[InlineData(426, 240, false, "240p")]
|
||||
[InlineData(426, 240, true, "240i")]
|
||||
[InlineData(640, 360, false, "360p")]
|
||||
[InlineData(640, 360, true, "360i")]
|
||||
[InlineData(854, 480, false, "480p")]
|
||||
[InlineData(854, 480, true, "480i")]
|
||||
[InlineData(960, 540, false, "540p")]
|
||||
[InlineData(960, 540, true, "540i")]
|
||||
[InlineData(1024, 576, false, "576p")]
|
||||
[InlineData(1024, 576, true, "576i")]
|
||||
[InlineData(1280, 720, false, "720p")]
|
||||
[InlineData(1280, 720, true, "720i")]
|
||||
[InlineData(1920, 1080, false, "1080p")]
|
||||
[InlineData(1920, 1080, true, "1080i")]
|
||||
[InlineData(2560, 1080, false, "1080p")]
|
||||
[InlineData(2560, 1080, true, "1080i")]
|
||||
[InlineData(4096, 3072, false, "4K")]
|
||||
[InlineData(8192, 6144, false, "8K")]
|
||||
[InlineData(512, 384, false, "480p")]
|
||||
[InlineData(576, 336, false, "480p")]
|
||||
[InlineData(624, 352, false, "480p")]
|
||||
[InlineData(640, 352, false, "480p")]
|
||||
[InlineData(704, 396, false, "480p")]
|
||||
[InlineData(720, 404, false, "480p")]
|
||||
[InlineData(512, 384, false, "384p")]
|
||||
[InlineData(576, 336, false, "360p")]
|
||||
[InlineData(576, 336, true, "360i")]
|
||||
[InlineData(624, 352, false, "360p")]
|
||||
[InlineData(640, 352, false, "360p")]
|
||||
[InlineData(640, 480, false, "480p")]
|
||||
[InlineData(704, 396, false, "404p")]
|
||||
[InlineData(720, 404, false, "404p")]
|
||||
[InlineData(720, 480, false, "480p")]
|
||||
[InlineData(720, 576, false, "576p")]
|
||||
[InlineData(768, 576, false, "576p")]
|
||||
[InlineData(960, 544, false, "540p")]
|
||||
[InlineData(960, 544, true, "540i")]
|
||||
[InlineData(960, 720, false, "720p")]
|
||||
[InlineData(1280, 528, false, "720p")]
|
||||
[InlineData(1280, 532, false, "720p")]
|
||||
@@ -140,6 +151,11 @@ namespace Jellyfin.Model.Tests.Entities
|
||||
[InlineData(1280, 696, false, "720p")]
|
||||
[InlineData(1280, 716, false, "720p")]
|
||||
[InlineData(1280, 718, false, "720p")]
|
||||
[InlineData(1920, 1080, false, "1080p")]
|
||||
[InlineData(1440, 1070, false, "1080p")]
|
||||
[InlineData(1440, 1072, false, "1080p")]
|
||||
[InlineData(1440, 1080, false, "1080p")]
|
||||
[InlineData(1440, 1440, false, "1080p")]
|
||||
[InlineData(1912, 792, false, "1080p")]
|
||||
[InlineData(1916, 1076, false, "1080p")]
|
||||
[InlineData(1918, 1080, false, "1080p")]
|
||||
@@ -153,14 +169,16 @@ namespace Jellyfin.Model.Tests.Entities
|
||||
[InlineData(1920, 960, false, "1080p")]
|
||||
[InlineData(1920, 1024, false, "1080p")]
|
||||
[InlineData(1920, 1040, false, "1080p")]
|
||||
[InlineData(1920, 1070, false, "1080p")]
|
||||
[InlineData(1920, 1072, false, "1080p")]
|
||||
[InlineData(1440, 1072, false, "1080p")]
|
||||
[InlineData(1440, 1080, false, "1080p")]
|
||||
[InlineData(1920, 1440, false, "1080p")]
|
||||
[InlineData(3840, 1600, false, "4K")]
|
||||
[InlineData(3840, 1606, false, "4K")]
|
||||
[InlineData(3840, 1608, false, "4K")]
|
||||
[InlineData(3840, 2160, false, "4K")]
|
||||
[InlineData(4090, 3070, false, "4K")]
|
||||
[InlineData(7680, 4320, false, "8K")]
|
||||
[InlineData(8190, 6140, false, "8K")]
|
||||
public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string expected)
|
||||
{
|
||||
var mediaStream = new MediaStream()
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -28,7 +31,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
{
|
||||
"Name": "Jellyfin AndroidTV-ExoPlayer",
|
||||
"EnableAlbumArtInDidl": false,
|
||||
"EnableSingleAlbumArtLimit": false,
|
||||
"EnableSingleSubtitleLimit": false,
|
||||
"SupportedMediaTypes": "Audio,Photo,Video",
|
||||
"MaxAlbumArtWidth": 0,
|
||||
"MaxAlbumArtHeight": 0,
|
||||
"MaxStreamingBitrate": 120000000,
|
||||
"MaxStaticBitrate": 100000000,
|
||||
"MusicStreamingTranscodingBitrate": 192000,
|
||||
"TimelineOffsetSeconds": 0,
|
||||
"RequiresPlainVideoItems": false,
|
||||
"RequiresPlainFolders": false,
|
||||
"EnableMSMediaReceiverRegistrar": false,
|
||||
"IgnoreTranscodeByteRangeRequests": false,
|
||||
"DirectPlayProfiles": [
|
||||
{
|
||||
"Container": "m4v,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,mp4,webm",
|
||||
"AudioCodec": "aac,mp3,mp2,aac_latm,alac,ac3,eac3,dca,dts,mlp,truehd,pcm_alaw,pcm_mulaw",
|
||||
"VideoCodec": "h264,hevc,vp8,vp9,mpeg,mpeg2video",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac,mp3,mp2,aac_latm,alac,ac3,eac3,dca,dts,mlp,truehd,pcm_alaw,pcm_mulaw,,pa,flac,wav,wma,ogg,oga,webma,ape,opus",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "jpg,jpeg,png,gif,web",
|
||||
"Type": "Photo",
|
||||
"$type": "DirectPlayProfile"
|
||||
}
|
||||
],
|
||||
"CodecProfiles": [
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": "high|main|baseline|constrained baseline",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": "51",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "h264",
|
||||
"$type": "CodecProfile"
|
||||
},
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "RefFrames",
|
||||
"Value": "12",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"ApplyConditions": [
|
||||
{
|
||||
"Condition": "GreaterThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "1200",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "h264",
|
||||
"$type": "CodecProfile"
|
||||
},
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "RefFrames",
|
||||
"Value": "4",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"ApplyConditions": [
|
||||
{
|
||||
"Condition": "GreaterThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "1900",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "h264",
|
||||
"$type": "CodecProfile"
|
||||
},
|
||||
{
|
||||
"Type": "VideoAudio",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "AudioChannels",
|
||||
"Value": "6",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "CodecProfile"
|
||||
}
|
||||
],
|
||||
"TranscodingProfiles": [
|
||||
{
|
||||
"Container": "ts",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264",
|
||||
"AudioCodec": "aac,mp3",
|
||||
"Protocol": "hls",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "mp3",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
}
|
||||
],
|
||||
"SubtitleProfiles": [
|
||||
{
|
||||
"Format": "srt",
|
||||
"Method": "Embed",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "srt",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "subrip",
|
||||
"Method": "Embed",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "subrip",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "ass",
|
||||
"Method": "Encode",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "ssa",
|
||||
"Method": "Encode",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "pgs",
|
||||
"Method": "Encode",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "pgssub",
|
||||
"Method": "Encode",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "dvdsub",
|
||||
"Method": "Encode",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "vtt",
|
||||
"Method": "Embed",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "sub",
|
||||
"Method": "Embed",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "idx",
|
||||
"Method": "Embed",
|
||||
"$type": "SubtitleProfile"
|
||||
}
|
||||
],
|
||||
"$type": "DeviceProfile"
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
{
|
||||
"Name": "Jellyfin Tizen 3 Stereo",
|
||||
"EnableAlbumArtInDidl": false,
|
||||
"EnableSingleAlbumArtLimit": false,
|
||||
"EnableSingleSubtitleLimit": false,
|
||||
"SupportedMediaTypes": "Audio,Photo,Video",
|
||||
"MaxAlbumArtWidth": 0,
|
||||
"MaxAlbumArtHeight": 0,
|
||||
"MaxStreamingBitrate": 120000000,
|
||||
"MaxStaticBitrate": 100000000,
|
||||
"MusicStreamingTranscodingBitrate": 384000,
|
||||
"TimelineOffsetSeconds": 0,
|
||||
"RequiresPlainVideoItems": false,
|
||||
"RequiresPlainFolders": false,
|
||||
"EnableMSMediaReceiverRegistrar": false,
|
||||
"IgnoreTranscodeByteRangeRequests": false,
|
||||
"DirectPlayProfiles": [
|
||||
{
|
||||
"Container": "webm",
|
||||
"AudioCodec": "vorbis,opus",
|
||||
"VideoCodec": "vp8,vp9",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp4,m4v",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mkv",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "m2ts",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,vc1,mpeg2video",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wmv",
|
||||
"AudioCodec": "wma",
|
||||
"VideoCodec": "wmv,vc1",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "ts,mpegts",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc,vc1,mpeg2video",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "asf",
|
||||
"AudioCodec": "wma",
|
||||
"VideoCodec": "wmv,vc1",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "avi",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mpg,mpeg,flv,3gp,mts,trp,vob,vro",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mov",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "opus",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webm",
|
||||
"AudioCodec": "opus",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "m4a",
|
||||
"AudioCodec": "aac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "m4b",
|
||||
"AudioCodec": "aac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "flac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webma",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webm",
|
||||
"AudioCodec": "webma",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wma",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wav",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "ogg",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
}
|
||||
],
|
||||
"TranscodingProfiles": [
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "aac",
|
||||
"Protocol": "hls",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 1,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": true,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "aac",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "mp3",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "opus",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "opus",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wav",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "wav",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "opus",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "opus",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "mp3",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "aac",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wav",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "wav",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mkv",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"Protocol": "",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": true,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "1920",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "ts",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264,hevc",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,opus",
|
||||
"Protocol": "hls",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 1,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "1920",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webm",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "vp8,vp9,vpx",
|
||||
"AudioCodec": "vorbis,opus",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "2",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "1920",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp4",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "1920",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
}
|
||||
],
|
||||
"CodecProfiles": [
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "NotEquals",
|
||||
"Property": "IsAnamorphic",
|
||||
"Value": "true",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": "high|main|baseline|constrained baseline|high 10",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": "52",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoBitrate",
|
||||
"Value": "20000000",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "h264",
|
||||
"$type": "CodecProfile"
|
||||
},
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "NotEquals",
|
||||
"Property": "IsAnamorphic",
|
||||
"Value": "true",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": "main|main 10",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": "183",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoBitrate",
|
||||
"Value": "20000000",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "hevc",
|
||||
"$type": "CodecProfile"
|
||||
},
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoBitrate",
|
||||
"Value": "20000000",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "CodecProfile"
|
||||
}
|
||||
],
|
||||
"ResponseProfiles": [
|
||||
{
|
||||
"Container": "m4v",
|
||||
"Type": "Video",
|
||||
"MimeType": "video/mp4",
|
||||
"$type": "ResponseProfile"
|
||||
}
|
||||
],
|
||||
"SubtitleProfiles": [
|
||||
{
|
||||
"Format": "vtt",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "ass",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "ssa",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
}
|
||||
],
|
||||
"$type": "DeviceProfile"
|
||||
}
|
||||
@@ -0,0 +1,499 @@
|
||||
{
|
||||
"Name": "Jellyfin Tizen 4 4K 5.1",
|
||||
"EnableAlbumArtInDidl": false,
|
||||
"EnableSingleAlbumArtLimit": false,
|
||||
"EnableSingleSubtitleLimit": false,
|
||||
"SupportedMediaTypes": "Audio,Photo,Video",
|
||||
"MaxAlbumArtWidth": 0,
|
||||
"MaxAlbumArtHeight": 0,
|
||||
"MaxStreamingBitrate": 120000000,
|
||||
"MaxStaticBitrate": 100000000,
|
||||
"MusicStreamingTranscodingBitrate": 384000,
|
||||
"TimelineOffsetSeconds": 0,
|
||||
"RequiresPlainVideoItems": false,
|
||||
"RequiresPlainFolders": false,
|
||||
"EnableMSMediaReceiverRegistrar": false,
|
||||
"IgnoreTranscodeByteRangeRequests": false,
|
||||
"DirectPlayProfiles": [
|
||||
{
|
||||
"Container": "webm",
|
||||
"AudioCodec": "vorbis,opus",
|
||||
"VideoCodec": "vp8,vp9",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp4,m4v",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mkv",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "m2ts",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,vc1,mpeg2video",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wmv",
|
||||
"AudioCodec": "wma",
|
||||
"VideoCodec": "wmv,vc1",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "ts,mpegts",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc,vc1,mpeg2video",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "asf",
|
||||
"AudioCodec": "wma",
|
||||
"VideoCodec": "wmv,vc1",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "avi",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264,hevc",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mpg,mpeg,flv,3gp,mts,trp,vob,vro",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mov",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"VideoCodec": "h264",
|
||||
"Type": "Video",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "opus",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webm",
|
||||
"AudioCodec": "opus",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "m4a",
|
||||
"AudioCodec": "aac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "m4b",
|
||||
"AudioCodec": "aac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "flac",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webma",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webm",
|
||||
"AudioCodec": "webma",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wma",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wav",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
},
|
||||
{
|
||||
"Container": "ogg",
|
||||
"Type": "Audio",
|
||||
"$type": "DirectPlayProfile"
|
||||
}
|
||||
],
|
||||
"TranscodingProfiles": [
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "aac",
|
||||
"Protocol": "hls",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 1,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": true,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "aac",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "mp3",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "opus",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "opus",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wav",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "wav",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "opus",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "opus",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp3",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "mp3",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "aac",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "aac",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "wav",
|
||||
"Type": "Audio",
|
||||
"AudioCodec": "wav",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mkv",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"Protocol": "",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": true,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "3840",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "ts",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264,hevc",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,opus",
|
||||
"Protocol": "hls",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 1,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "3840",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "webm",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "vp8,vp9,vpx",
|
||||
"AudioCodec": "vorbis,opus",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Streaming",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MaxAudioChannels": "6",
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "3840",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
},
|
||||
{
|
||||
"Container": "mp4",
|
||||
"Type": "Video",
|
||||
"VideoCodec": "h264",
|
||||
"AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
|
||||
"Protocol": "http",
|
||||
"EstimateContentLength": false,
|
||||
"EnableMpegtsM2TsMode": false,
|
||||
"TranscodeSeekInfo": "Auto",
|
||||
"CopyTimestamps": false,
|
||||
"Context": "Static",
|
||||
"EnableSubtitlesInManifest": false,
|
||||
"MinSegments": 0,
|
||||
"SegmentLength": 0,
|
||||
"BreakOnNonKeyFrames": false,
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "Width",
|
||||
"Value": "3840",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"$type": "TranscodingProfile"
|
||||
}
|
||||
],
|
||||
"CodecProfiles": [
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "NotEquals",
|
||||
"Property": "IsAnamorphic",
|
||||
"Value": "true",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": "high|main|baseline|constrained baseline|high 10",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": "52",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "h264",
|
||||
"$type": "CodecProfile"
|
||||
},
|
||||
{
|
||||
"Type": "Video",
|
||||
"Conditions": [
|
||||
{
|
||||
"Condition": "NotEquals",
|
||||
"Property": "IsAnamorphic",
|
||||
"Value": "true",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "EqualsAny",
|
||||
"Property": "VideoProfile",
|
||||
"Value": "main|main 10",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
},
|
||||
{
|
||||
"Condition": "LessThanEqual",
|
||||
"Property": "VideoLevel",
|
||||
"Value": "183",
|
||||
"IsRequired": false,
|
||||
"$type": "ProfileCondition"
|
||||
}
|
||||
],
|
||||
"Codec": "hevc",
|
||||
"$type": "CodecProfile"
|
||||
}
|
||||
],
|
||||
"ResponseProfiles": [
|
||||
{
|
||||
"Container": "m4v",
|
||||
"Type": "Video",
|
||||
"MimeType": "video/mp4",
|
||||
"$type": "ResponseProfile"
|
||||
}
|
||||
],
|
||||
"SubtitleProfiles": [
|
||||
{
|
||||
"Format": "vtt",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "ass",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
},
|
||||
{
|
||||
"Format": "ssa",
|
||||
"Method": "External",
|
||||
"$type": "SubtitleProfile"
|
||||
}
|
||||
],
|
||||
"$type": "DeviceProfile"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"Id": "a766d122b58e45d9492d17af77748bf5",
|
||||
"Path": "/Media/MyVideo-720p.mp4",
|
||||
"Container": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"Size": 835317696,
|
||||
"Name": "MyVideo-720p",
|
||||
"ETag": "579a34c6d5dfb21d81539a51220b6a23",
|
||||
"RunTimeTicks": 25801230336,
|
||||
"SupportsTranscoding": true,
|
||||
"SupportsDirectStream": true,
|
||||
"SupportsDirectPlay": true,
|
||||
"SupportsProbing": true,
|
||||
"MediaStreams": [
|
||||
{
|
||||
"Codec": "h264",
|
||||
"CodecTag": "avc1",
|
||||
"Language": "eng",
|
||||
"TimeBase": "1/11988",
|
||||
"VideoRange": "SDR",
|
||||
"DisplayTitle": "720p H264 SDR",
|
||||
"NalLengthSize": "0",
|
||||
"BitRate": 2032876,
|
||||
"BitDepth": 8,
|
||||
"RefFrames": 1,
|
||||
"IsDefault": true,
|
||||
"Height": 720,
|
||||
"Width": 1280,
|
||||
"AverageFrameRate": 23.976,
|
||||
"RealFrameRate": 23.976,
|
||||
"Profile": "High",
|
||||
"Type": 1,
|
||||
"AspectRatio": "16:9",
|
||||
"PixelFormat": "yuv420p",
|
||||
"Level": 41
|
||||
},
|
||||
{
|
||||
"Codec": "dts",
|
||||
"Language": "eng",
|
||||
"TimeBase": "1/48000",
|
||||
"DisplayTitle": "En - DTS - 5.1 - Default",
|
||||
"ChannelLayout": "5.1",
|
||||
"BitRate": 384000,
|
||||
"Channels": 6,
|
||||
"SampleRate": 48000,
|
||||
"IsDefault": true,
|
||||
"Index": 1,
|
||||
"Score": 202
|
||||
},
|
||||
{
|
||||
"Codec": "srt",
|
||||
"Language": "eng",
|
||||
"TimeBase": "1/1000000",
|
||||
"localizedUndefined": "Undefined",
|
||||
"localizedDefault": "Default",
|
||||
"localizedForced": "Forced",
|
||||
"DisplayTitle": "En - Default",
|
||||
"BitRate": 92,
|
||||
"IsDefault": true,
|
||||
"Type": 2,
|
||||
"Index": 2,
|
||||
"Score": 6421,
|
||||
"IsExternal": true,
|
||||
"IsTextSubtitleStream": true,
|
||||
"SupportsExternalStream": true
|
||||
}
|
||||
],
|
||||
"Bitrate": 2590008,
|
||||
"DefaultAudioStreamIndex": 1,
|
||||
"DefaultSubtitleStreamIndex": 2
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"Id": "f6eab7118618ab26e61e495a1853481a",
|
||||
"Path": "/Media/MyVideo-WEBDL-2160p.mp4",
|
||||
"Container": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"Size": 6521110016,
|
||||
"Name": "MyVideo WEBDL-2160p",
|
||||
"ETag": "a2fb84b618ba2467fe377543f879e9bf",
|
||||
"RunTimeTicks": 34318510080,
|
||||
"SupportsTranscoding": true,
|
||||
"SupportsDirectStream": true,
|
||||
"SupportsDirectPlay": true,
|
||||
"SupportsProbing": true,
|
||||
"MediaStreams": [
|
||||
{
|
||||
"Codec": "hevc",
|
||||
"CodecTag": "hev1",
|
||||
"Language": "eng",
|
||||
"ColorSpace": "bt2020nc",
|
||||
"ColorTransfer": "smpte2084",
|
||||
"ColorPrimaries": "bt2020",
|
||||
"TimeBase": "1/16000",
|
||||
"VideoRange": "HDR",
|
||||
"DisplayTitle": "4K HEVC HDR",
|
||||
"BitRate": 14715079,
|
||||
"BitDepth": 8,
|
||||
"RefFrames": 1,
|
||||
"IsDefault": true,
|
||||
"Height": 2160,
|
||||
"Width": 3840,
|
||||
"AverageFrameRate": 23.976,
|
||||
"RealFrameRate": 23.976,
|
||||
"Profile": "Main 10",
|
||||
"Type": 1,
|
||||
"AspectRatio": "16:9",
|
||||
"PixelFormat": "yuv420p10le",
|
||||
"Level": 150
|
||||
},
|
||||
{
|
||||
"Codec": "truehd",
|
||||
"CodecTag": "AC-3",
|
||||
"Language": "eng",
|
||||
"TimeBase": "1/48000",
|
||||
"DisplayTitle": "TRUEHD - 7.1",
|
||||
"ChannelLayout": "7.1",
|
||||
"BitRate": 384000,
|
||||
"Channels": 8,
|
||||
"SampleRate": 48000,
|
||||
"IsDefault": true,
|
||||
"Index": 1,
|
||||
"Score": 203
|
||||
},
|
||||
{
|
||||
"Codec": "srt",
|
||||
"Language": "eng",
|
||||
"TimeBase": "1/1000000",
|
||||
"localizedUndefined": "Undefined",
|
||||
"localizedDefault": "Default",
|
||||
"localizedForced": "Forced",
|
||||
"DisplayTitle": "En - Default",
|
||||
"BitRate": 92,
|
||||
"IsDefault": true,
|
||||
"Type": 2,
|
||||
"Index": 2,
|
||||
"Score": 6421,
|
||||
"IsExternal": true,
|
||||
"IsTextSubtitleStream": true,
|
||||
"SupportsExternalStream": true,
|
||||
"Path": "/Media/MyVideo-WEBDL-2160p.default.eng.srt"
|
||||
}
|
||||
],
|
||||
"Bitrate": 15201382,
|
||||
"DefaultAudioStreamIndex": 1,
|
||||
"DefaultSubtitleStreamIndex": 2
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"Id": "f6eab7118618ab26e61e495a1853481a",
|
||||
"Path": "/Media/MyVideo-WEBDL-2160p.mp4",
|
||||
"Container": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"Size": 6521110016,
|
||||
"Name": "MyVideo WEBDL-2160p",
|
||||
"ETag": "a2fb84b618ba2467fe377543f879e9bf",
|
||||
"RunTimeTicks": 34318510080,
|
||||
"SupportsTranscoding": true,
|
||||
"SupportsDirectStream": true,
|
||||
"SupportsDirectPlay": true,
|
||||
"SupportsProbing": true,
|
||||
"MediaStreams": [],
|
||||
"Bitrate": 15201382,
|
||||
"DefaultAudioStreamIndex": null,
|
||||
"DefaultSubtitleStreamIndex": null
|
||||
}
|
||||
@@ -12,10 +12,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -30,7 +33,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Emby.Naming.Common;
|
||||
using Emby.Naming.Common;
|
||||
using Emby.Naming.TV;
|
||||
using Xunit;
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Jellyfin.Naming.Tests.TV
|
||||
private readonly NamingOptions _namingOptions = new NamingOptions();
|
||||
|
||||
[Theory]
|
||||
[InlineData("Season 21/One Piece 1001", 1001)]
|
||||
[InlineData("Watchmen (2019)/Watchmen 1x03 [WEBDL-720p][EAC3 5.1][h264][-TBS] - She Was Killed by Space Junk.mkv", 3)]
|
||||
[InlineData("The Daily Show/The Daily Show 25x22 - [WEBDL-720p][AAC 2.0][x264] Noah Baumbach-TBS.mkv", 22)]
|
||||
[InlineData("Castle Rock 2x01 Que el rio siga su curso [WEB-DL HULU 1080p h264 Dual DD5.1 Subs].mkv", 1)]
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Emby.Naming.Common;
|
||||
using Emby.Naming.Video;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Naming.Tests.Video
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Linq;
|
||||
using Emby.Naming.Common;
|
||||
using Emby.Naming.Video;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Naming.Tests.Video
|
||||
|
||||
@@ -12,12 +12,15 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers-->
|
||||
@@ -27,7 +30,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -103,10 +103,7 @@ namespace Jellyfin.Networking.Tests
|
||||
"[192.158.0.0/16,192.0.0.0/8]")]
|
||||
public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
|
||||
var conf = new NetworkConfiguration()
|
||||
{
|
||||
@@ -155,20 +152,11 @@ namespace Jellyfin.Networking.Tests
|
||||
[InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")]
|
||||
public void UnionCheck(string settings, string compare, string result)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
|
||||
if (compare == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(compare));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(compare);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(result);
|
||||
|
||||
var conf = new NetworkConfiguration()
|
||||
{
|
||||
@@ -264,20 +252,11 @@ namespace Jellyfin.Networking.Tests
|
||||
|
||||
public void TestCollectionEquality(string source, string dest, string result)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dest));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(dest);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(result);
|
||||
|
||||
var conf = new NetworkConfiguration()
|
||||
{
|
||||
@@ -331,20 +310,11 @@ namespace Jellyfin.Networking.Tests
|
||||
[InlineData("", "", false, "eth16")]
|
||||
public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
if (bindAddresses == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bindAddresses));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(bindAddresses);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(result);
|
||||
|
||||
var conf = new NetworkConfiguration()
|
||||
{
|
||||
@@ -393,7 +363,7 @@ namespace Jellyfin.Networking.Tests
|
||||
// User on external network, internal binding only - so assumption is a proxy forward, return external override.
|
||||
[InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")]
|
||||
|
||||
// User on external network, no binding - so result is the 1st external which is overriden.
|
||||
// User on external network, no binding - so result is the 1st external which is overridden.
|
||||
[InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")]
|
||||
|
||||
// User assumed to be internal, no binding - so result is the 1st internal.
|
||||
@@ -403,15 +373,9 @@ namespace Jellyfin.Networking.Tests
|
||||
[InlineData("192.168.1.1", "192.168.1.0/24", "", false, "eth16=http://helloworld.com", "http://helloworld.com")]
|
||||
public void TestBindInterfaceOverrides(string source, string lan, string bindAddresses, bool ipv6enabled, string publishedServers, string result)
|
||||
{
|
||||
if (lan == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(lan));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(lan);
|
||||
|
||||
if (bindAddresses == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bindAddresses));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(bindAddresses);
|
||||
|
||||
var conf = new NetworkConfiguration()
|
||||
{
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@@ -33,7 +33,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Jellyfin.Providers.Tests.Manager
|
||||
ValidateImages_Test(ImageType.Primary, 0, true, 0, false, 0);
|
||||
}
|
||||
|
||||
private static TheoryData<ImageType, int> GetImageTypesWithCount()
|
||||
public static TheoryData<ImageType, int> GetImageTypesWithCount()
|
||||
{
|
||||
var theoryTypes = new TheoryData<ImageType, int>
|
||||
{
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Jellyfin.Providers.Tests.Manager
|
||||
Assert.True(TestMergeBaseItemData<Audio, SongInfo>(propName, oldValue, Array.Empty<string>(), null, true, out _));
|
||||
}
|
||||
|
||||
private static TheoryData<string, object, object> MergeBaseItemData_SimpleField_ReplacesAppropriately_TestData()
|
||||
public static TheoryData<string, object, object> MergeBaseItemData_SimpleField_ReplacesAppropriately_TestData()
|
||||
=> new()
|
||||
{
|
||||
{ "IndexNumber", 1, 2 },
|
||||
|
||||
@@ -13,6 +13,7 @@ using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Providers.MediaInfo;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
@@ -43,6 +44,9 @@ public class AudioResolverTests
|
||||
MediaStreams = new List<MediaStream>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Type = MediaStreamType.Audio
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -52,7 +56,7 @@ public class AudioResolverTests
|
||||
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MediaInfoResolverTests.MetadataDirectoryRegex)))
|
||||
.Returns(true);
|
||||
|
||||
_audioResolver = new AudioResolver(localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
_audioResolver = new AudioResolver(Mock.Of<ILogger<AudioResolver>>(), localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -18,6 +18,7 @@ using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Providers.MediaInfo;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
@@ -70,7 +71,7 @@ public class MediaInfoResolverTests
|
||||
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MetadataDirectoryRegex)))
|
||||
.Returns(true);
|
||||
|
||||
_subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
_subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -201,14 +202,14 @@ public class MediaInfoResolverTests
|
||||
var mediaEncoder = Mock.Of<IMediaEncoder>(MockBehavior.Strict);
|
||||
var fileSystem = Mock.Of<IFileSystem>();
|
||||
|
||||
var subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder, fileSystem, new NamingOptions());
|
||||
var subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder, fileSystem, new NamingOptions());
|
||||
|
||||
var streams = await subtitleResolver.GetExternalStreamsAsync(video, 0, directoryService.Object, false, CancellationToken.None);
|
||||
|
||||
Assert.Empty(streams);
|
||||
}
|
||||
|
||||
private static TheoryData<string, MediaStream[], MediaStream[]> GetExternalStreams_MergeMetadata_HandlesOverridesCorrectly_Data()
|
||||
public static TheoryData<string, MediaStream[], MediaStream[]> GetExternalStreams_MergeMetadata_HandlesOverridesCorrectly_Data()
|
||||
{
|
||||
var data = new TheoryData<string, MediaStream[], MediaStream[]>();
|
||||
|
||||
@@ -306,7 +307,7 @@ public class MediaInfoResolverTests
|
||||
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MetadataDirectoryRegex)))
|
||||
.Returns(true);
|
||||
|
||||
var subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
var subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
|
||||
var directoryService = GetDirectoryServiceForExternalFile(file);
|
||||
var streams = await subtitleResolver.GetExternalStreamsAsync(video, 0, directoryService, false, CancellationToken.None);
|
||||
@@ -359,7 +360,10 @@ public class MediaInfoResolverTests
|
||||
var mediaStreams = new List<MediaStream>();
|
||||
for (int i = 0; i < streamCount; i++)
|
||||
{
|
||||
mediaStreams.Add(new());
|
||||
mediaStreams.Add(new()
|
||||
{
|
||||
Type = MediaStreamType.Subtitle
|
||||
});
|
||||
}
|
||||
|
||||
return mediaStreams;
|
||||
@@ -378,7 +382,7 @@ public class MediaInfoResolverTests
|
||||
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MetadataDirectoryRegex)))
|
||||
.Returns(true);
|
||||
|
||||
var subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
var subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
|
||||
int startIndex = 1;
|
||||
var streams = await subtitleResolver.GetExternalStreamsAsync(video, startIndex, directoryService.Object, false, CancellationToken.None);
|
||||
|
||||
@@ -13,6 +13,7 @@ using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Providers.MediaInfo;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
@@ -43,6 +44,9 @@ public class SubtitleResolverTests
|
||||
MediaStreams = new List<MediaStream>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Type = MediaStreamType.Subtitle
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -52,7 +56,7 @@ public class SubtitleResolverTests
|
||||
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MediaInfoResolverTests.MetadataDirectoryRegex)))
|
||||
.Returns(true);
|
||||
|
||||
_subtitleResolver = new SubtitleResolver(localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
_subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo
|
||||
{
|
||||
public class VideoImageProviderTests
|
||||
{
|
||||
private static TheoryData<Video> GetImage_UnsupportedInput_ReturnsNoImage_TestData()
|
||||
public static TheoryData<Video> GetImage_UnsupportedInput_ReturnsNoImage_TestData()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
@@ -36,7 +39,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -16,15 +16,39 @@ public class MediaStreamSelectorTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GetDefaultAudioStreamIndex_WithoutDefault_NotNull(bool preferDefaultTrack)
|
||||
[InlineData(new string[0], false, 1)]
|
||||
[InlineData(new string[0], true, 1)]
|
||||
[InlineData(new[] { "eng" }, false, 2)]
|
||||
[InlineData(new[] { "eng" }, true, 1)]
|
||||
[InlineData(new[] { "eng", "fre" }, false, 2)]
|
||||
[InlineData(new[] { "fre", "eng" }, false, 1)]
|
||||
[InlineData(new[] { "eng", "fre" }, true, 1)]
|
||||
public void GetDefaultAudioStreamIndex_PreferredLanguage_SelectsCorrect(string[] preferredLanguages, bool preferDefaultTrack, int expectedIndex)
|
||||
{
|
||||
var streams = new[]
|
||||
var streams = new MediaStream[]
|
||||
{
|
||||
new MediaStream()
|
||||
new()
|
||||
{
|
||||
Index = 0,
|
||||
Type = MediaStreamType.Video,
|
||||
IsDefault = true
|
||||
},
|
||||
new()
|
||||
{
|
||||
Index = 1,
|
||||
Type = MediaStreamType.Audio,
|
||||
Language = "fre",
|
||||
IsDefault = true
|
||||
},
|
||||
new()
|
||||
{
|
||||
Index = 2,
|
||||
Type = MediaStreamType.Audio,
|
||||
Language = "eng",
|
||||
IsDefault = false
|
||||
}
|
||||
};
|
||||
|
||||
Assert.NotNull(MediaStreamSelector.GetDefaultAudioStreamIndex(streams, Array.Empty<string>(), preferDefaultTrack));
|
||||
Assert.Equal(expectedIndex, MediaStreamSelector.GetDefaultAudioStreamIndex(streams, preferredLanguages, preferDefaultTrack));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,17 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
EpisodeTitle = "The VCR Illumination"
|
||||
});
|
||||
|
||||
data.Add(
|
||||
"Lorem ipsum dolor sit amet: consect 2018_12_06_21_06_00",
|
||||
new TimerInfo
|
||||
{
|
||||
Name = "Lorem ipsum dolor sit amet: consect",
|
||||
IsProgramSeries = true,
|
||||
StartDate = new DateTime(2018, 12, 6, 21, 6, 0, DateTimeKind.Local),
|
||||
OriginalAirDate = new DateTime(2018, 12, 6),
|
||||
EpisodeTitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor"
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// /token reponse.
|
||||
/// /token response.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Deserialize_Token_Response_Live_Success()
|
||||
|
||||
@@ -50,7 +50,10 @@ namespace Jellyfin.Server.Implementations.Tests.QuickConnect
|
||||
|
||||
[Fact]
|
||||
public void IsEnabled_QuickConnectUnavailable_False()
|
||||
=> Assert.False(_quickConnectManager.IsEnabled);
|
||||
{
|
||||
_config.QuickConnectAvailable = false;
|
||||
Assert.False(_quickConnectManager.IsEnabled);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "DeviceId", "Client", "1.0.0")]
|
||||
@@ -69,19 +72,31 @@ namespace Jellyfin.Server.Implementations.Tests.QuickConnect
|
||||
|
||||
[Fact]
|
||||
public void TryConnect_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
=> Assert.Throws<AuthenticationException>(() => _quickConnectManager.TryConnect(_quickConnectAuthInfo));
|
||||
{
|
||||
_config.QuickConnectAvailable = false;
|
||||
Assert.Throws<AuthenticationException>(() => _quickConnectManager.TryConnect(_quickConnectAuthInfo));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckRequestStatus_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
=> Assert.Throws<AuthenticationException>(() => _quickConnectManager.CheckRequestStatus(string.Empty));
|
||||
{
|
||||
_config.QuickConnectAvailable = false;
|
||||
Assert.Throws<AuthenticationException>(() => _quickConnectManager.CheckRequestStatus(string.Empty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
=> Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
|
||||
{
|
||||
_config.QuickConnectAvailable = false;
|
||||
Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAuthorizedRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
=> Assert.Throws<AuthenticationException>(() => _quickConnectManager.GetAuthorizedRequest(string.Empty));
|
||||
{
|
||||
_config.QuickConnectAvailable = false;
|
||||
Assert.Throws<AuthenticationException>(() => _quickConnectManager.GetAuthorizedRequest(string.Empty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsEnabled_QuickConnectAvailable_True()
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using Emby.Server.Implementations.Sorting;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.Tests.Sorting;
|
||||
|
||||
public class IndexNumberComparerTests
|
||||
{
|
||||
private readonly IBaseItemComparer _cmp = new IndexNumberComparer();
|
||||
|
||||
public static TheoryData<BaseItem?, BaseItem?> Compare_GivenNull_ThrowsArgumentNullException_TestData()
|
||||
=> new()
|
||||
{
|
||||
{ null, new Audio() },
|
||||
{ new Audio(), null }
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Compare_GivenNull_ThrowsArgumentNullException_TestData))]
|
||||
public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem? x, BaseItem? y)
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _cmp.Compare(x, y));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, 0)]
|
||||
[InlineData(0, null, 1)]
|
||||
[InlineData(null, 0, -1)]
|
||||
[InlineData(1, 1, 0)]
|
||||
[InlineData(0, 1, -1)]
|
||||
[InlineData(1, 0, 1)]
|
||||
public void Compare_ValidIndices_SortsExpected(int? index1, int? index2, int expected)
|
||||
{
|
||||
BaseItem x = new Audio
|
||||
{
|
||||
IndexNumber = index1
|
||||
};
|
||||
BaseItem y = new Audio
|
||||
{
|
||||
IndexNumber = index2
|
||||
};
|
||||
|
||||
Assert.Equal(expected, _cmp.Compare(x, y));
|
||||
Assert.Equal(-expected, _cmp.Compare(y, x));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using Emby.Server.Implementations.Sorting;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.Tests.Sorting;
|
||||
|
||||
public class ParentIndexNumberComparerTests
|
||||
{
|
||||
private readonly IBaseItemComparer _cmp = new ParentIndexNumberComparer();
|
||||
|
||||
public static TheoryData<BaseItem?, BaseItem?> Compare_GivenNull_ThrowsArgumentNullException_TestData()
|
||||
=> new()
|
||||
{
|
||||
{ null, new Audio() },
|
||||
{ new Audio(), null }
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Compare_GivenNull_ThrowsArgumentNullException_TestData))]
|
||||
public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem? x, BaseItem? y)
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => _cmp.Compare(x, y));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, 0)]
|
||||
[InlineData(0, null, 1)]
|
||||
[InlineData(null, 0, -1)]
|
||||
[InlineData(1, 1, 0)]
|
||||
[InlineData(0, 1, -1)]
|
||||
[InlineData(1, 0, 1)]
|
||||
public void Compare_ValidIndices_SortsExpected(int? parentIndex1, int? parentIndex2, int expected)
|
||||
{
|
||||
BaseItem x = new Audio
|
||||
{
|
||||
ParentIndexNumber = parentIndex1
|
||||
};
|
||||
BaseItem y = new Audio
|
||||
{
|
||||
ParentIndexNumber = parentIndex2
|
||||
};
|
||||
|
||||
Assert.Equal(expected, _cmp.Compare(x, y));
|
||||
Assert.Equal(-expected, _cmp.Compare(y, x));
|
||||
}
|
||||
}
|
||||
@@ -253,7 +253,7 @@
|
||||
"versions": [
|
||||
{
|
||||
"version": "5.0.0.0",
|
||||
"changelog": "Updated to use NextPVR API v5, no longer compatable with API v4.\n",
|
||||
"changelog": "Updated to use NextPVR API v5, no longer compatible with API v4.\n",
|
||||
"targetAbi": "10.7.0.0",
|
||||
"sourceUrl": "https://repo.jellyfin.org/releases/plugin/nextpvr/nextpvr_5.0.0.0.zip",
|
||||
"checksum": "d70f694d14bf9462ba2b2ebe110068d3",
|
||||
|
||||
@@ -83,6 +83,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
|
||||
var res = await response.Content.ReadAsStreamAsync();
|
||||
var data = await JsonSerializer.DeserializeAsync<ConfigurationPageInfo[]>(res, _jsonOpions);
|
||||
Assert.NotNull(data);
|
||||
Assert.Empty(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
var client = _factory.CreateClient();
|
||||
client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
|
||||
|
||||
using var getResponse = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
|
||||
using var response = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -45,8 +45,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
var client = _factory.CreateClient();
|
||||
client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
|
||||
|
||||
using var getResponse = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
|
||||
using var response = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -61,8 +61,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
Name = "ThisProfileDoesNotExist"
|
||||
};
|
||||
|
||||
using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
|
||||
using var response = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -77,8 +77,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
Name = "ThisProfileIsNew"
|
||||
};
|
||||
|
||||
using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode);
|
||||
using var response = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -115,20 +115,46 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
Id = _newDeviceProfileId
|
||||
};
|
||||
|
||||
using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles", updatedProfile, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode);
|
||||
using var postResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + _newDeviceProfileId, updatedProfile, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode);
|
||||
|
||||
// Verify that the profile got updated
|
||||
using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType);
|
||||
Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet);
|
||||
|
||||
var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>(
|
||||
await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
|
||||
_jsonOptions).ConfigureAwait(false);
|
||||
|
||||
Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal)));
|
||||
var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal));
|
||||
Assert.NotNull(newProfile);
|
||||
_newDeviceProfileId = newProfile!.Id;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Priority(4)]
|
||||
[Priority(5)]
|
||||
public async Task DeleteProfile_Valid_NoContent()
|
||||
{
|
||||
var client = _factory.CreateClient();
|
||||
client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
|
||||
|
||||
using var getResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false);
|
||||
Console.WriteLine(await getResponse.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode);
|
||||
using var deleteResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.NoContent, deleteResponse.StatusCode);
|
||||
|
||||
// Verify that the profile got deleted
|
||||
using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false);
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType);
|
||||
Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet);
|
||||
|
||||
var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>(
|
||||
await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
|
||||
_jsonOptions).ConfigureAwait(false);
|
||||
|
||||
Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
|
||||
using var contentStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
var user = await JsonSerializer.DeserializeAsync<StartupUserDto>(contentStream, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.NotEmpty(user!.Name);
|
||||
Assert.NotNull(user);
|
||||
Assert.NotNull(user.Name);
|
||||
Assert.NotEmpty(user.Name);
|
||||
Assert.Null(user.Password);
|
||||
}
|
||||
|
||||
@@ -87,7 +89,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
|
||||
var contentStream = await getResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
var newUser = await JsonSerializer.DeserializeAsync<StartupUserDto>(contentStream, _jsonOptions).ConfigureAwait(false);
|
||||
Assert.Equal(user.Name, newUser!.Name);
|
||||
Assert.NotNull(newUser);
|
||||
Assert.Equal(user.Name, newUser.Name);
|
||||
Assert.NotNull(newUser.Password);
|
||||
Assert.NotEmpty(newUser.Password);
|
||||
Assert.NotEqual(user.Password, newUser.Password);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
var users = await JsonSerializer.DeserializeAsync<UserDto[]>(
|
||||
await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false);
|
||||
// User are hidden by default
|
||||
Assert.NotNull(users);
|
||||
Assert.Empty(users);
|
||||
}
|
||||
|
||||
@@ -60,6 +61,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var users = await JsonSerializer.DeserializeAsync<UserDto[]>(
|
||||
await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false);
|
||||
Assert.NotNull(users);
|
||||
Assert.Single(users);
|
||||
Assert.False(users![0].HasConfiguredPassword);
|
||||
}
|
||||
|
||||
@@ -9,14 +9,17 @@
|
||||
<PackageReference Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -33,7 +36,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog;
|
||||
using Serilog.Extensions.Logging;
|
||||
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
|
||||
|
||||
namespace Jellyfin.Server.Integration.Tests
|
||||
{
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
<PackageReference Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
@@ -26,7 +29,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="Moq" Version="4.17.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -27,7 +30,7 @@
|
||||
<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.406" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Jellyfin.Data.Entities;
|
||||
|
||||
Reference in New Issue
Block a user