mirror of
https://github.com/jellyfin/jellyfin
synced 2024-10-14 19:54:01 +00:00
Merge pull request #7947 from nyanmisaka/video-range-condition
This commit is contained in:
commit
f1d56aa5ce
|
@ -221,6 +221,7 @@ namespace Emby.Dlna.Didl
|
||||||
streamInfo.IsDirectStream,
|
streamInfo.IsDirectStream,
|
||||||
streamInfo.RunTimeTicks ?? 0,
|
streamInfo.RunTimeTicks ?? 0,
|
||||||
streamInfo.TargetVideoProfile,
|
streamInfo.TargetVideoProfile,
|
||||||
|
streamInfo.TargetVideoRangeType,
|
||||||
streamInfo.TargetVideoLevel,
|
streamInfo.TargetVideoLevel,
|
||||||
streamInfo.TargetFramerate ?? 0,
|
streamInfo.TargetFramerate ?? 0,
|
||||||
streamInfo.TargetPacketLength,
|
streamInfo.TargetPacketLength,
|
||||||
|
@ -376,6 +377,7 @@ namespace Emby.Dlna.Didl
|
||||||
targetHeight,
|
targetHeight,
|
||||||
streamInfo.TargetVideoBitDepth,
|
streamInfo.TargetVideoBitDepth,
|
||||||
streamInfo.TargetVideoProfile,
|
streamInfo.TargetVideoProfile,
|
||||||
|
streamInfo.TargetVideoRangeType,
|
||||||
streamInfo.TargetVideoLevel,
|
streamInfo.TargetVideoLevel,
|
||||||
streamInfo.TargetFramerate ?? 0,
|
streamInfo.TargetFramerate ?? 0,
|
||||||
streamInfo.TargetPacketLength,
|
streamInfo.TargetPacketLength,
|
||||||
|
|
|
@ -561,6 +561,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
streamInfo.IsDirectStream,
|
streamInfo.IsDirectStream,
|
||||||
streamInfo.RunTimeTicks ?? 0,
|
streamInfo.RunTimeTicks ?? 0,
|
||||||
streamInfo.TargetVideoProfile,
|
streamInfo.TargetVideoProfile,
|
||||||
|
streamInfo.TargetVideoRangeType,
|
||||||
streamInfo.TargetVideoLevel,
|
streamInfo.TargetVideoLevel,
|
||||||
streamInfo.TargetFramerate ?? 0,
|
streamInfo.TargetFramerate ?? 0,
|
||||||
streamInfo.TargetPacketLength,
|
streamInfo.TargetPacketLength,
|
||||||
|
|
|
@ -312,7 +312,7 @@ namespace Jellyfin.Api.Helpers
|
||||||
|
|
||||||
responseHeaders.Add(
|
responseHeaders.Add(
|
||||||
"contentFeatures.dlna.org",
|
"contentFeatures.dlna.org",
|
||||||
ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty);
|
ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoRangeType, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,6 +533,7 @@ namespace Jellyfin.Api.Helpers
|
||||||
state.TargetVideoBitDepth,
|
state.TargetVideoBitDepth,
|
||||||
state.OutputVideoBitrate,
|
state.OutputVideoBitrate,
|
||||||
state.TargetVideoProfile,
|
state.TargetVideoProfile,
|
||||||
|
state.TargetVideoRangeType,
|
||||||
state.TargetVideoLevel,
|
state.TargetVideoLevel,
|
||||||
state.TargetFramerate,
|
state.TargetFramerate,
|
||||||
state.TargetPacketLength,
|
state.TargetPacketLength,
|
||||||
|
|
|
@ -75,6 +75,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <value>The profile.</value>
|
/// <value>The profile.</value>
|
||||||
public string Profile { get; set; }
|
public string Profile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the video range type.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The video range type.</value>
|
||||||
|
public string VideoRangeType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the level.
|
/// Gets or sets the level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1753,6 +1753,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var requestedRangeTypes = state.GetRequestedRangeTypes(videoStream.Codec);
|
||||||
|
if (requestedProfiles.Length > 0)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(videoStream.VideoRangeType))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestedRangeTypes.Contains(videoStream.VideoRangeType, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Video width must fall within requested value
|
// Video width must fall within requested value
|
||||||
if (request.MaxWidth.HasValue
|
if (request.MaxWidth.HasValue
|
||||||
&& (!videoStream.Width.HasValue || videoStream.Width.Value > request.MaxWidth.Value))
|
&& (!videoStream.Width.HasValue || videoStream.Width.Value > request.MaxWidth.Value))
|
||||||
|
|
|
@ -366,6 +366,28 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the target video range type.
|
||||||
|
/// </summary>
|
||||||
|
public string TargetVideoRangeType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (BaseRequest.Static || EncodingHelper.IsCopyCodec(OutputVideoCodec))
|
||||||
|
{
|
||||||
|
return VideoStream?.VideoRangeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestedRangeType = GetRequestedRangeTypes(ActualOutputVideoCodec).FirstOrDefault();
|
||||||
|
if (!string.IsNullOrEmpty(requestedRangeType))
|
||||||
|
{
|
||||||
|
return requestedRangeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string TargetVideoCodecTag
|
public string TargetVideoCodecTag
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -579,6 +601,26 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return Array.Empty<string>();
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string[] GetRequestedRangeTypes(string codec)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(BaseRequest.VideoRangeType))
|
||||||
|
{
|
||||||
|
return BaseRequest.VideoRangeType.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var rangetype = BaseRequest.GetOption(codec, "rangetype");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(rangetype))
|
||||||
|
{
|
||||||
|
return rangetype.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
public string GetRequestedLevel(string codec)
|
public string GetRequestedLevel(string codec)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(BaseRequest.Level))
|
if (!string.IsNullOrEmpty(BaseRequest.Level))
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? videoBitDepth,
|
int? videoBitDepth,
|
||||||
int? videoBitrate,
|
int? videoBitrate,
|
||||||
string? videoProfile,
|
string? videoProfile,
|
||||||
|
string? videoRangeType,
|
||||||
double? videoLevel,
|
double? videoLevel,
|
||||||
float? videoFramerate,
|
float? videoFramerate,
|
||||||
int? packetLength,
|
int? packetLength,
|
||||||
|
@ -42,6 +43,8 @@ namespace MediaBrowser.Model.Dlna
|
||||||
return IsConditionSatisfied(condition, videoLevel);
|
return IsConditionSatisfied(condition, videoLevel);
|
||||||
case ProfileConditionValue.VideoProfile:
|
case ProfileConditionValue.VideoProfile:
|
||||||
return IsConditionSatisfied(condition, videoProfile);
|
return IsConditionSatisfied(condition, videoProfile);
|
||||||
|
case ProfileConditionValue.VideoRangeType:
|
||||||
|
return IsConditionSatisfied(condition, videoRangeType);
|
||||||
case ProfileConditionValue.VideoCodecTag:
|
case ProfileConditionValue.VideoCodecTag:
|
||||||
return IsConditionSatisfied(condition, videoCodecTag);
|
return IsConditionSatisfied(condition, videoCodecTag);
|
||||||
case ProfileConditionValue.PacketLength:
|
case ProfileConditionValue.PacketLength:
|
||||||
|
|
|
@ -128,6 +128,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
bool isDirectStream,
|
bool isDirectStream,
|
||||||
long? runtimeTicks,
|
long? runtimeTicks,
|
||||||
string videoProfile,
|
string videoProfile,
|
||||||
|
string videoRangeType,
|
||||||
double? videoLevel,
|
double? videoLevel,
|
||||||
float? videoFramerate,
|
float? videoFramerate,
|
||||||
int? packetLength,
|
int? packetLength,
|
||||||
|
@ -176,6 +177,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
bitDepth,
|
bitDepth,
|
||||||
videoBitrate,
|
videoBitrate,
|
||||||
videoProfile,
|
videoProfile,
|
||||||
|
videoRangeType,
|
||||||
videoLevel,
|
videoLevel,
|
||||||
videoFramerate,
|
videoFramerate,
|
||||||
packetLength,
|
packetLength,
|
||||||
|
|
|
@ -423,6 +423,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
/// <param name="bitDepth">The bit depth.</param>
|
/// <param name="bitDepth">The bit depth.</param>
|
||||||
/// <param name="videoBitrate">The video bitrate.</param>
|
/// <param name="videoBitrate">The video bitrate.</param>
|
||||||
/// <param name="videoProfile">The video profile.</param>
|
/// <param name="videoProfile">The video profile.</param>
|
||||||
|
/// <param name="videoRangeType">The video range type.</param>
|
||||||
/// <param name="videoLevel">The video level.</param>
|
/// <param name="videoLevel">The video level.</param>
|
||||||
/// <param name="videoFramerate">The video framerate.</param>
|
/// <param name="videoFramerate">The video framerate.</param>
|
||||||
/// <param name="packetLength">The packet length.</param>
|
/// <param name="packetLength">The packet length.</param>
|
||||||
|
@ -444,6 +445,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? bitDepth,
|
int? bitDepth,
|
||||||
int? videoBitrate,
|
int? videoBitrate,
|
||||||
string videoProfile,
|
string videoProfile,
|
||||||
|
string videoRangeType,
|
||||||
double? videoLevel,
|
double? videoLevel,
|
||||||
float? videoFramerate,
|
float? videoFramerate,
|
||||||
int? packetLength,
|
int? packetLength,
|
||||||
|
@ -483,7 +485,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
var anyOff = false;
|
var anyOff = false;
|
||||||
foreach (ProfileCondition c in i.Conditions)
|
foreach (ProfileCondition c in i.Conditions)
|
||||||
{
|
{
|
||||||
if (!ConditionProcessor.IsVideoConditionSatisfied(GetModelProfileCondition(c), width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc))
|
if (!ConditionProcessor.IsVideoConditionSatisfied(GetModelProfileCondition(c), width, height, bitDepth, videoBitrate, videoProfile, videoRangeType, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc))
|
||||||
{
|
{
|
||||||
anyOff = true;
|
anyOff = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
IsAvc = 20,
|
IsAvc = 20,
|
||||||
IsInterlaced = 21,
|
IsInterlaced = 21,
|
||||||
AudioSampleRate = 22,
|
AudioSampleRate = 22,
|
||||||
AudioBitDepth = 23
|
AudioBitDepth = 23,
|
||||||
|
VideoRangeType = 24
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,6 +221,9 @@ namespace MediaBrowser.Model.Dlna
|
||||||
case ProfileConditionValue.VideoProfile:
|
case ProfileConditionValue.VideoProfile:
|
||||||
return TranscodeReason.VideoProfileNotSupported;
|
return TranscodeReason.VideoProfileNotSupported;
|
||||||
|
|
||||||
|
case ProfileConditionValue.VideoRangeType:
|
||||||
|
return TranscodeReason.VideoRangeTypeNotSupported;
|
||||||
|
|
||||||
case ProfileConditionValue.VideoTimestamp:
|
case ProfileConditionValue.VideoTimestamp:
|
||||||
// TODO
|
// TODO
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -748,9 +751,9 @@ namespace MediaBrowser.Model.Dlna
|
||||||
var appliedVideoConditions = options.Profile.CodecProfiles
|
var appliedVideoConditions = options.Profile.CodecProfiles
|
||||||
.Where(i => i.Type == CodecType.Video &&
|
.Where(i => i.Type == CodecType.Video &&
|
||||||
i.ContainsAnyCodec(videoCodec, container) &&
|
i.ContainsAnyCodec(videoCodec, container) &&
|
||||||
i.ApplyConditions.All(applyCondition => ConditionProcessor.IsVideoConditionSatisfied(applyCondition, videoStream?.Width, videoStream?.Height, videoStream?.BitDepth, videoStream?.BitRate, videoStream?.Profile, videoStream?.Level, videoFramerate, videoStream?.PacketLength, timestamp, videoStream?.IsAnamorphic, videoStream?.IsInterlaced, videoStream?.RefFrames, numVideoStreams, numAudioStreams, videoStream?.CodecTag, videoStream?.IsAVC)))
|
i.ApplyConditions.All(applyCondition => ConditionProcessor.IsVideoConditionSatisfied(applyCondition, videoStream?.Width, videoStream?.Height, videoStream?.BitDepth, videoStream?.BitRate, videoStream?.Profile, videoStream?.VideoRangeType, videoStream?.Level, videoFramerate, videoStream?.PacketLength, timestamp, videoStream?.IsAnamorphic, videoStream?.IsInterlaced, videoStream?.RefFrames, numVideoStreams, numAudioStreams, videoStream?.CodecTag, videoStream?.IsAVC)))
|
||||||
.Select(i =>
|
.Select(i =>
|
||||||
i.Conditions.All(condition => ConditionProcessor.IsVideoConditionSatisfied(condition, videoStream?.Width, videoStream?.Height, videoStream?.BitDepth, videoStream?.BitRate, videoStream?.Profile, videoStream?.Level, videoFramerate, videoStream?.PacketLength, timestamp, videoStream?.IsAnamorphic, videoStream?.IsInterlaced, videoStream?.RefFrames, numVideoStreams, numAudioStreams, videoStream?.CodecTag, videoStream?.IsAVC)));
|
i.Conditions.All(condition => ConditionProcessor.IsVideoConditionSatisfied(condition, videoStream?.Width, videoStream?.Height, videoStream?.BitDepth, videoStream?.BitRate, videoStream?.Profile, videoStream?.VideoRangeType, videoStream?.Level, videoFramerate, videoStream?.PacketLength, timestamp, videoStream?.IsAnamorphic, videoStream?.IsInterlaced, videoStream?.RefFrames, numVideoStreams, numAudioStreams, videoStream?.CodecTag, videoStream?.IsAVC)));
|
||||||
|
|
||||||
// An empty appliedVideoConditions means that the codec has no conditions for the current video stream
|
// An empty appliedVideoConditions means that the codec has no conditions for the current video stream
|
||||||
var conditionsSatisfied = appliedVideoConditions.All(satisfied => satisfied);
|
var conditionsSatisfied = appliedVideoConditions.All(satisfied => satisfied);
|
||||||
|
@ -834,6 +837,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? videoBitrate = videoStream?.BitRate;
|
int? videoBitrate = videoStream?.BitRate;
|
||||||
double? videoLevel = videoStream?.Level;
|
double? videoLevel = videoStream?.Level;
|
||||||
string videoProfile = videoStream?.Profile;
|
string videoProfile = videoStream?.Profile;
|
||||||
|
string videoRangeType = videoStream?.VideoRangeType;
|
||||||
float videoFramerate = videoStream == null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
float videoFramerate = videoStream == null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
||||||
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
||||||
bool? isInterlaced = videoStream?.IsInterlaced;
|
bool? isInterlaced = videoStream?.IsInterlaced;
|
||||||
|
@ -850,7 +854,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
var appliedVideoConditions = options.Profile.CodecProfiles
|
var appliedVideoConditions = options.Profile.CodecProfiles
|
||||||
.Where(i => i.Type == CodecType.Video &&
|
.Where(i => i.Type == CodecType.Video &&
|
||||||
i.ContainsAnyCodec(videoCodec, container) &&
|
i.ContainsAnyCodec(videoCodec, container) &&
|
||||||
i.ApplyConditions.All(applyCondition => ConditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)));
|
i.ApplyConditions.All(applyCondition => ConditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoRangeType, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)));
|
||||||
var isFirstAppliedCodecProfile = true;
|
var isFirstAppliedCodecProfile = true;
|
||||||
foreach (var i in appliedVideoConditions)
|
foreach (var i in appliedVideoConditions)
|
||||||
{
|
{
|
||||||
|
@ -1081,6 +1085,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? videoBitrate = videoStream?.BitRate;
|
int? videoBitrate = videoStream?.BitRate;
|
||||||
double? videoLevel = videoStream?.Level;
|
double? videoLevel = videoStream?.Level;
|
||||||
string videoProfile = videoStream?.Profile;
|
string videoProfile = videoStream?.Profile;
|
||||||
|
string videoRangeType = videoStream?.VideoRangeType;
|
||||||
float videoFramerate = videoStream == null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
float videoFramerate = videoStream == null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
||||||
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
||||||
bool? isInterlaced = videoStream?.IsInterlaced;
|
bool? isInterlaced = videoStream?.IsInterlaced;
|
||||||
|
@ -1098,7 +1103,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? numVideoStreams = mediaSource.GetStreamCount(MediaStreamType.Video);
|
int? numVideoStreams = mediaSource.GetStreamCount(MediaStreamType.Video);
|
||||||
|
|
||||||
var checkVideoConditions = (ProfileCondition[] conditions) =>
|
var checkVideoConditions = (ProfileCondition[] conditions) =>
|
||||||
conditions.Where(applyCondition => !ConditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc));
|
conditions.Where(applyCondition => !ConditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoRangeType, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc));
|
||||||
|
|
||||||
// Check container conditions
|
// Check container conditions
|
||||||
var containerProfileReasons = AggregateFailureConditions(
|
var containerProfileReasons = AggregateFailureConditions(
|
||||||
|
@ -1852,6 +1857,38 @@ namespace MediaBrowser.Model.Dlna
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ProfileConditionValue.VideoRangeType:
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(qualifier))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change from split by | to comma
|
||||||
|
// strip spaces to avoid having to encode
|
||||||
|
var values = value
|
||||||
|
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
|
||||||
|
if (condition.Condition == ProfileConditionType.Equals)
|
||||||
|
{
|
||||||
|
item.SetOption(qualifier, "rangetype", string.Join(',', values));
|
||||||
|
}
|
||||||
|
else if (condition.Condition == ProfileConditionType.EqualsAny)
|
||||||
|
{
|
||||||
|
var currentValue = item.GetOption(qualifier, "rangetype");
|
||||||
|
if (!string.IsNullOrEmpty(currentValue) && values.Any(v => string.Equals(v, currentValue, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
item.SetOption(qualifier, "rangetype", currentValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.SetOption(qualifier, "rangetype", string.Join(',', values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ProfileConditionValue.Height:
|
case ProfileConditionValue.Height:
|
||||||
{
|
{
|
||||||
if (!enableNonQualifiedConditions)
|
if (!enableNonQualifiedConditions)
|
||||||
|
|
|
@ -280,6 +280,29 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the target video range type that will be in the output stream.
|
||||||
|
/// </summary>
|
||||||
|
public string TargetVideoRangeType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsDirectStream)
|
||||||
|
{
|
||||||
|
return TargetVideoStream?.VideoRangeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetVideoCodecs = TargetVideoCodec;
|
||||||
|
var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0];
|
||||||
|
if (!string.IsNullOrEmpty(videoCodec))
|
||||||
|
{
|
||||||
|
return GetOption(videoCodec, "rangetype");
|
||||||
|
}
|
||||||
|
|
||||||
|
return TargetVideoStream?.VideoRangeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the target video codec tag.
|
/// Gets the target video codec tag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -104,32 +104,23 @@ namespace MediaBrowser.Model.Entities
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Type != MediaStreamType.Video)
|
var (videoRange, _) = GetVideoColorRange();
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var colorTransfer = ColorTransfer;
|
return videoRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase)
|
/// <summary>
|
||||||
|| string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase))
|
/// Gets the video range type.
|
||||||
{
|
/// </summary>
|
||||||
return "HDR";
|
/// <value>The video range type.</value>
|
||||||
}
|
public string VideoRangeType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var (_, videoRangeType) = GetVideoColorRange();
|
||||||
|
|
||||||
// For some Dolby Vision files, no color transfer is provided, so check the codec
|
return videoRangeType;
|
||||||
|
|
||||||
var codecTag = CodecTag;
|
|
||||||
|
|
||||||
if (string.Equals(codecTag, "dovi", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(codecTag, "dvh1", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(codecTag, "dvhe", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(codecTag, "dav1", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return "HDR";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "SDR";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,5 +562,39 @@ namespace MediaBrowser.Model.Entities
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (string VideoRange, string VideoRangeType) GetVideoColorRange()
|
||||||
|
{
|
||||||
|
if (Type != MediaStreamType.Video)
|
||||||
|
{
|
||||||
|
return (null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var colorTransfer = ColorTransfer;
|
||||||
|
|
||||||
|
if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return ("HDR", "HDR10");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return ("HDR", "HLG");
|
||||||
|
}
|
||||||
|
|
||||||
|
// For some Dolby Vision files, no color transfer is provided, so check the codec
|
||||||
|
|
||||||
|
var codecTag = CodecTag;
|
||||||
|
|
||||||
|
if (string.Equals(codecTag, "dovi", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(codecTag, "dvh1", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(codecTag, "dvhe", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(codecTag, "dav1", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return ("HDR", "DOVI");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ("SDR", "SDR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace MediaBrowser.Model.Session
|
||||||
|
|
||||||
// Video Constraints
|
// Video Constraints
|
||||||
VideoProfileNotSupported = 1 << 6,
|
VideoProfileNotSupported = 1 << 6,
|
||||||
|
VideoRangeTypeNotSupported = 1 << 24,
|
||||||
VideoLevelNotSupported = 1 << 7,
|
VideoLevelNotSupported = 1 << 7,
|
||||||
VideoResolutionNotSupported = 1 << 8,
|
VideoResolutionNotSupported = 1 << 8,
|
||||||
VideoBitDepthNotSupported = 1 << 9,
|
VideoBitDepthNotSupported = 1 << 9,
|
||||||
|
|
Loading…
Reference in a new issue