Preserve native broadcast video and add patient shared stream startup

This commit is contained in:
2026-10-25 16:59:56 +01:00
parent bd7395f045
commit 11a34a5195
27 changed files with 708 additions and 139 deletions
+6 -12
View File
@@ -13,6 +13,8 @@ namespace Jellyfin.Plugin.Enigma2;
// Probe-only transport details; the public Jellyfin contract remains MediaStream.
public sealed class BroadcastMediaStream : MediaStream
{
public string SampleAspectRatio { get; set; }
public string FrameRateRational { get; set; }
public int? TransportId { get; set; }
public bool IsVisualImpaired { get; set; }
public byte[] SubtitleExtraData { get; set; }
@@ -27,9 +29,9 @@ public sealed class BroadcastTracks
public string Key { get; }
public int AudioCount => Input.Count(s => s.Type == MediaStreamType.Audio);
public bool HasSubtitles => Input.Any(s => s.Type == MediaStreamType.Subtitle);
public BroadcastTracks(IEnumerable<MediaStream> streams, bool normalize = true, bool preserveResolution = true)
public BroadcastTracks(IEnumerable<MediaStream> streams, bool normalize = false, bool preserveResolution = true)
{
Normalize = normalize;
Normalize = false; // Legacy argument retained for compatibility; channel AV is never normalized.
var all = streams.ToArray();
Input = all.Where(s => s.Type == MediaStreamType.Video).Take(1)
.Concat(all.Where(s => s.Type == MediaStreamType.Audio))
@@ -41,21 +43,13 @@ public sealed class BroadcastTracks
Output = Input.Select((s, i) => {
var copy = LiveStreamProbe.ParseLiveMetadata(s); copy.Index = i;
if (s is BroadcastMediaStream { IsVisualImpaired: true } && string.IsNullOrWhiteSpace(copy.Title)) copy.Title = "Audio description";
if (normalize && copy.Type == MediaStreamType.Video)
{
copy.Codec = "h264"; copy.Width = preserveResolution ? s.Width : ContinuityStreams.Width;
copy.Height = preserveResolution ? s.Height : ContinuityStreams.Height; copy.Level = null;
copy.Profile = "Constrained Baseline"; copy.PixelFormat = "yuv420p"; copy.IsInterlaced = false;
copy.AverageFrameRate = copy.RealFrameRate = ContinuityStreams.FrameRate;
copy.ColorRange = copy.ColorSpace = copy.ColorTransfer = copy.ColorPrimaries = null; copy.BitRate = null;
}
if (normalize && copy.Type == MediaStreamType.Audio)
{ copy.Codec = "aac"; copy.Channels = 2; copy.SampleRate = 48000; copy.BitRate = 128000; copy.Profile = "LC"; copy.ChannelLayout = "stereo"; }
return copy;
}).ToArray();
// Stable per-channel track cache; no URLs, credentials or user identities in its key.
Key = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(Input.Select(s => new {
s.Type, s.Index, s.Codec, s.Language, s.Title, s.IsDefault, s.IsForced, s.IsHearingImpaired, s.Channels, s.Width, s.Height,
s.Profile, s.PixelFormat, s.AverageFrameRate, s.RealFrameRate, s.IsInterlaced, s.ColorRange, s.ColorSpace, s.ColorTransfer, s.ColorPrimaries, s.SampleRate, s.ChannelLayout,
Sar = (s as BroadcastMediaStream)?.SampleAspectRatio, Rate = (s as BroadcastMediaStream)?.FrameRateRational,
Pid = (s as BroadcastMediaStream)?.TransportId, Extra = (s as BroadcastMediaStream)?.SubtitleExtraData
}))))).ToLowerInvariant();
}