aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
diff options
context:
space:
mode:
authorNick <20588554+nicknsy@users.noreply.github.com>2023-06-28 21:43:23 -0700
committerNick <20588554+nicknsy@users.noreply.github.com>2023-06-28 21:43:23 -0700
commit6d9e43cfe03d94aec62a0b35743003fa4caa32b1 (patch)
treea78b31f6743061f4c8bfa41985ae6b2574eaa06f /Jellyfin.Api/Helpers/DynamicHlsHelper.cs
parentfc619337481e3bb0f686aee06d9c5630926baaef (diff)
parent76939bbd9bebb622759422f262c2490b56ab5a16 (diff)
Merge branch 'master' into trickplay
Diffstat (limited to 'Jellyfin.Api/Helpers/DynamicHlsHelper.cs')
-rw-r--r--Jellyfin.Api/Helpers/DynamicHlsHelper.cs53
1 files changed, 39 insertions, 14 deletions
diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
index bd3091055..45e0d475d 100644
--- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
+++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
@@ -216,9 +217,9 @@ public class DynamicHlsHelper
// Provide SDR HEVC entrance for backward compatibility.
if (encodingOptions.AllowHevcEncoding
+ && !encodingOptions.AllowAv1Encoding
&& EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
- && !string.IsNullOrEmpty(state.VideoStream.VideoRange)
- && string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase)
+ && state.VideoStream.VideoRange == VideoRange.HDR
&& string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
{
var requestedVideoProfiles = state.GetRequestedProfiles("hevc");
@@ -258,11 +259,12 @@ public class DynamicHlsHelper
// Provide Level 5.0 entrance for backward compatibility.
// e.g. Apple A10 chips refuse the master playlist containing SDR HEVC Main Level 5.1 video,
// but in fact it is capable of playing videos up to Level 6.1.
- if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
+ if (encodingOptions.AllowHevcEncoding
+ && !encodingOptions.AllowAv1Encoding
+ && EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
&& state.VideoStream.Level.HasValue
&& state.VideoStream.Level > 150
- && !string.IsNullOrEmpty(state.VideoStream.VideoRange)
- && string.Equals(state.VideoStream.VideoRange, "SDR", StringComparison.OrdinalIgnoreCase)
+ && state.VideoStream.VideoRange == VideoRange.SDR
&& string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
{
var playlistCodecsField = new StringBuilder();
@@ -353,17 +355,17 @@ public class DynamicHlsHelper
/// <param name="state">StreamState of the current stream.</param>
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;
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
{
- if (string.Equals(videoRange, "SDR", StringComparison.OrdinalIgnoreCase))
+ if (videoRange == VideoRange.SDR)
{
builder.Append(",VIDEO-RANGE=SDR");
}
- if (string.Equals(videoRange, "HDR", StringComparison.OrdinalIgnoreCase))
+ if (videoRange == VideoRange.HDR)
{
builder.Append(",VIDEO-RANGE=PQ");
}
@@ -603,6 +605,12 @@ public class DynamicHlsHelper
levelString = state.GetRequestedLevel("h265") ?? state.GetRequestedLevel("hevc") ?? "120";
levelString = EncodingHelper.NormalizeTranscodingLevel(state, levelString);
}
+
+ if (string.Equals(state.ActualOutputVideoCodec, "av1", StringComparison.OrdinalIgnoreCase))
+ {
+ levelString = state.GetRequestedLevel("av1") ?? "19";
+ levelString = EncodingHelper.NormalizeTranscodingLevel(state, levelString);
+ }
}
if (int.TryParse(levelString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedLevel))
@@ -614,11 +622,11 @@ public class DynamicHlsHelper
}
/// <summary>
- /// Get the H.26X profile of the output video stream.
+ /// Get the profile of the output video stream.
/// </summary>
/// <param name="state">StreamState of the current stream.</param>
/// <param name="codec">Video codec.</param>
- /// <returns>H.26X profile of the output video stream.</returns>
+ /// <returns>Profile of the output video stream.</returns>
private string GetOutputVideoCodecProfile(StreamState state, string codec)
{
string profileString = string.Empty;
@@ -636,7 +644,8 @@ public class DynamicHlsHelper
}
if (string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase)
- || string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase))
+ || string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(state.ActualOutputVideoCodec, "av1", StringComparison.OrdinalIgnoreCase))
{
profileString ??= "main";
}
@@ -706,9 +715,9 @@ public class DynamicHlsHelper
{
if (level == 0)
{
- // This is 0 when there's no requested H.26X level in the device profile
- // and the source is not encoded in H.26X
- _logger.LogError("Got invalid H.26X level when building CODECS field for HLS master playlist");
+ // This is 0 when there's no requested level in the device profile
+ // and the source is not encoded in H.26X or AV1
+ _logger.LogError("Got invalid level when building CODECS field for HLS master playlist");
return string.Empty;
}
@@ -725,6 +734,22 @@ public class DynamicHlsHelper
return HlsCodecStringHelpers.GetH265String(profile, level);
}
+ if (string.Equals(codec, "av1", StringComparison.OrdinalIgnoreCase))
+ {
+ string profile = GetOutputVideoCodecProfile(state, "av1");
+
+ // Currently we only transcode to 8 bits AV1
+ int bitDepth = 8;
+ if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
+ && state.VideoStream != null
+ && state.VideoStream.BitDepth.HasValue)
+ {
+ bitDepth = state.VideoStream.BitDepth.Value;
+ }
+
+ return HlsCodecStringHelpers.GetAv1String(profile, level, false, bitDepth);
+ }
+
return string.Empty;
}