Enable nullable for more files and add tests
Adds basic tests for FFProbeVideoInfo.CreateDummyChapters Fixed error message CreateDummyChapters instead of reporting the total minutes it only reported the minute component
This commit is contained in:
parent
84643e328d
commit
d92e9ae85e
|
@ -1971,18 +1971,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
if (reader.TryGetString(2, out var imagePath))
|
if (reader.TryGetString(2, out var imagePath))
|
||||||
{
|
{
|
||||||
chapter.ImagePath = imagePath;
|
chapter.ImagePath = imagePath;
|
||||||
|
chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
|
||||||
if (!string.IsNullOrEmpty(chapter.ImagePath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex, "Failed to create image cache tag.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.TryReadDateTime(3, out var imageDateModified))
|
if (reader.TryReadDateTime(3, out var imageDateModified))
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||||
/// <returns>Guid.</returns>
|
/// <returns>Guid.</returns>
|
||||||
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
|
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
|
||||||
|
|
||||||
string GetImageCacheTag(BaseItem item, ChapterInfo chapter);
|
string? GetImageCacheTag(BaseItem item, ChapterInfo chapter);
|
||||||
|
|
||||||
string? GetImageCacheTag(User user);
|
string? GetImageCacheTag(User user);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
@ -14,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the path.
|
/// Gets or sets the path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The path.</value>
|
/// <value>The path.</value>
|
||||||
public string Path { get; set; }
|
public required string Path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type.
|
/// Gets or sets the type.
|
||||||
|
@ -36,9 +34,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Gets or sets the blurhash.
|
/// Gets or sets the blurhash.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The blurhash.</value>
|
/// <value>The blurhash.</value>
|
||||||
public string BlurHash { get; set; }
|
public string? BlurHash { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool IsLocalFile => Path is null || !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
public bool IsLocalFile => !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#nullable enable
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Security
|
namespace MediaBrowser.Controller.Security
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#nullable disable
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
@ -20,16 +19,16 @@ namespace MediaBrowser.Model.Entities
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the image path.
|
/// Gets or sets the image path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The image path.</value>
|
/// <value>The image path.</value>
|
||||||
public string ImagePath { get; set; }
|
public string? ImagePath { get; set; }
|
||||||
|
|
||||||
public DateTime ImageDateModified { get; set; }
|
public DateTime ImageDateModified { get; set; }
|
||||||
|
|
||||||
public string ImageTag { get; set; }
|
public string? ImageTag { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CA1068, CS1591
|
#pragma warning disable CA1068, CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -83,9 +80,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
where T : Video
|
where T : Video
|
||||||
{
|
{
|
||||||
BlurayDiscInfo blurayDiscInfo = null;
|
BlurayDiscInfo? blurayDiscInfo = null;
|
||||||
|
|
||||||
Model.MediaInfo.MediaInfo mediaInfoResult = null;
|
Model.MediaInfo.MediaInfo? mediaInfoResult = null;
|
||||||
|
|
||||||
if (!item.IsShortcut || options.EnableRemoteContentProbe)
|
if (!item.IsShortcut || options.EnableRemoteContentProbe)
|
||||||
{
|
{
|
||||||
|
@ -131,7 +128,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
var m2ts = _mediaEncoder.GetPrimaryPlaylistM2tsFiles(item.Path);
|
var m2ts = _mediaEncoder.GetPrimaryPlaylistM2tsFiles(item.Path);
|
||||||
|
|
||||||
// Return if no playable .m2ts files are found
|
// Return if no playable .m2ts files are found
|
||||||
if (blurayDiscInfo.Files.Length == 0 || m2ts.Count == 0)
|
if (blurayDiscInfo == null || blurayDiscInfo.Files.Length == 0 || m2ts.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.LogError("No playable .m2ts files found in Blu-ray structure, skipping FFprobe.");
|
_logger.LogError("No playable .m2ts files found in Blu-ray structure, skipping FFprobe.");
|
||||||
return ItemUpdateType.MetadataImport;
|
return ItemUpdateType.MetadataImport;
|
||||||
|
@ -192,16 +189,14 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
protected async Task Fetch(
|
protected async Task Fetch(
|
||||||
Video video,
|
Video video,
|
||||||
CancellationToken cancellationToken,
|
CancellationToken cancellationToken,
|
||||||
Model.MediaInfo.MediaInfo mediaInfo,
|
Model.MediaInfo.MediaInfo? mediaInfo,
|
||||||
BlurayDiscInfo blurayInfo,
|
BlurayDiscInfo? blurayInfo,
|
||||||
MetadataRefreshOptions options)
|
MetadataRefreshOptions options)
|
||||||
{
|
{
|
||||||
List<MediaStream> mediaStreams;
|
List<MediaStream> mediaStreams = new List<MediaStream>();
|
||||||
IReadOnlyList<MediaAttachment> mediaAttachments;
|
IReadOnlyList<MediaAttachment> mediaAttachments;
|
||||||
ChapterInfo[] chapters;
|
ChapterInfo[] chapters;
|
||||||
|
|
||||||
mediaStreams = new List<MediaStream>();
|
|
||||||
|
|
||||||
// Add external streams before adding the streams from the file to preserve stream IDs on remote videos
|
// Add external streams before adding the streams from the file to preserve stream IDs on remote videos
|
||||||
await AddExternalSubtitlesAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
await AddExternalSubtitlesAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -221,18 +216,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
video.TotalBitrate = mediaInfo.Bitrate;
|
video.TotalBitrate = mediaInfo.Bitrate;
|
||||||
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
||||||
video.Size = mediaInfo.Size;
|
video.Size = mediaInfo.Size;
|
||||||
|
|
||||||
if (video.VideoType == VideoType.VideoFile)
|
|
||||||
{
|
|
||||||
var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');
|
|
||||||
|
|
||||||
video.Container = extension;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
video.Container = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
video.Container = mediaInfo.Container;
|
video.Container = mediaInfo.Container;
|
||||||
|
|
||||||
chapters = mediaInfo.Chapters ?? Array.Empty<ChapterInfo>();
|
chapters = mediaInfo.Chapters ?? Array.Empty<ChapterInfo>();
|
||||||
|
@ -243,8 +226,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var currentMediaStreams = video.GetMediaStreams();
|
foreach (var mediaStream in video.GetMediaStreams())
|
||||||
foreach (var mediaStream in currentMediaStreams)
|
|
||||||
{
|
{
|
||||||
if (!mediaStream.IsExternal)
|
if (!mediaStream.IsExternal)
|
||||||
{
|
{
|
||||||
|
@ -295,8 +277,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh
|
||||||
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
|| options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
||||||
{
|
{
|
||||||
if (_config.Configuration.DummyChapterDuration > 0 && chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
if (_config.Configuration.DummyChapterDuration > 0 && chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
||||||
{
|
{
|
||||||
|
@ -321,11 +303,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
{
|
{
|
||||||
for (int i = 0; i < chapters.Length; i++)
|
for (int i = 0; i < chapters.Length; i++)
|
||||||
{
|
{
|
||||||
string name = chapters[i].Name;
|
string? name = chapters[i].Name;
|
||||||
// Check if the name is empty and/or if the name is a time
|
// Check if the name is empty and/or if the name is a time
|
||||||
// Some ripping programs do that.
|
// Some ripping programs do that.
|
||||||
if (string.IsNullOrWhiteSpace(name) ||
|
if (string.IsNullOrWhiteSpace(name)
|
||||||
TimeSpan.TryParse(name, out _))
|
|| TimeSpan.TryParse(name, out _))
|
||||||
{
|
{
|
||||||
chapters[i].Name = string.Format(
|
chapters[i].Name = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
|
@ -384,23 +366,18 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
// Use the ffprobe values if these are empty
|
// Use the ffprobe values if these are empty
|
||||||
if (videoStream is not null)
|
if (videoStream is not null)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = IsEmpty(videoStream.BitRate) ? currentBitRate : videoStream.BitRate;
|
videoStream.BitRate = videoStream.BitRate.GetValueOrDefault() == 0 ? currentBitRate : videoStream.BitRate;
|
||||||
videoStream.Width = IsEmpty(videoStream.Width) ? currentWidth : videoStream.Width;
|
videoStream.Width = videoStream.Width.GetValueOrDefault() == 0 ? currentWidth : videoStream.Width;
|
||||||
videoStream.Height = IsEmpty(videoStream.Height) ? currentHeight : videoStream.Height;
|
videoStream.Height = videoStream.Height.GetValueOrDefault() == 0 ? currentHeight : videoStream.Height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsEmpty(int? num)
|
|
||||||
{
|
|
||||||
return !num.HasValue || num.Value == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets information about the longest playlist on a bdrom.
|
/// Gets information about the longest playlist on a bdrom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <returns>VideoStream.</returns>
|
/// <returns>VideoStream.</returns>
|
||||||
private BlurayDiscInfo GetBDInfo(string path)
|
private BlurayDiscInfo? GetBDInfo(string path)
|
||||||
{
|
{
|
||||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||||
|
|
||||||
|
@ -527,32 +504,29 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
|
|
||||||
private void FetchPeople(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
|
private void FetchPeople(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
|
||||||
{
|
{
|
||||||
var replaceData = options.ReplaceAllMetadata;
|
if (video.IsLocked
|
||||||
|
|| video.LockedFields.Contains(MetadataField.Cast)
|
||||||
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Cast))
|
|| data.People.Length == 0)
|
||||||
{
|
{
|
||||||
if (replaceData || _libraryManager.GetPeople(video).Count == 0)
|
return;
|
||||||
{
|
|
||||||
var people = new List<PersonInfo>();
|
|
||||||
|
|
||||||
foreach (var person in data.People)
|
|
||||||
{
|
|
||||||
PeopleHelper.AddPerson(people, new PersonInfo
|
|
||||||
{
|
|
||||||
Name = person.Name,
|
|
||||||
Type = person.Type,
|
|
||||||
Role = person.Role
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_libraryManager.UpdatePeople(video, people);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private SubtitleOptions GetOptions()
|
if (options.ReplaceAllMetadata || _libraryManager.GetPeople(video).Count == 0)
|
||||||
{
|
{
|
||||||
return _config.GetConfiguration<SubtitleOptions>("subtitles");
|
var people = new List<PersonInfo>();
|
||||||
|
|
||||||
|
foreach (var person in data.People)
|
||||||
|
{
|
||||||
|
PeopleHelper.AddPerson(people, new PersonInfo
|
||||||
|
{
|
||||||
|
Name = person.Name,
|
||||||
|
Type = person.Type,
|
||||||
|
Role = person.Role
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_libraryManager.UpdatePeople(video, people);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -575,7 +549,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
|
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
|
||||||
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
|
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
|
||||||
|
|
||||||
var subtitleOptions = GetOptions();
|
var subtitleOptions = _config.GetConfiguration<SubtitleOptions>("subtitles");
|
||||||
|
|
||||||
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
||||||
|
|
||||||
|
@ -659,9 +633,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="video">The video.</param>
|
/// <param name="video">The video.</param>
|
||||||
/// <returns>An array of dummy chapters.</returns>
|
/// <returns>An array of dummy chapters.</returns>
|
||||||
private ChapterInfo[] CreateDummyChapters(Video video)
|
internal ChapterInfo[] CreateDummyChapters(Video video)
|
||||||
{
|
{
|
||||||
var runtime = video.RunTimeTicks ?? 0;
|
var runtime = video.RunTimeTicks.GetValueOrDefault();
|
||||||
|
|
||||||
// Only process files with a runtime higher than 0 and lower than 12h. The latter are likely corrupted.
|
// Only process files with a runtime higher than 0 and lower than 12h. The latter are likely corrupted.
|
||||||
if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks)
|
if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks)
|
||||||
|
@ -671,30 +645,30 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"{0} has an invalid runtime of {1} minutes",
|
"{0} has an invalid runtime of {1} minutes",
|
||||||
video.Name,
|
video.Name,
|
||||||
TimeSpan.FromTicks(runtime).Minutes));
|
TimeSpan.FromTicks(runtime).TotalMinutes));
|
||||||
}
|
}
|
||||||
|
|
||||||
long dummyChapterDuration = TimeSpan.FromSeconds(_config.Configuration.DummyChapterDuration).Ticks;
|
long dummyChapterDuration = TimeSpan.FromSeconds(_config.Configuration.DummyChapterDuration).Ticks;
|
||||||
if (runtime > dummyChapterDuration)
|
if (runtime <= dummyChapterDuration)
|
||||||
{
|
{
|
||||||
int chapterCount = (int)(runtime / dummyChapterDuration);
|
return Array.Empty<ChapterInfo>();
|
||||||
var chapters = new ChapterInfo[chapterCount];
|
|
||||||
|
|
||||||
long currentChapterTicks = 0;
|
|
||||||
for (int i = 0; i < chapterCount; i++)
|
|
||||||
{
|
|
||||||
chapters[i] = new ChapterInfo
|
|
||||||
{
|
|
||||||
StartPositionTicks = currentChapterTicks
|
|
||||||
};
|
|
||||||
|
|
||||||
currentChapterTicks += dummyChapterDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
return chapters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.Empty<ChapterInfo>();
|
int chapterCount = (int)(runtime / dummyChapterDuration);
|
||||||
|
var chapters = new ChapterInfo[chapterCount];
|
||||||
|
|
||||||
|
long currentChapterTicks = 0;
|
||||||
|
for (int i = 0; i < chapterCount; i++)
|
||||||
|
{
|
||||||
|
chapters[i] = new ChapterInfo
|
||||||
|
{
|
||||||
|
StartPositionTicks = currentChapterTicks
|
||||||
|
};
|
||||||
|
|
||||||
|
currentChapterTicks += dummyChapterDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chapters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
@ -437,8 +436,13 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
|
||||||
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetImageCacheTag(BaseItem item, ChapterInfo chapter)
|
public string? GetImageCacheTag(BaseItem item, ChapterInfo chapter)
|
||||||
{
|
{
|
||||||
|
if (chapter.ImagePath is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return GetImageCacheTag(item, new ItemImageInfo
|
return GetImageCacheTag(item, new ItemImageInfo
|
||||||
{
|
{
|
||||||
Path = chapter.ImagePath,
|
Path = chapter.ImagePath,
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AutoFixture" />
|
||||||
|
<PackageReference Include="AutoFixture.AutoMoq" />
|
||||||
|
<PackageReference Include="AutoFixture.Xunit2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
<PackageReference Include="Moq" />
|
<PackageReference Include="Moq" />
|
||||||
<PackageReference Include="xunit" />
|
<PackageReference Include="xunit" />
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using AutoFixture;
|
||||||
|
using AutoFixture.AutoMoq;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using MediaBrowser.Providers.MediaInfo;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Jellyfin.Providers.Tests.MediaInfo;
|
||||||
|
|
||||||
|
public class FFProbeVideoInfoTests
|
||||||
|
{
|
||||||
|
private readonly FFProbeVideoInfo _fFProbeVideoInfo;
|
||||||
|
|
||||||
|
public FFProbeVideoInfoTests()
|
||||||
|
{
|
||||||
|
var serverConfiguration = new ServerConfiguration()
|
||||||
|
{
|
||||||
|
DummyChapterDuration = (int)TimeSpan.FromMinutes(5).TotalSeconds
|
||||||
|
};
|
||||||
|
var serverConfig = new Mock<IServerConfigurationManager>();
|
||||||
|
serverConfig.Setup(c => c.Configuration)
|
||||||
|
.Returns(serverConfiguration);
|
||||||
|
|
||||||
|
IFixture fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
|
||||||
|
fixture.Inject(serverConfig);
|
||||||
|
_fFProbeVideoInfo = fixture.Create<FFProbeVideoInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-1L)]
|
||||||
|
[InlineData(long.MinValue)]
|
||||||
|
[InlineData(long.MaxValue)]
|
||||||
|
public void CreateDummyChapters_InvalidRuntime_ThrowsArgumentException(long? runtime)
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentException>(
|
||||||
|
() => _fFProbeVideoInfo.CreateDummyChapters(new Video()
|
||||||
|
{
|
||||||
|
RunTimeTicks = runtime
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(null, 0)]
|
||||||
|
[InlineData(0L, 0)]
|
||||||
|
[InlineData(1L, 0)]
|
||||||
|
[InlineData(TimeSpan.TicksPerMinute * 5, 0)]
|
||||||
|
[InlineData((TimeSpan.TicksPerMinute * 5) + 1, 1)]
|
||||||
|
[InlineData(TimeSpan.TicksPerMinute * 50, 10)]
|
||||||
|
public void CreateDummyChapters_ValidRuntime_CorrectChaptersCount(long? runtime, int chaptersCount)
|
||||||
|
{
|
||||||
|
var chapters = _fFProbeVideoInfo.CreateDummyChapters(new Video()
|
||||||
|
{
|
||||||
|
RunTimeTicks = runtime
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal(chaptersCount, chapters.Length);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user