mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-10 08:13:20 +01:00
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:
@@ -1,11 +1,8 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CA1068, CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -83,9 +80,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
CancellationToken cancellationToken)
|
||||
where T : Video
|
||||
{
|
||||
BlurayDiscInfo blurayDiscInfo = null;
|
||||
BlurayDiscInfo? blurayDiscInfo = null;
|
||||
|
||||
Model.MediaInfo.MediaInfo mediaInfoResult = null;
|
||||
Model.MediaInfo.MediaInfo? mediaInfoResult = null;
|
||||
|
||||
if (!item.IsShortcut || options.EnableRemoteContentProbe)
|
||||
{
|
||||
@@ -131,7 +128,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
var m2ts = _mediaEncoder.GetPrimaryPlaylistM2tsFiles(item.Path);
|
||||
|
||||
// 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.");
|
||||
return ItemUpdateType.MetadataImport;
|
||||
@@ -192,16 +189,14 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
protected async Task Fetch(
|
||||
Video video,
|
||||
CancellationToken cancellationToken,
|
||||
Model.MediaInfo.MediaInfo mediaInfo,
|
||||
BlurayDiscInfo blurayInfo,
|
||||
Model.MediaInfo.MediaInfo? mediaInfo,
|
||||
BlurayDiscInfo? blurayInfo,
|
||||
MetadataRefreshOptions options)
|
||||
{
|
||||
List<MediaStream> mediaStreams;
|
||||
List<MediaStream> mediaStreams = new List<MediaStream>();
|
||||
IReadOnlyList<MediaAttachment> mediaAttachments;
|
||||
ChapterInfo[] chapters;
|
||||
|
||||
mediaStreams = new List<MediaStream>();
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -221,18 +216,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
video.TotalBitrate = mediaInfo.Bitrate;
|
||||
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
||||
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;
|
||||
|
||||
chapters = mediaInfo.Chapters ?? Array.Empty<ChapterInfo>();
|
||||
@@ -243,8 +226,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentMediaStreams = video.GetMediaStreams();
|
||||
foreach (var mediaStream in currentMediaStreams)
|
||||
foreach (var mediaStream in video.GetMediaStreams())
|
||||
{
|
||||
if (!mediaStream.IsExternal)
|
||||
{
|
||||
@@ -295,8 +277,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
||||
}
|
||||
|
||||
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
||||
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
||||
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh
|
||||
|| options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
string name = chapters[i].Name;
|
||||
string? name = chapters[i].Name;
|
||||
// Check if the name is empty and/or if the name is a time
|
||||
// Some ripping programs do that.
|
||||
if (string.IsNullOrWhiteSpace(name) ||
|
||||
TimeSpan.TryParse(name, out _))
|
||||
if (string.IsNullOrWhiteSpace(name)
|
||||
|| TimeSpan.TryParse(name, out _))
|
||||
{
|
||||
chapters[i].Name = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
@@ -384,23 +366,18 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
// Use the ffprobe values if these are empty
|
||||
if (videoStream is not null)
|
||||
{
|
||||
videoStream.BitRate = IsEmpty(videoStream.BitRate) ? currentBitRate : videoStream.BitRate;
|
||||
videoStream.Width = IsEmpty(videoStream.Width) ? currentWidth : videoStream.Width;
|
||||
videoStream.Height = IsEmpty(videoStream.Height) ? currentHeight : videoStream.Height;
|
||||
videoStream.BitRate = videoStream.BitRate.GetValueOrDefault() == 0 ? currentBitRate : videoStream.BitRate;
|
||||
videoStream.Width = videoStream.Width.GetValueOrDefault() == 0 ? currentWidth : videoStream.Width;
|
||||
videoStream.Height = videoStream.Height.GetValueOrDefault() == 0 ? currentHeight : videoStream.Height;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsEmpty(int? num)
|
||||
{
|
||||
return !num.HasValue || num.Value == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about the longest playlist on a bdrom.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>VideoStream.</returns>
|
||||
private BlurayDiscInfo GetBDInfo(string path)
|
||||
private BlurayDiscInfo? GetBDInfo(string path)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||
|
||||
@@ -527,32 +504,29 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private SubtitleOptions GetOptions()
|
||||
{
|
||||
return _config.GetConfiguration<SubtitleOptions>("subtitles");
|
||||
if (options.ReplaceAllMetadata || _libraryManager.GetPeople(video).Count == 0)
|
||||
{
|
||||
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>
|
||||
@@ -575,7 +549,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
|
||||
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
|
||||
|
||||
var subtitleOptions = GetOptions();
|
||||
var subtitleOptions = _config.GetConfiguration<SubtitleOptions>("subtitles");
|
||||
|
||||
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
||||
|
||||
@@ -659,9 +633,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
/// </summary>
|
||||
/// <param name="video">The video.</param>
|
||||
/// <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.
|
||||
if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks)
|
||||
@@ -671,30 +645,30 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0} has an invalid runtime of {1} minutes",
|
||||
video.Name,
|
||||
TimeSpan.FromTicks(runtime).Minutes));
|
||||
TimeSpan.FromTicks(runtime).TotalMinutes));
|
||||
}
|
||||
|
||||
long dummyChapterDuration = TimeSpan.FromSeconds(_config.Configuration.DummyChapterDuration).Ticks;
|
||||
if (runtime > dummyChapterDuration)
|
||||
if (runtime <= dummyChapterDuration)
|
||||
{
|
||||
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;
|
||||
return Array.Empty<ChapterInfo>();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user