New: Add {MediaInfo VideoDynamicRangeType} token for renaming

This commit is contained in:
Alan Collins 2021-12-05 12:41:27 -06:00 committed by GitHub
parent 7f079ac8f2
commit 7b694ea71d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 202 additions and 19 deletions

View File

@ -17,8 +17,8 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
[TestCase(10, "BT.2020", "HLG", "", "", "HDR")]
[TestCase(10, "", "", "Dolby Vision", "", "HDR")]
[TestCase(10, "", "", "SMPTE ST 2086", "HDR10", "HDR")]
[TestCase(8, "", "", "Dolby Vision", "", "HDR")]
[TestCase(8, "", "", "SMPTE ST 2086", "HDR10", "HDR")]
[TestCase(8, "", "", "Dolby Vision", "", "")]
[TestCase(8, "", "", "SMPTE ST 2086", "HDR10", "")]
[TestCase(10, "BT.2020", "PQ", "Dolby Vision / SMPTE ST 2086", "Blu-ray / HDR10", "HDR")]
public void should_format_video_dynamic_range(int bitDepth, string colourPrimaries, string transferCharacteristics, string hdrFormat, string hdrFormatCompatibility, string expectedVideoDynamicRange)
{
@ -34,5 +34,37 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
MediaInfoFormatter.FormatVideoDynamicRange(mediaInfo).Should().Be(expectedVideoDynamicRange);
}
[TestCase(8, "", "", "", "")]
[TestCase(8, "BT.601 NTSC", "BT.709", "", "")]
[TestCase(8, "BT.2020", "PQ", "", "")]
[TestCase(8, "", "", "Dolby Vision", "")]
[TestCase(8, "", "", "SMPTE ST 2086", "")]
[TestCase(10, "BT.601 NTSC", "PQ", "", "")]
[TestCase(10, "BT.2020", "BT.709", "", "")]
[TestCase(10, "BT.2020", "PQ", "", "PQ")]
[TestCase(10, "BT.2020", "HLG", "", "HLG")]
[TestCase(10, "", "", "SMPTE ST 2086", "HDR10")]
[TestCase(10, "", "", "HDR10", "HDR10")]
[TestCase(10, "", "", "SMPTE ST 2094 App 4", "HDR10Plus")]
[TestCase(10, "", "", "Dolby Vision", "DV")]
[TestCase(10, "BT.2020", "PQ", "Dolby Vision / SMPTE ST 2086", "DV HDR10")]
[TestCase(10, "", "", "SL-HDR1", "HDR")]
[TestCase(10, "", "", "SL-HDR2", "HDR")]
[TestCase(10, "", "", "SL-HDR3", "HDR")]
[TestCase(10, "", "", "Technicolor Advanced HDR", "HDR")]
public void should_format_video_dynamic_range_type(int bitDepth, string colourPrimaries, string transferCharacteristics, string hdrFormat, string expectedVideoDynamicRange)
{
var mediaInfo = new MediaInfoModel
{
VideoBitDepth = bitDepth,
VideoColourPrimaries = colourPrimaries,
VideoTransferCharacteristics = transferCharacteristics,
VideoHdrFormat = hdrFormat,
SchemaRevision = 7
};
MediaInfoFormatter.FormatVideoDynamicRangeType(mediaInfo).Should().Be(expectedVideoDynamicRange);
}
}
}

View File

@ -0,0 +1,48 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Test.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
{
[TestFixture]
public class MediaInfoModelExtensionsFixture : TestBase
{
[TestCase(8, "", "", "", HdrFormat.None)]
[TestCase(8, "BT.601 NTSC", "BT.709", "", HdrFormat.None)]
[TestCase(8, "BT.2020", "PQ", "", HdrFormat.None)]
[TestCase(8, "", "", "Dolby Vision", HdrFormat.None)]
[TestCase(8, "", "", "SMPTE ST 2086", HdrFormat.None)]
[TestCase(10, "BT.601 NTSC", "PQ", "", HdrFormat.None)]
[TestCase(10, "BT.2020", "BT.709", "", HdrFormat.None)]
[TestCase(10, "BT.2020", "PQ", "", HdrFormat.Pq10)]
[TestCase(10, "BT.2020", "HLG", "", HdrFormat.Hlg10)]
[TestCase(10, "", "", "SMPTE ST 2086", HdrFormat.Hdr10)]
[TestCase(10, "", "", "HDR10", HdrFormat.Hdr10)]
[TestCase(10, "", "", "SMPTE ST 2094 App 4", HdrFormat.Hdr10Plus)]
[TestCase(10, "", "", "Dolby Vision", HdrFormat.DolbyVision)]
[TestCase(10, "BT.2020", "PQ", "Dolby Vision / SMPTE ST 2086", HdrFormat.DolbyVisionHdr10)]
[TestCase(10, "", "", "SL-HDR1", HdrFormat.UnknownHdr)]
[TestCase(10, "", "", "SL-HDR2", HdrFormat.UnknownHdr)]
[TestCase(10, "", "", "SL-HDR3", HdrFormat.UnknownHdr)]
[TestCase(10, "", "", "Technicolor Advanced HDR", HdrFormat.UnknownHdr)]
public void should_get_hdr_format(int bitDepth, string colourPrimaries, string transferCharacteristics, string hdrFormat, HdrFormat expectedVideoDynamicRange)
{
var mediaInfo = new MediaInfoModel
{
VideoBitDepth = bitDepth,
VideoColourPrimaries = colourPrimaries,
VideoTransferCharacteristics = transferCharacteristics,
VideoHdrFormat = hdrFormat,
SchemaRevision = 7
};
MediaInfoModelExtensions.GetHdrFormat(mediaInfo).Should().Be(expectedVideoDynamicRange);
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.MediaFiles.MediaInfo
{
public enum HdrFormat
{
None,
UnknownHdr,
Pq10,
Hdr10,
Hdr10Plus,
Hlg10,
DolbyVision,
DolbyVisionHdr10
}
}

View File

@ -585,26 +585,29 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return tokens.Last();
}
private static readonly string[] ValidHdrTransferFunctions = {"PQ", "HLG"};
private const string ValidHdrColourPrimaries = "BT.2020";
private const string VideoDynamicRangeHdr = "HDR";
public static string FormatVideoDynamicRange(MediaInfoModel mediaInfo)
{
if (mediaInfo.VideoHdrFormat.IsNotNullOrWhiteSpace())
{
return VideoDynamicRangeHdr;
}
return mediaInfo.GetHdrFormat() == HdrFormat.None ? "" : "HDR";
}
if (mediaInfo.VideoBitDepth >= 10 &&
mediaInfo.VideoColourPrimaries.IsNotNullOrWhiteSpace() &&
mediaInfo.VideoTransferCharacteristics.IsNotNullOrWhiteSpace())
public static string FormatVideoDynamicRangeType(MediaInfoModel mediaInfo)
{
switch(mediaInfo.GetHdrFormat())
{
if (mediaInfo.VideoColourPrimaries.EqualsIgnoreCase(ValidHdrColourPrimaries) &&
ValidHdrTransferFunctions.Any(mediaInfo.VideoTransferCharacteristics.Contains))
{
return VideoDynamicRangeHdr;
}
case HdrFormat.DolbyVision:
return "DV";
case HdrFormat.DolbyVisionHdr10:
return "DV HDR10";
case HdrFormat.Hdr10:
return "HDR10";
case HdrFormat.Hdr10Plus:
return "HDR10Plus";
case HdrFormat.Hlg10:
return "HLG";
case HdrFormat.Pq10:
return "PQ";
case HdrFormat.UnknownHdr:
return "HDR";
}
return "";

View File

@ -0,0 +1,76 @@
using NzbDrone.Common.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.MediaFiles.MediaInfo
{
public static class MediaInfoModelExtensions
{
private const string HlgTransferFunction = "HLG";
private const string PgTransferFunction = "PQ";
private const string ValidHdrColourPrimaries = "BT.2020";
private static readonly string[] Hdr10Formats = { "SMPTE ST 2086", "HDR10" };
private static readonly string[] Hdr10PlusFormats = { "SMPTE ST 2094 App 4" };
private static readonly string[] DolbyVisionFormats = { "Dolby Vision" };
public static HdrFormat GetHdrFormat(this MediaInfoModel mediaInfo)
{
if (mediaInfo.VideoBitDepth < 10)
{
return HdrFormat.None;
}
if (mediaInfo.VideoHdrFormat.IsNotNullOrWhiteSpace())
{
if(DolbyVisionFormats.Any(mediaInfo.VideoHdrFormat.ContainsIgnoreCase))
{
if(Hdr10Formats.Any(mediaInfo.VideoHdrFormat.ContainsIgnoreCase))
{
return HdrFormat.DolbyVisionHdr10;
}
else
{
return HdrFormat.DolbyVision;
}
}
else if(Hdr10Formats.Any(mediaInfo.VideoHdrFormat.ContainsIgnoreCase))
{
return HdrFormat.Hdr10;
}
else if(Hdr10PlusFormats.Any(mediaInfo.VideoHdrFormat.ContainsIgnoreCase))
{
return HdrFormat.Hdr10Plus;
}
}
//
// We didn't match straight from the format from MediaInfo, so try and match in ColourPrimaries and TransferCharacteristics
//
if (mediaInfo.VideoColourPrimaries.IsNotNullOrWhiteSpace() && mediaInfo.VideoTransferCharacteristics.IsNotNullOrWhiteSpace())
{
if (mediaInfo.VideoColourPrimaries.EqualsIgnoreCase(ValidHdrColourPrimaries))
{
if (mediaInfo.VideoTransferCharacteristics.EqualsIgnoreCase(PgTransferFunction))
{
return HdrFormat.Pq10;
}
else if (mediaInfo.VideoTransferCharacteristics.EqualsIgnoreCase(HlgTransferFunction))
{
return HdrFormat.Hlg10;
}
}
}
if (mediaInfo.VideoHdrFormat.IsNotNullOrWhiteSpace())
{
return HdrFormat.UnknownHdr; // MediaInfo reported Hdr information, but we're unsure of what type.
}
return HdrFormat.None;
}
}
}

View File

@ -603,10 +603,12 @@ namespace NzbDrone.Core.Organizer
}
private const string MediaInfoVideoDynamicRangeToken = "{MediaInfo VideoDynamicRange}";
private const string MediaInfoVideoDynamicRangeTypeToken = "{MediaInfo VideoDynamicRangeType}";
private static readonly IDictionary<string, int> MinimumMediaInfoSchemaRevisions =
new Dictionary<string, int>(FileNameBuilderTokenEqualityComparer.Instance)
{
{MediaInfoVideoDynamicRangeToken, 5}
{MediaInfoVideoDynamicRangeToken, 5},
{MediaInfoVideoDynamicRangeTypeToken, 5}
};
private void AddMediaInfoTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, EpisodeFile episodeFile)
@ -650,6 +652,8 @@ namespace NzbDrone.Core.Organizer
tokenHandlers[MediaInfoVideoDynamicRangeToken] =
m => MediaInfoFormatter.FormatVideoDynamicRange(episodeFile.MediaInfo);
tokenHandlers[MediaInfoVideoDynamicRangeTypeToken] =
m => MediaInfoFormatter.FormatVideoDynamicRangeType(episodeFile.MediaInfo);
}
private void AddIdTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Series series)