diff options
| author | theopeuchlestrade <83510973+theopeuchlestrade@users.noreply.github.com> | 2026-10-05 19:19:10 -0400 |
|---|---|---|
| committer | Cody Robibero <cody@robibe.ro> | 2026-10-05 19:19:10 -0400 |
| commit | 32efb47601d3ce4174f61a66181d9e4665288c92 (patch) | |
| tree | e0818ea584c7ab7ea67fb358ec8ceca5392f7938 | |
| parent | f89279fc4bd33d47623284ad337d3bc5aa6dd282 (diff) | |
Use hvc1 for Dolby Vision profile 8
Original-merge: 173ee6947286d36cdb0ba86bbe9676770c57e27b
Merged-by: crobibero <cody@robibe.ro>
Backported-by: Cody Robibero <cody@robibe.ro>
| -rw-r--r-- | Jellyfin.Api/Controllers/DynamicHlsController.cs | 13 | ||||
| -rw-r--r-- | tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs | 29 |
2 files changed, 40 insertions, 2 deletions
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index dc0a6b2da9..6df76de0b4 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1778,6 +1778,16 @@ public class DynamicHlsController : BaseJellyfinApiController } /// <summary> + /// Selects the HEVC Dolby Vision sample entry tag. + /// </summary> + /// <param name="stream">The video stream.</param> + /// <returns>The MP4 sample entry tag.</returns> + internal static string GetDolbyVisionHevcCodecTag(MediaStream stream) + { + return stream.DvProfile == 8 ? "hvc1" : "dvh1"; + } + + /// <summary> /// Gets the video arguments for transcoding. /// </summary> /// <param name="state">The <see cref="StreamState"/>.</param> @@ -1819,8 +1829,7 @@ public class DynamicHlsController : BaseJellyfinApiController { if (isActualOutputVideoCodecHevc) { - // Use hvc1 for 8.4. This is what Dolby uses for its official sample streams. Tagging with dvh1 would break some players with strict tag checking like Apple Safari. - var codecTag = state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithHLG ? "hvc1" : "dvh1"; + var codecTag = GetDolbyVisionHevcCodecTag(state.VideoStream); args += $" -tag:v:0 {codecTag} -strict -2"; } else if (isActualOutputVideoCodecAv1) diff --git a/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs b/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs index 5f5f273f12..a9f85739bc 100644 --- a/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs +++ b/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Controllers; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Entities; using Microsoft.Extensions.Logging.Abstractions; using Xunit; @@ -11,6 +12,34 @@ namespace Jellyfin.Api.Tests.Controllers public class DynamicHlsControllerTests { [Theory] + [InlineData(8, 1, "smpte2084", false, "hvc1")] + [InlineData(8, 1, "smpte2084", true, "hvc1")] + [InlineData(8, 2, "bt709", false, "hvc1")] + [InlineData(8, 4, "arib-std-b67", false, "hvc1")] + [InlineData(8, 6, "smpte2084", false, "hvc1")] + [InlineData(5, 0, "smpte2084", false, "dvh1")] + [InlineData(7, 6, "smpte2084", false, "dvh1")] + [InlineData(null, null, "smpte2084", false, "dvh1")] + public void GetDolbyVisionHevcCodecTag_SelectsTagForProfile(int? profile, int? compatibilityId, string transfer, bool hdr10Plus, string expected) + { + var stream = new MediaStream + { + Codec = "hevc", + Type = MediaStreamType.Video, + RpuPresentFlag = 1, + BlPresentFlag = 1, + ColorSpace = "bt2020nc", + ColorPrimaries = "bt2020", + ColorTransfer = transfer, + DvProfile = profile, + DvBlSignalCompatibilityId = compatibilityId, + Hdr10PlusPresentFlag = hdr10Plus + }; + + Assert.Equal(expected, DynamicHlsController.GetDolbyVisionHevcCodecTag(stream)); + } + + [Theory] [MemberData(nameof(GetSegmentLengths_Success_TestData))] public void GetSegmentLengths_Success(long runtimeTicks, int segmentlength, double[] expected) { |
