Merge pull request #17806 from jellyfin/fix/dovi-color-validation
Enforce dolby vision transfer check
This commit is contained in:
@@ -458,6 +458,7 @@ public class DynamicHlsHelper
|
||||
{
|
||||
case VideoRangeType.HLG:
|
||||
case VideoRangeType.DOVIWithHLG:
|
||||
case VideoRangeType.DOVIInvalid when string.Equals(state.VideoStream.ColorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase):
|
||||
builder.Append(",VIDEO-RANGE=HLG");
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -61,8 +61,9 @@ public enum VideoRangeType
|
||||
DOVIWithELHDR10Plus,
|
||||
|
||||
/// <summary>
|
||||
/// Dolby Vision with invalid configuration. e.g. Profile 8 compat id 6.
|
||||
/// When using this range, the server would assume the video is still HDR10 after removing the Dolby Vision metadata.
|
||||
/// Dolby Vision with invalid configuration, e.g. Profile 8 compat id 6 or inconsistent base-layer color metadata.
|
||||
/// The base layer is classified as HDR only when its transfer characteristics signal PQ or HLG.
|
||||
/// Otherwise, it is classified as SDR.
|
||||
/// </summary>
|
||||
DOVIInvalid,
|
||||
|
||||
|
||||
@@ -442,7 +442,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
&& (state.VideoStream.VideoRangeType == VideoRangeType.HDR10
|
||||
|| IsHdr10Plus(state.VideoStream)
|
||||
|| IsDoviWithHdr10Bl(state.VideoStream)
|
||||
|| state.VideoStream.VideoRangeType == VideoRangeType.HLG);
|
||||
|| state.VideoStream.VideoRangeType == VideoRangeType.HLG
|
||||
|| state.VideoStream.VideoRangeType == VideoRangeType.DOVIInvalid);
|
||||
}
|
||||
|
||||
private static bool IsDeinterlaceAvailable(EncodingJobInfo state)
|
||||
@@ -1390,7 +1391,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
or VideoRangeType.DOVIWithEL
|
||||
or VideoRangeType.DOVIWithHDR10Plus
|
||||
or VideoRangeType.DOVIWithELHDR10Plus
|
||||
or VideoRangeType.DOVIInvalid;
|
||||
|| (rangeType == VideoRangeType.DOVIInvalid
|
||||
&& string.Equals(stream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase)); // invalid may be hlg now
|
||||
}
|
||||
|
||||
public static bool IsDovi(MediaStream stream)
|
||||
@@ -1400,7 +1402,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return IsDoviWithHdr10Bl(stream)
|
||||
|| (rangeType is VideoRangeType.DOVI
|
||||
or VideoRangeType.DOVIWithHLG
|
||||
or VideoRangeType.DOVIWithSDR);
|
||||
or VideoRangeType.DOVIWithSDR
|
||||
or VideoRangeType.DOVIInvalid);
|
||||
}
|
||||
|
||||
public static bool IsHdr10Plus(MediaStream stream)
|
||||
@@ -1420,7 +1423,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
private static DynamicHdrMetadataRemovalPlan ShouldRemoveDynamicHdrMetadata(EncodingJobInfo state)
|
||||
{
|
||||
var videoStream = state.VideoStream;
|
||||
if (videoStream.VideoRange is not VideoRange.HDR)
|
||||
if (videoStream.VideoRange is not VideoRange.HDR
|
||||
&& videoStream.VideoRangeType != VideoRangeType.DOVIInvalid)
|
||||
{
|
||||
return DynamicHdrMetadataRemovalPlan.None;
|
||||
}
|
||||
|
||||
@@ -810,6 +810,11 @@ namespace MediaBrowser.Model.Entities
|
||||
return (VideoRange.Unknown, VideoRangeType.Unknown);
|
||||
}
|
||||
|
||||
var isPq = string.Equals(ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase);
|
||||
var isHlg = string.Equals(ColorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase);
|
||||
// Invalid DV only retains HDR when the base layer explicitly signals PQ or HLG.
|
||||
var baseVideoRange = isPq || isHlg ? VideoRange.HDR : VideoRange.SDR;
|
||||
|
||||
var codecTag = CodecTag;
|
||||
var dvProfile = DvProfile;
|
||||
var rpuPresentFlag = RpuPresentFlag == 1;
|
||||
@@ -834,7 +839,7 @@ namespace MediaBrowser.Model.Entities
|
||||
4 => (VideoRange.HDR, VideoRangeType.DOVIWithHLG),
|
||||
2 => (VideoRange.SDR, VideoRangeType.DOVIWithSDR),
|
||||
// Out of Dolby Spec files should be marked as invalid
|
||||
_ => (VideoRange.HDR, VideoRangeType.DOVIInvalid)
|
||||
_ => (baseVideoRange, VideoRangeType.DOVIInvalid)
|
||||
},
|
||||
7 => (VideoRange.HDR, VideoRangeType.DOVIWithEL),
|
||||
10 => dvBlCompatId switch
|
||||
@@ -844,11 +849,26 @@ namespace MediaBrowser.Model.Entities
|
||||
2 => (VideoRange.SDR, VideoRangeType.DOVIWithSDR),
|
||||
4 => (VideoRange.HDR, VideoRangeType.DOVIWithHLG),
|
||||
// Out of Dolby Spec files should be marked as invalid
|
||||
_ => (VideoRange.HDR, VideoRangeType.DOVIInvalid)
|
||||
_ => (baseVideoRange, VideoRangeType.DOVIInvalid)
|
||||
},
|
||||
_ => (VideoRange.SDR, VideoRangeType.SDR)
|
||||
};
|
||||
|
||||
var expectedTransfer = dvRangeSet.Item2 switch
|
||||
{
|
||||
VideoRangeType.DOVIWithHDR10 or VideoRangeType.DOVIWithEL => "smpte2084",
|
||||
VideoRangeType.DOVIWithHLG => "arib-std-b67",
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (expectedTransfer is not null
|
||||
&& (!string.Equals(ColorSpace, "bt2020nc", StringComparison.OrdinalIgnoreCase)
|
||||
|| !string.Equals(ColorTransfer, expectedTransfer, StringComparison.OrdinalIgnoreCase)
|
||||
|| !string.Equals(ColorPrimaries, "bt2020", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return (baseVideoRange, VideoRangeType.DOVIInvalid);
|
||||
}
|
||||
|
||||
if (Hdr10PlusPresentFlag == true)
|
||||
{
|
||||
return dvRangeSet.Item2 switch
|
||||
@@ -862,13 +882,11 @@ namespace MediaBrowser.Model.Entities
|
||||
return dvRangeSet;
|
||||
}
|
||||
|
||||
var colorTransfer = ColorTransfer;
|
||||
|
||||
if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase))
|
||||
if (isPq)
|
||||
{
|
||||
return Hdr10PlusPresentFlag == true ? (VideoRange.HDR, VideoRangeType.HDR10Plus) : (VideoRange.HDR, VideoRangeType.HDR10);
|
||||
}
|
||||
else if (string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase))
|
||||
else if (isHlg)
|
||||
{
|
||||
return (VideoRange.HDR, VideoRangeType.HLG);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Controller.Streaming;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration;
|
||||
|
||||
namespace Jellyfin.Controller.Tests.MediaEncoding;
|
||||
|
||||
public class EncodingHelperDoviTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null, false)]
|
||||
[InlineData("bt709", false)]
|
||||
[InlineData("unknown", false)]
|
||||
[InlineData("bt2020-10", false)]
|
||||
[InlineData("smpte2084", true)]
|
||||
[InlineData("arib-std-b67", true)]
|
||||
public void GetSwVidFilterChain_InvalidDovi_OnlyTonemapsHdrBaseLayer(string? transfer, bool tonemap)
|
||||
{
|
||||
var state = CreateState("hevc", transfer);
|
||||
var helper = CreateHelper(true);
|
||||
|
||||
var (filters, _, _) = helper.GetSwVidFilterChain(state, new EncodingOptions(), "libx264");
|
||||
var args = string.Join(',', filters);
|
||||
|
||||
Assert.Equal(VideoRangeType.DOVIInvalid, state.VideoStream.VideoRangeType);
|
||||
Assert.Equal(tonemap, args.Contains("tonemapx=", StringComparison.Ordinal));
|
||||
Assert.Contains(tonemap ? "color_trc=" + transfer : "color_trc=bt709", args, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, false)]
|
||||
[InlineData("bt709", false)]
|
||||
[InlineData("arib-std-b67", false)]
|
||||
[InlineData("smpte2084", true)]
|
||||
[InlineData("SMPTE2084", true)]
|
||||
public void IsDoviWithHdr10Bl_InvalidDovi_RequiresPq(string? transfer, bool expected)
|
||||
{
|
||||
var stream = CreateState("hevc", transfer).VideoStream;
|
||||
|
||||
Assert.True(EncodingHelper.IsDovi(stream));
|
||||
Assert.Equal(expected, EncodingHelper.IsDoviWithHdr10Bl(stream));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hevc", null, "hevc_metadata=remove_dovi=1")]
|
||||
[InlineData("hevc", "bt709", "hevc_metadata=remove_dovi=1")]
|
||||
[InlineData("hevc", "smpte2084", "hevc_metadata=remove_dovi=1")]
|
||||
[InlineData("hevc", "arib-std-b67", "hevc_metadata=remove_dovi=1")]
|
||||
[InlineData("av1", null, "av1_metadata=remove_dovi=1")]
|
||||
[InlineData("av1", "bt709", "av1_metadata=remove_dovi=1")]
|
||||
[InlineData("av1", "smpte2084", "av1_metadata=remove_dovi=1")]
|
||||
[InlineData("av1", "arib-std-b67", "av1_metadata=remove_dovi=1")]
|
||||
public void GetBitStreamArgs_InvalidDovi_PreservesClientDependentRemoval(string codec, string? transfer, string expected)
|
||||
{
|
||||
var state = CreateState(codec, transfer);
|
||||
var helper = CreateHelper(true);
|
||||
|
||||
foreach (var (requestedRanges, removeDovi) in new[] { (null, false), ("SDR", false), ("HDR10", false), ("DOVIWithEL", false), ("DOVI", true), ("SDR,DOVI", true) })
|
||||
{
|
||||
state.BaseRequest.VideoRangeType = requestedRanges;
|
||||
|
||||
Assert.Equal(removeDovi, helper.IsDoviRemoved(state));
|
||||
if (removeDovi)
|
||||
{
|
||||
Assert.Contains(expected, helper.GetBitStreamArgs(state, MediaStreamType.Video), StringComparison.Ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(codec == "hevc" ? "-bsf:v hevc_mp4toannexb" : null, helper.GetBitStreamArgs(state, MediaStreamType.Video));
|
||||
}
|
||||
|
||||
Assert.False(CreateHelper(false).IsDoviRemoved(state));
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, true)]
|
||||
[InlineData("HDR10", true)]
|
||||
[InlineData("DOVI", false)]
|
||||
[InlineData("SDR,DOVI", false)]
|
||||
public void CanStreamCopyVideo_InvalidDovi_RequiresRemovalSupportOnlyForDoviClients(string? requestedRanges, bool copyWithoutRemovalSupport)
|
||||
{
|
||||
foreach (var codec in new[] { "hevc", "av1" })
|
||||
{
|
||||
foreach (var transfer in new[] { "bt709", "smpte2084" })
|
||||
{
|
||||
var state = CreateState(codec, transfer);
|
||||
state.BaseRequest.VideoRangeType = requestedRanges;
|
||||
|
||||
Assert.True(CreateHelper(true).CanStreamCopyVideo(state, state.VideoStream));
|
||||
Assert.Equal(copyWithoutRemovalSupport, CreateHelper(false).CanStreamCopyVideo(state, state.VideoStream));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBitStreamArgs_ValidDovi_PreservesMetadata()
|
||||
{
|
||||
var state = CreateState("hevc", "smpte2084");
|
||||
state.VideoStream.ColorSpace = "bt2020nc";
|
||||
state.VideoStream.ColorPrimaries = "bt2020";
|
||||
state.BaseRequest.VideoRangeType = "DOVIWithEL";
|
||||
var helper = CreateHelper(true);
|
||||
|
||||
Assert.False(helper.IsDoviRemoved(state));
|
||||
Assert.Equal("-bsf:v hevc_mp4toannexb", helper.GetBitStreamArgs(state, MediaStreamType.Video));
|
||||
}
|
||||
|
||||
private static EncodingJobInfo CreateState(string codec, string? transfer)
|
||||
{
|
||||
var stream = new MediaStream
|
||||
{
|
||||
Type = MediaStreamType.Video,
|
||||
Codec = codec,
|
||||
Width = 1920,
|
||||
Height = 1080,
|
||||
BitDepth = 10,
|
||||
DvProfile = codec == "hevc" ? 7 : 10,
|
||||
DvBlSignalCompatibilityId = codec == "hevc" ? 6 : 1,
|
||||
RpuPresentFlag = 1,
|
||||
BlPresentFlag = 1,
|
||||
ColorSpace = "bt709",
|
||||
ColorPrimaries = "bt709",
|
||||
ColorTransfer = transfer
|
||||
};
|
||||
|
||||
return new EncodingJobInfo(TranscodingJobType.Hls)
|
||||
{
|
||||
VideoStream = stream,
|
||||
MediaSource = new MediaSourceInfo { Container = "mkv", MediaStreams = [stream] },
|
||||
BaseRequest = new VideoRequestDto(),
|
||||
OutputVideoCodec = "copy",
|
||||
IsVideoRequest = true,
|
||||
IsInputVideo = true
|
||||
};
|
||||
}
|
||||
|
||||
private static EncodingHelper CreateHelper(bool supportsRemoval)
|
||||
{
|
||||
var encoder = new Mock<IMediaEncoder>();
|
||||
encoder.Setup(x => x.SupportsBitStreamFilterWithOption(It.IsAny<BitStreamFilterOptionType>())).Returns(supportsRemoval);
|
||||
encoder.Setup(x => x.SupportsFilter("tonemapx")).Returns(true);
|
||||
encoder.SetupGet(x => x.EncoderVersion).Returns(new Version(8, 1));
|
||||
|
||||
return new EncodingHelper(
|
||||
Mock.Of<IApplicationPaths>(),
|
||||
encoder.Object,
|
||||
Mock.Of<ISubtitleEncoder>(),
|
||||
Mock.Of<IConfiguration>(),
|
||||
Mock.Of<IConfigurationManager>(),
|
||||
Mock.Of<IPathManager>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Model.Tests.Entities;
|
||||
|
||||
public class MediaStreamVideoRangeTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(7, 6, "smpte2084", false, VideoRangeType.DOVIWithEL)]
|
||||
[InlineData(7, 6, "smpte2084", true, VideoRangeType.DOVIWithELHDR10Plus)]
|
||||
[InlineData(8, 1, "smpte2084", false, VideoRangeType.DOVIWithHDR10)]
|
||||
[InlineData(8, 1, "smpte2084", true, VideoRangeType.DOVIWithHDR10Plus)]
|
||||
[InlineData(8, 4, "arib-std-b67", false, VideoRangeType.DOVIWithHLG)]
|
||||
[InlineData(10, 1, "smpte2084", false, VideoRangeType.DOVIWithHDR10)]
|
||||
[InlineData(10, 1, "smpte2084", true, VideoRangeType.DOVIWithHDR10Plus)]
|
||||
[InlineData(10, 4, "arib-std-b67", false, VideoRangeType.DOVIWithHLG)]
|
||||
[InlineData(8, 1, "SMPTE2084", false, VideoRangeType.DOVIWithHDR10)]
|
||||
[InlineData(8, 4, "ARIB-STD-B67", false, VideoRangeType.DOVIWithHLG)]
|
||||
public void GetVideoColorRange_ValidDovi_PreservesRangeType(
|
||||
int profile, int compatibilityId, string transfer, bool hdr10Plus, VideoRangeType expected)
|
||||
{
|
||||
var stream = CreateDovi(profile, compatibilityId, "BT2020NC", transfer, "BT2020", hdr10Plus);
|
||||
|
||||
Assert.Equal((VideoRange.HDR, expected), stream.GetVideoColorRange());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("bt709", "bt709", "bt709", VideoRange.SDR)]
|
||||
[InlineData("bt2020nc", "bt709", "bt2020", VideoRange.SDR)]
|
||||
[InlineData("bt2020nc", null, "bt2020", VideoRange.SDR)]
|
||||
[InlineData("bt2020nc", "", "bt2020", VideoRange.SDR)]
|
||||
[InlineData("bt2020nc", "unknown", "bt2020", VideoRange.SDR)]
|
||||
[InlineData("bt2020nc", "bt2020-10", "bt2020", VideoRange.SDR)]
|
||||
[InlineData(null, null, null, VideoRange.SDR)]
|
||||
[InlineData("bt709", "smpte2084", "bt2020", VideoRange.HDR)]
|
||||
[InlineData("bt2020nc", "smpte2084", "bt709", VideoRange.HDR)]
|
||||
[InlineData(null, "smpte2084", "bt2020", VideoRange.HDR)]
|
||||
[InlineData("bt2020nc", "smpte2084", null, VideoRange.HDR)]
|
||||
[InlineData("bt709", "arib-std-b67", "bt2020", VideoRange.HDR)]
|
||||
[InlineData("bt2020nc", "arib-std-b67", "bt709", VideoRange.HDR)]
|
||||
[InlineData(null, "arib-std-b67", "bt2020", VideoRange.HDR)]
|
||||
[InlineData("bt2020nc", "arib-std-b67", null, VideoRange.HDR)]
|
||||
public void GetVideoColorRange_InvalidDoviColors_UsesBaseLayerRange(
|
||||
string? space, string? transfer, string? primaries, VideoRange expected)
|
||||
{
|
||||
// Cover every HDR-compatible DV profile, including the HDR10+ variants.
|
||||
foreach (var (profile, compatibilityId) in new[] { (7, 6), (8, 1), (8, 4), (10, 1), (10, 4) })
|
||||
{
|
||||
foreach (var hdr10Plus in new[] { false, true })
|
||||
{
|
||||
var stream = CreateDovi(profile, compatibilityId, space, transfer, primaries, hdr10Plus);
|
||||
|
||||
Assert.Equal(expected, stream.VideoRange);
|
||||
Assert.Equal(VideoRangeType.DOVIInvalid, stream.VideoRangeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(7, 6, "arib-std-b67")]
|
||||
[InlineData(8, 1, "arib-std-b67")]
|
||||
[InlineData(8, 4, "smpte2084")]
|
||||
[InlineData(10, 1, "arib-std-b67")]
|
||||
[InlineData(10, 4, "smpte2084")]
|
||||
public void GetVideoColorRange_WrongHdrTransfer_InvalidButStillHdr(int profile, int compatibilityId, string transfer)
|
||||
{
|
||||
var stream = CreateDovi(profile, compatibilityId, "bt2020nc", transfer, "bt2020", true);
|
||||
|
||||
Assert.Equal((VideoRange.HDR, VideoRangeType.DOVIInvalid), stream.GetVideoColorRange());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(5, 0, null, VideoRange.HDR, VideoRangeType.DOVI)]
|
||||
[InlineData(10, 0, null, VideoRange.HDR, VideoRangeType.DOVI)]
|
||||
[InlineData(8, 2, "bt709", VideoRange.SDR, VideoRangeType.DOVIWithSDR)]
|
||||
[InlineData(10, 2, "bt709", VideoRange.SDR, VideoRangeType.DOVIWithSDR)]
|
||||
public void GetVideoColorRange_OtherDoviProfiles_PreservesClassification(
|
||||
int profile, int compatibilityId, string? transfer, VideoRange range, VideoRangeType rangeType)
|
||||
{
|
||||
var stream = CreateDovi(profile, compatibilityId, "bt709", transfer, "bt709", false);
|
||||
|
||||
Assert.Equal((range, rangeType), stream.GetVideoColorRange());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(8, null, VideoRange.SDR)]
|
||||
[InlineData(8, "bt709", VideoRange.SDR)]
|
||||
[InlineData(8, "smpte2084", VideoRange.HDR)]
|
||||
[InlineData(10, null, VideoRange.SDR)]
|
||||
[InlineData(10, "arib-std-b67", VideoRange.HDR)]
|
||||
public void GetVideoColorRange_InvalidCompatibilityId_UsesBaseLayerRange(int profile, string? transfer, VideoRange expected)
|
||||
{
|
||||
var stream = CreateDovi(profile, 6, "bt2020nc", transfer, "bt2020", false);
|
||||
|
||||
Assert.Equal((expected, VideoRangeType.DOVIInvalid), stream.GetVideoColorRange());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("bt709", false, VideoRange.SDR, VideoRangeType.SDR)]
|
||||
[InlineData(null, false, VideoRange.SDR, VideoRangeType.SDR)]
|
||||
[InlineData("smpte2084", false, VideoRange.HDR, VideoRangeType.HDR10)]
|
||||
[InlineData("smpte2084", true, VideoRange.HDR, VideoRangeType.HDR10Plus)]
|
||||
[InlineData("arib-std-b67", false, VideoRange.HDR, VideoRangeType.HLG)]
|
||||
public void GetVideoColorRange_WithoutDovi_PreservesClassification(
|
||||
string? transfer, bool hdr10Plus, VideoRange range, VideoRangeType rangeType)
|
||||
{
|
||||
var stream = new MediaStream { Type = MediaStreamType.Video, ColorTransfer = transfer, Hdr10PlusPresentFlag = hdr10Plus };
|
||||
|
||||
Assert.Equal((range, rangeType), stream.GetVideoColorRange());
|
||||
stream.Type = MediaStreamType.Audio;
|
||||
Assert.Equal((VideoRange.Unknown, VideoRangeType.Unknown), stream.GetVideoColorRange());
|
||||
}
|
||||
|
||||
private static MediaStream CreateDovi(int profile, int compatibilityId, string? space, string? transfer, string? primaries, bool hdr10Plus)
|
||||
=> new()
|
||||
{
|
||||
Type = MediaStreamType.Video,
|
||||
DvProfile = profile,
|
||||
DvBlSignalCompatibilityId = compatibilityId,
|
||||
RpuPresentFlag = 1,
|
||||
BlPresentFlag = 1,
|
||||
ElPresentFlag = profile == 7 ? 1 : 0,
|
||||
ColorSpace = space,
|
||||
ColorTransfer = transfer,
|
||||
ColorPrimaries = primaries,
|
||||
Hdr10PlusPresentFlag = hdr10Plus
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user