mirror of https://github.com/jellyfin/jellyfin.git
Migrate VideoRange and VideoRangeType to Enum
This commit is contained in:
parent
d874262bf9
commit
20a4509991
|
@ -12,6 +12,7 @@ using Jellyfin.Api.Attributes;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
using Jellyfin.Api.Models.PlaybackDtos;
|
using Jellyfin.Api.Models.PlaybackDtos;
|
||||||
using Jellyfin.Api.Models.StreamingDtos;
|
using Jellyfin.Api.Models.StreamingDtos;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using Jellyfin.MediaEncoding.Hls.Playlist;
|
using Jellyfin.MediaEncoding.Hls.Playlist;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
@ -1809,7 +1810,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||||
|| string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
|
|| string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (EncodingHelper.IsCopyCodec(codec)
|
if (EncodingHelper.IsCopyCodec(codec)
|
||||||
&& (string.Equals(state.VideoStream.VideoRangeType, "DOVI", StringComparison.OrdinalIgnoreCase)
|
&& (state.VideoStream.VideoRangeType == VideoRangeType.DOVI
|
||||||
|| string.Equals(state.VideoStream.CodecTag, "dovi", StringComparison.OrdinalIgnoreCase)
|
|| string.Equals(state.VideoStream.CodecTag, "dovi", StringComparison.OrdinalIgnoreCase)
|
||||||
|| string.Equals(state.VideoStream.CodecTag, "dvh1", StringComparison.OrdinalIgnoreCase)
|
|| string.Equals(state.VideoStream.CodecTag, "dvh1", StringComparison.OrdinalIgnoreCase)
|
||||||
|| string.Equals(state.VideoStream.CodecTag, "dvhe", StringComparison.OrdinalIgnoreCase)))
|
|| string.Equals(state.VideoStream.CodecTag, "dvhe", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Models.StreamingDtos;
|
using Jellyfin.Api.Models.StreamingDtos;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
@ -211,8 +212,7 @@ public class DynamicHlsHelper
|
||||||
// Provide SDR HEVC entrance for backward compatibility.
|
// Provide SDR HEVC entrance for backward compatibility.
|
||||||
if (encodingOptions.AllowHevcEncoding
|
if (encodingOptions.AllowHevcEncoding
|
||||||
&& EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
|
&& EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
|
||||||
&& !string.IsNullOrEmpty(state.VideoStream.VideoRange)
|
&& state.VideoStream.VideoRange == VideoRange.HDR
|
||||||
&& string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase)
|
|
||||||
&& string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
|
&& string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var requestedVideoProfiles = state.GetRequestedProfiles("hevc");
|
var requestedVideoProfiles = state.GetRequestedProfiles("hevc");
|
||||||
|
@ -255,8 +255,7 @@ public class DynamicHlsHelper
|
||||||
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
|
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
|
||||||
&& state.VideoStream.Level.HasValue
|
&& state.VideoStream.Level.HasValue
|
||||||
&& state.VideoStream.Level > 150
|
&& state.VideoStream.Level > 150
|
||||||
&& !string.IsNullOrEmpty(state.VideoStream.VideoRange)
|
&& state.VideoStream.VideoRange == VideoRange.SDR
|
||||||
&& string.Equals(state.VideoStream.VideoRange, "SDR", StringComparison.OrdinalIgnoreCase)
|
|
||||||
&& string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
|
&& string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var playlistCodecsField = new StringBuilder();
|
var playlistCodecsField = new StringBuilder();
|
||||||
|
@ -340,17 +339,17 @@ public class DynamicHlsHelper
|
||||||
/// <param name="state">StreamState of the current stream.</param>
|
/// <param name="state">StreamState of the current stream.</param>
|
||||||
private void AppendPlaylistVideoRangeField(StringBuilder builder, StreamState state)
|
private void AppendPlaylistVideoRangeField(StringBuilder builder, StreamState state)
|
||||||
{
|
{
|
||||||
if (state.VideoStream is not null && !string.IsNullOrEmpty(state.VideoStream.VideoRange))
|
if (state.VideoStream is not null && state.VideoStream.VideoRange != VideoRange.Unknown)
|
||||||
{
|
{
|
||||||
var videoRange = state.VideoStream.VideoRange;
|
var videoRange = state.VideoStream.VideoRange;
|
||||||
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
|
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
|
||||||
{
|
{
|
||||||
if (string.Equals(videoRange, "SDR", StringComparison.OrdinalIgnoreCase))
|
if (videoRange == VideoRange.SDR)
|
||||||
{
|
{
|
||||||
builder.Append(",VIDEO-RANGE=SDR");
|
builder.Append(",VIDEO-RANGE=SDR");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(videoRange, "HDR", StringComparison.OrdinalIgnoreCase))
|
if (videoRange == VideoRange.HDR)
|
||||||
{
|
{
|
||||||
builder.Append(",VIDEO-RANGE=PQ");
|
builder.Append(",VIDEO-RANGE=PQ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
namespace Jellyfin.Data.Enums;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An enum representing video ranges.
|
||||||
|
/// </summary>
|
||||||
|
public enum VideoRange
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unknown video range.
|
||||||
|
/// </summary>
|
||||||
|
Unknown,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SDR video range.
|
||||||
|
/// </summary>
|
||||||
|
SDR,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HDR video range.
|
||||||
|
/// </summary>
|
||||||
|
HDR
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
namespace Jellyfin.Data.Enums;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An enum representing types of video ranges.
|
||||||
|
/// </summary>
|
||||||
|
public enum VideoRangeType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unknown video range type.
|
||||||
|
/// </summary>
|
||||||
|
Unknown,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SDR video range type (8bit).
|
||||||
|
/// </summary>
|
||||||
|
SDR,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HDR10 video range type (10bit).
|
||||||
|
/// </summary>
|
||||||
|
HDR10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HLG video range type (10bit).
|
||||||
|
/// </summary>
|
||||||
|
HLG,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dolby Vision video range type (12bit).
|
||||||
|
/// </summary>
|
||||||
|
DOVI,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HDR10+ video range type (10bit to 16bit).
|
||||||
|
/// </summary>
|
||||||
|
HDR10Plus
|
||||||
|
}
|
|
@ -209,8 +209,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(state.VideoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase)
|
if (string.Equals(state.VideoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase)
|
||||||
&& string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase)
|
&& state.VideoStream.VideoRange == VideoRange.HDR
|
||||||
&& string.Equals(state.VideoStream.VideoRangeType, "DOVI", StringComparison.OrdinalIgnoreCase))
|
&& state.VideoStream.VideoRangeType == VideoRangeType.DOVI)
|
||||||
{
|
{
|
||||||
// Only native SW decoder and HW accelerator can parse dovi rpu.
|
// Only native SW decoder and HW accelerator can parse dovi rpu.
|
||||||
var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty;
|
var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty;
|
||||||
|
@ -221,9 +221,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return isSwDecoder || isNvdecDecoder || isVaapiDecoder || isD3d11vaDecoder;
|
return isSwDecoder || isNvdecDecoder || isVaapiDecoder || isD3d11vaDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase)
|
return state.VideoStream.VideoRange == VideoRange.HDR
|
||||||
&& (string.Equals(state.VideoStream.VideoRangeType, "HDR10", StringComparison.OrdinalIgnoreCase)
|
&& (state.VideoStream.VideoRangeType == VideoRangeType.HDR10
|
||||||
|| string.Equals(state.VideoStream.VideoRangeType, "HLG", StringComparison.OrdinalIgnoreCase));
|
|| state.VideoStream.VideoRangeType == VideoRangeType.HLG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVulkanHwTonemapAvailable(EncodingJobInfo state, EncodingOptions options)
|
private bool IsVulkanHwTonemapAvailable(EncodingJobInfo state, EncodingOptions options)
|
||||||
|
@ -235,7 +235,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
// libplacebo has partial Dolby Vision to SDR tonemapping support.
|
// libplacebo has partial Dolby Vision to SDR tonemapping support.
|
||||||
return options.EnableTonemapping
|
return options.EnableTonemapping
|
||||||
&& string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase)
|
&& state.VideoStream.VideoRange == VideoRange.HDR
|
||||||
&& GetVideoColorBitDepth(state) == 10;
|
&& GetVideoColorBitDepth(state) == 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,8 +250,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
// Native VPP tonemapping may come to QSV in the future.
|
// Native VPP tonemapping may come to QSV in the future.
|
||||||
|
|
||||||
return string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase)
|
return state.VideoStream.VideoRange == VideoRange.HDR
|
||||||
&& string.Equals(state.VideoStream.VideoRangeType, "HDR10", StringComparison.OrdinalIgnoreCase);
|
&& state.VideoStream.VideoRangeType == VideoRangeType.HDR10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1945,12 +1945,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
var requestedRangeTypes = state.GetRequestedRangeTypes(videoStream.Codec);
|
var requestedRangeTypes = state.GetRequestedRangeTypes(videoStream.Codec);
|
||||||
if (requestedRangeTypes.Length > 0)
|
if (requestedRangeTypes.Length > 0)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(videoStream.VideoRangeType))
|
if (videoStream.VideoRangeType == VideoRangeType.Unknown)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requestedRangeTypes.Contains(videoStream.VideoRangeType, StringComparison.OrdinalIgnoreCase))
|
if (!requestedRangeTypes.Contains(videoStream.VideoRangeType.ToString(), StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
|
@ -367,22 +368,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the target video range type.
|
/// Gets the target video range type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TargetVideoRangeType
|
public VideoRangeType TargetVideoRangeType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (BaseRequest.Static || EncodingHelper.IsCopyCodec(OutputVideoCodec))
|
if (BaseRequest.Static || EncodingHelper.IsCopyCodec(OutputVideoCodec))
|
||||||
{
|
{
|
||||||
return VideoStream?.VideoRangeType;
|
return VideoStream?.VideoRangeType ?? VideoRangeType.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestedRangeType = GetRequestedRangeTypes(ActualOutputVideoCodec).FirstOrDefault();
|
if (Enum.TryParse(GetRequestedRangeTypes(ActualOutputVideoCodec).FirstOrDefault() ?? "Unknown", true, out VideoRangeType requestedRangeType))
|
||||||
if (!string.IsNullOrEmpty(requestedRangeType))
|
|
||||||
{
|
{
|
||||||
return requestedRangeType;
|
return requestedRangeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return VideoRangeType.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,38 @@
|
||||||
#pragma warning disable CS1591
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dlna
|
namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The condition processor.
|
||||||
|
/// </summary>
|
||||||
public static class ConditionProcessor
|
public static class ConditionProcessor
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a video condition is satisfied.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="condition">The <see cref="ProfileCondition"/>.</param>
|
||||||
|
/// <param name="width">The width.</param>
|
||||||
|
/// <param name="height">The height.</param>
|
||||||
|
/// <param name="videoBitDepth">The bit depth.</param>
|
||||||
|
/// <param name="videoBitrate">The bitrate.</param>
|
||||||
|
/// <param name="videoProfile">The video profile.</param>
|
||||||
|
/// <param name="videoRangeType">The <see cref="VideoRangeType"/>.</param>
|
||||||
|
/// <param name="videoLevel">The video level.</param>
|
||||||
|
/// <param name="videoFramerate">The framerate.</param>
|
||||||
|
/// <param name="packetLength">The packet length.</param>
|
||||||
|
/// <param name="timestamp">The <see cref="TransportStreamTimestamp"/>.</param>
|
||||||
|
/// <param name="isAnamorphic">A value indicating whether tthe video is anamorphic.</param>
|
||||||
|
/// <param name="isInterlaced">A value indicating whether tthe video is interlaced.</param>
|
||||||
|
/// <param name="refFrames">The reference frames.</param>
|
||||||
|
/// <param name="numVideoStreams">The number of video streams.</param>
|
||||||
|
/// <param name="numAudioStreams">The number of audio streams.</param>
|
||||||
|
/// <param name="videoCodecTag">The video codec tag.</param>
|
||||||
|
/// <param name="isAvc">A value indicating whether the video is AVC.</param>
|
||||||
|
/// <returns><b>True</b> if the condition is satisfied.</returns>
|
||||||
public static bool IsVideoConditionSatisfied(
|
public static bool IsVideoConditionSatisfied(
|
||||||
ProfileCondition condition,
|
ProfileCondition condition,
|
||||||
int? width,
|
int? width,
|
||||||
|
@ -16,7 +40,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? videoBitDepth,
|
int? videoBitDepth,
|
||||||
int? videoBitrate,
|
int? videoBitrate,
|
||||||
string? videoProfile,
|
string? videoProfile,
|
||||||
string? videoRangeType,
|
VideoRangeType? videoRangeType,
|
||||||
double? videoLevel,
|
double? videoLevel,
|
||||||
float? videoFramerate,
|
float? videoFramerate,
|
||||||
int? packetLength,
|
int? packetLength,
|
||||||
|
@ -70,6 +94,13 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a image condition is satisfied.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="condition">The <see cref="ProfileCondition"/>.</param>
|
||||||
|
/// <param name="width">The width.</param>
|
||||||
|
/// <param name="height">The height.</param>
|
||||||
|
/// <returns><b>True</b> if the condition is satisfied.</returns>
|
||||||
public static bool IsImageConditionSatisfied(ProfileCondition condition, int? width, int? height)
|
public static bool IsImageConditionSatisfied(ProfileCondition condition, int? width, int? height)
|
||||||
{
|
{
|
||||||
switch (condition.Property)
|
switch (condition.Property)
|
||||||
|
@ -83,6 +114,15 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if an audio condition is satisfied.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="condition">The <see cref="ProfileCondition"/>.</param>
|
||||||
|
/// <param name="audioChannels">The channel count.</param>
|
||||||
|
/// <param name="audioBitrate">The bitrate.</param>
|
||||||
|
/// <param name="audioSampleRate">The sample rate.</param>
|
||||||
|
/// <param name="audioBitDepth">The bit depth.</param>
|
||||||
|
/// <returns><b>True</b> if the condition is satisfied.</returns>
|
||||||
public static bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth)
|
public static bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth)
|
||||||
{
|
{
|
||||||
switch (condition.Property)
|
switch (condition.Property)
|
||||||
|
@ -100,6 +140,17 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if an audio condition is satisfied for a video.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="condition">The <see cref="ProfileCondition"/>.</param>
|
||||||
|
/// <param name="audioChannels">The channel count.</param>
|
||||||
|
/// <param name="audioBitrate">The bitrate.</param>
|
||||||
|
/// <param name="audioSampleRate">The sample rate.</param>
|
||||||
|
/// <param name="audioBitDepth">The bit depth.</param>
|
||||||
|
/// <param name="audioProfile">The profile.</param>
|
||||||
|
/// <param name="isSecondaryTrack">A value indicating whether the audio is a secondary track.</param>
|
||||||
|
/// <returns><b>True</b> if the condition is satisfied.</returns>
|
||||||
public static bool IsVideoAudioConditionSatisfied(
|
public static bool IsVideoAudioConditionSatisfied(
|
||||||
ProfileCondition condition,
|
ProfileCondition condition,
|
||||||
int? audioChannels,
|
int? audioChannels,
|
||||||
|
@ -281,5 +332,41 @@ namespace MediaBrowser.Model.Dlna
|
||||||
throw new InvalidOperationException("Unexpected ProfileConditionType: " + condition.Condition);
|
throw new InvalidOperationException("Unexpected ProfileConditionType: " + condition.Condition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsConditionSatisfied(ProfileCondition condition, VideoRangeType? currentValue)
|
||||||
|
{
|
||||||
|
if (!currentValue.HasValue || currentValue.Equals(VideoRangeType.Unknown))
|
||||||
|
{
|
||||||
|
// If the value is unknown, it satisfies if not marked as required
|
||||||
|
return !condition.IsRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
var conditionType = condition.Condition;
|
||||||
|
if (conditionType == ProfileConditionType.EqualsAny)
|
||||||
|
{
|
||||||
|
foreach (var singleConditionString in condition.Value.AsSpan().Split('|'))
|
||||||
|
{
|
||||||
|
if (Enum.TryParse(singleConditionString, true, out VideoRangeType conditionValue)
|
||||||
|
&& conditionValue.Equals(currentValue))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Enum.TryParse(condition.Value, true, out VideoRangeType expected))
|
||||||
|
{
|
||||||
|
return conditionType switch
|
||||||
|
{
|
||||||
|
ProfileConditionType.Equals => currentValue.Value == expected,
|
||||||
|
ProfileConditionType.NotEquals => currentValue.Value != expected,
|
||||||
|
_ => throw new InvalidOperationException("Unexpected ProfileConditionType: " + condition.Condition)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dlna
|
namespace MediaBrowser.Model.Dlna
|
||||||
|
@ -128,7 +129,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
bool isDirectStream,
|
bool isDirectStream,
|
||||||
long? runtimeTicks,
|
long? runtimeTicks,
|
||||||
string videoProfile,
|
string videoProfile,
|
||||||
string videoRangeType,
|
VideoRangeType videoRangeType,
|
||||||
double? videoLevel,
|
double? videoLevel,
|
||||||
float? videoFramerate,
|
float? videoFramerate,
|
||||||
int? packetLength,
|
int? packetLength,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
|
||||||
|
@ -445,7 +446,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int? bitDepth,
|
int? bitDepth,
|
||||||
int? videoBitrate,
|
int? videoBitrate,
|
||||||
string videoProfile,
|
string videoProfile,
|
||||||
string videoRangeType,
|
VideoRangeType videoRangeType,
|
||||||
double? videoLevel,
|
double? videoLevel,
|
||||||
float? videoFramerate,
|
float? videoFramerate,
|
||||||
int? packetLength,
|
int? packetLength,
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
@ -889,7 +890,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;
|
VideoRangeType? videoRangeType = videoStream?.VideoRangeType;
|
||||||
float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
||||||
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
||||||
bool? isInterlaced = videoStream?.IsInterlaced;
|
bool? isInterlaced = videoStream?.IsInterlaced;
|
||||||
|
@ -1144,7 +1145,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;
|
VideoRangeType? videoRangeType = videoStream?.VideoRangeType;
|
||||||
float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
||||||
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
||||||
bool? isInterlaced = videoStream?.IsInterlaced;
|
bool? isInterlaced = videoStream?.IsInterlaced;
|
||||||
|
@ -1932,6 +1933,10 @@ namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
item.SetOption(qualifier, "rangetype", string.Join(',', values));
|
item.SetOption(qualifier, "rangetype", string.Join(',', values));
|
||||||
}
|
}
|
||||||
|
else if (condition.Condition == ProfileConditionType.NotEquals)
|
||||||
|
{
|
||||||
|
item.SetOption(qualifier, "rangetype", string.Join(',', Enum.GetNames(typeof(VideoRangeType)).Except(values)));
|
||||||
|
}
|
||||||
else if (condition.Condition == ProfileConditionType.EqualsAny)
|
else if (condition.Condition == ProfileConditionType.EqualsAny)
|
||||||
{
|
{
|
||||||
var currentValue = item.GetOption(qualifier, "rangetype");
|
var currentValue = item.GetOption(qualifier, "rangetype");
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -281,23 +282,24 @@ namespace MediaBrowser.Model.Dlna
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the target video range type that will be in the output stream.
|
/// Gets the target video range type that will be in the output stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TargetVideoRangeType
|
public VideoRangeType TargetVideoRangeType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (IsDirectStream)
|
if (IsDirectStream)
|
||||||
{
|
{
|
||||||
return TargetVideoStream?.VideoRangeType;
|
return TargetVideoStream?.VideoRangeType ?? VideoRangeType.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetVideoCodecs = TargetVideoCodec;
|
var targetVideoCodecs = TargetVideoCodec;
|
||||||
var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0];
|
var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0];
|
||||||
if (!string.IsNullOrEmpty(videoCodec))
|
if (!string.IsNullOrEmpty(videoCodec)
|
||||||
|
&& Enum.TryParse(GetOption(videoCodec, "rangetype"), true, out VideoRangeType videoRangeType))
|
||||||
{
|
{
|
||||||
return GetOption(videoCodec, "rangetype");
|
return videoRangeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TargetVideoStream?.VideoRangeType;
|
return TargetVideoStream?.VideoRangeType ?? VideoRangeType.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
|
@ -148,7 +149,7 @@ namespace MediaBrowser.Model.Entities
|
||||||
/// Gets the video range.
|
/// Gets the video range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The video range.</value>
|
/// <value>The video range.</value>
|
||||||
public string VideoRange
|
public VideoRange VideoRange
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -162,7 +163,7 @@ namespace MediaBrowser.Model.Entities
|
||||||
/// Gets the video range type.
|
/// Gets the video range type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The video range type.</value>
|
/// <value>The video range type.</value>
|
||||||
public string VideoRangeType
|
public VideoRangeType VideoRangeType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -306,9 +307,9 @@ namespace MediaBrowser.Model.Entities
|
||||||
attributes.Add(Codec.ToUpperInvariant());
|
attributes.Add(Codec.ToUpperInvariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(VideoRange))
|
if (VideoRange != VideoRange.Unknown)
|
||||||
{
|
{
|
||||||
attributes.Add(VideoRange.ToUpperInvariant());
|
attributes.Add(VideoRange.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Title))
|
if (!string.IsNullOrEmpty(Title))
|
||||||
|
@ -677,23 +678,23 @@ namespace MediaBrowser.Model.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (string VideoRange, string VideoRangeType) GetVideoColorRange()
|
public (VideoRange VideoRange, VideoRangeType VideoRangeType) GetVideoColorRange()
|
||||||
{
|
{
|
||||||
if (Type != MediaStreamType.Video)
|
if (Type != MediaStreamType.Video)
|
||||||
{
|
{
|
||||||
return (null, null);
|
return (VideoRange.Unknown, VideoRangeType.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
var colorTransfer = ColorTransfer;
|
var colorTransfer = ColorTransfer;
|
||||||
|
|
||||||
if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return ("HDR", "HDR10");
|
return (VideoRange.HDR, VideoRangeType.HDR10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return ("HDR", "HLG");
|
return (VideoRange.HDR, VideoRangeType.HLG);
|
||||||
}
|
}
|
||||||
|
|
||||||
var codecTag = CodecTag;
|
var codecTag = CodecTag;
|
||||||
|
@ -711,10 +712,10 @@ namespace MediaBrowser.Model.Entities
|
||||||
|| string.Equals(codecTag, "dvhe", StringComparison.OrdinalIgnoreCase)
|
|| string.Equals(codecTag, "dvhe", StringComparison.OrdinalIgnoreCase)
|
||||||
|| string.Equals(codecTag, "dav1", StringComparison.OrdinalIgnoreCase))
|
|| string.Equals(codecTag, "dav1", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return ("HDR", "DOVI");
|
return (VideoRange.HDR, VideoRangeType.DOVI);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ("SDR", "SDR");
|
return (VideoRange.SDR, VideoRangeType.SDR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue