Skip to content

Commit

Permalink
Enable nullable for more files and add tests
Browse files Browse the repository at this point in the history
Adds basic tests for FFProbeVideoInfo.CreateDummyChapters
Fixed error message CreateDummyChapters instead of reporting the total minutes it only reported the minute component
  • Loading branch information
Bond-009 committed Aug 22, 2023
1 parent 84643e3 commit d92e9ae
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 104 deletions.
13 changes: 1 addition & 12 deletions Emby.Server.Implementations/Data/SqliteItemRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1971,18 +1971,7 @@ private ChapterInfo GetChapter(IReadOnlyList<ResultSetValue> reader, BaseItem it
if (reader.TryGetString(2, out var imagePath))
{
chapter.ImagePath = imagePath;

if (!string.IsNullOrEmpty(chapter.ImagePath))
{
try
{
chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
}
catch (Exception ex)
{
Logger.LogError(ex, "Failed to create image cache tag.");
}
}
chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
}

if (reader.TryReadDateTime(3, out var imageDateModified))
Expand Down
2 changes: 1 addition & 1 deletion MediaBrowser.Controller/Drawing/IImageProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public interface IImageProcessor
/// <returns>Guid.</returns>
string GetImageCacheTag(BaseItem item, ItemImageInfo image);

string GetImageCacheTag(BaseItem item, ChapterInfo chapter);
string? GetImageCacheTag(BaseItem item, ChapterInfo chapter);

string? GetImageCacheTag(User user);

Expand Down
8 changes: 3 additions & 5 deletions MediaBrowser.Controller/Entities/ItemImageInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#nullable disable

#pragma warning disable CS1591

using System;
Expand All @@ -14,7 +12,7 @@ public class ItemImageInfo
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string Path { get; set; }
public required string Path { get; set; }

/// <summary>
/// Gets or sets the type.
Expand All @@ -36,9 +34,9 @@ public class ItemImageInfo
/// Gets or sets the blurhash.
/// </summary>
/// <value>The blurhash.</value>
public string BlurHash { get; set; }
public string? BlurHash { get; set; }

[JsonIgnore]
public bool IsLocalFile => Path is null || !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
public bool IsLocalFile => !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
}
}
4 changes: 1 addition & 3 deletions MediaBrowser.Controller/Security/IAuthenticationManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#nullable enable

using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MediaBrowser.Controller.Security
Expand Down
7 changes: 3 additions & 4 deletions MediaBrowser.Model/Entities/ChapterInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable disable
#pragma warning disable CS1591

using System;
Expand All @@ -20,16 +19,16 @@ public class ChapterInfo
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
public string? Name { get; set; }

/// <summary>
/// Gets or sets the image path.
/// </summary>
/// <value>The image path.</value>
public string ImagePath { get; set; }
public string? ImagePath { get; set; }

public DateTime ImageDateModified { get; set; }

public string ImageTag { get; set; }
public string? ImageTag { get; set; }
}
}
128 changes: 51 additions & 77 deletions MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -83,9 +80,9 @@ public async Task<ItemUpdateType> ProbeVideo<T>(
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)
{
Expand Down Expand Up @@ -131,7 +128,7 @@ public async Task<ItemUpdateType> ProbeVideo<T>(
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;
Expand Down Expand Up @@ -192,16 +189,14 @@ public async Task<ItemUpdateType> ProbeVideo<T>(
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);

Expand All @@ -221,18 +216,6 @@ protected async Task Fetch(
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>();
Expand All @@ -243,8 +226,7 @@ protected async Task Fetch(
}
else
{
var currentMediaStreams = video.GetMediaStreams();
foreach (var mediaStream in currentMediaStreams)
foreach (var mediaStream in video.GetMediaStreams())
{
if (!mediaStream.IsExternal)
{
Expand Down Expand Up @@ -295,8 +277,8 @@ protected async Task Fetch(
_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))
{
Expand All @@ -321,11 +303,11 @@ private void NormalizeChapterNames(ChapterInfo[] chapters)
{
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,
Expand Down Expand Up @@ -384,23 +366,18 @@ private void FetchBdInfo(Video video, ref ChapterInfo[] chapters, List<MediaStre
// 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);

Expand Down Expand Up @@ -527,32 +504,29 @@ private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, Meta

private void FetchPeople(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
{
var replaceData = options.ReplaceAllMetadata;
if (video.IsLocked
|| video.LockedFields.Contains(MetadataField.Cast)
|| data.People.Length == 0)
{
return;
}

if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Cast))
if (options.ReplaceAllMetadata || _libraryManager.GetPeople(video).Count == 0)
{
if (replaceData || _libraryManager.GetPeople(video).Count == 0)
{
var people = new List<PersonInfo>();
var people = new List<PersonInfo>();

foreach (var person in data.People)
foreach (var person in data.People)
{
PeopleHelper.AddPerson(people, new PersonInfo
{
PeopleHelper.AddPerson(people, new PersonInfo
{
Name = person.Name,
Type = person.Type,
Role = person.Role
});
}

_libraryManager.UpdatePeople(video, people);
Name = person.Name,
Type = person.Type,
Role = person.Role
});
}
}
}

private SubtitleOptions GetOptions()
{
return _config.GetConfiguration<SubtitleOptions>("subtitles");
_libraryManager.UpdatePeople(video, people);
}
}

/// <summary>
Expand All @@ -575,7 +549,7 @@ private async Task AddExternalSubtitlesAsync(
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;

var subtitleOptions = GetOptions();
var subtitleOptions = _config.GetConfiguration<SubtitleOptions>("subtitles");

var libraryOptions = _libraryManager.GetLibraryOptions(video);

Expand Down Expand Up @@ -659,9 +633,9 @@ private async Task AddExternalAudioAsync(
/// </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)
Expand All @@ -671,30 +645,30 @@ private ChapterInfo[] CreateDummyChapters(Video video)
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];
return Array.Empty<ChapterInfo>();
}

long currentChapterTicks = 0;
for (int i = 0; i < chapterCount; i++)
{
chapters[i] = new ChapterInfo
{
StartPositionTicks = currentChapterTicks
};
int chapterCount = (int)(runtime / dummyChapterDuration);
var chapters = new ChapterInfo[chapterCount];

currentChapterTicks += dummyChapterDuration;
}
long currentChapterTicks = 0;
for (int i = 0; i < chapterCount; i++)
{
chapters[i] = new ChapterInfo
{
StartPositionTicks = currentChapterTicks
};

return chapters;
currentChapterTicks += dummyChapterDuration;
}

return Array.Empty<ChapterInfo>();
return chapters;
}
}
}
8 changes: 6 additions & 2 deletions src/Jellyfin.Drawing/ImageProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
Expand Down Expand Up @@ -437,8 +436,13 @@ public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);

/// <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
{
Path = chapter.ImagePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AutoFixture" />
<PackageReference Include="AutoFixture.AutoMoq" />
<PackageReference Include="AutoFixture.Xunit2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="xunit" />
Expand Down
Loading

0 comments on commit d92e9ae

Please sign in to comment.