Browse Source

fix jellyfin streaming and sar calculation (#1195)

pull/1196/head
Jason Dove 2 years ago committed by GitHub
parent
commit
8ff6bf652c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      CHANGELOG.md
  2. 40
      ErsatzTV.FFmpeg/MediaStream.cs
  3. 19
      ErsatzTV.Infrastructure/Jellyfin/JellyfinApiClient.cs
  4. 1
      ErsatzTV.Infrastructure/Jellyfin/Models/JellyfinMediaStreamResponse.cs

4
CHANGELOG.md

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Fix scaling anamorphic content from non-local libraries
- Fix direct streaming content from Jellyfin that has external subtitles
- Note that these subtitles are not currently supported in ETV, but they did cause a playback issue
## [0.7.5-beta] - 2023-03-05
### Added

40
ErsatzTV.FFmpeg/MediaStream.cs

@ -15,7 +15,7 @@ public record VideoStream( @@ -15,7 +15,7 @@ public record VideoStream(
Option<IPixelFormat> PixelFormat,
ColorParams ColorParams,
FrameSize FrameSize,
string SampleAspectRatio,
string MaybeSampleAspectRatio,
string DisplayAspectRatio,
Option<string> FrameRate,
bool StillImage,
@ -25,7 +25,37 @@ public record VideoStream( @@ -25,7 +25,37 @@ public record VideoStream(
StreamKind.Video)
{
public int BitDepth => PixelFormat.Map(pf => pf.BitDepth).IfNone(8);
public string SampleAspectRatio
{
get
{
// some media servers don't provide sample aspect ratio so we have to calculate it
if (string.IsNullOrWhiteSpace(MaybeSampleAspectRatio) || MaybeSampleAspectRatio == "0:0")
{
// first check for decimal DAR
if (!double.TryParse(DisplayAspectRatio, out double dar))
{
// if not, assume it's a ratio
string[] split = DisplayAspectRatio.Split(':');
var num = double.Parse(split[0]);
var den = double.Parse(split[1]);
dar = num / den;
}
double res = FrameSize.Width / (double)FrameSize.Height;
return $"{dar}:{res}";
}
else
{
string[] split = MaybeSampleAspectRatio.Split(':');
var num = double.Parse(split[0]);
var den = double.Parse(split[1]);
return $"{num}:{den}";
}
}
}
public bool IsAnamorphic
{
get
@ -89,13 +119,13 @@ public record VideoStream( @@ -89,13 +119,13 @@ public record VideoStream(
private double GetSAR()
{
// some media servers don't provide sample aspect ratio so we have to calculate it
if (string.IsNullOrWhiteSpace(SampleAspectRatio))
if (string.IsNullOrWhiteSpace(MaybeSampleAspectRatio) || MaybeSampleAspectRatio == "0:0")
{
// first check for decimal DAR
if (!double.TryParse(DisplayAspectRatio, out double dar))
{
// if not, assume it's a ratio
string[] split = DisplayAspectRatio.Split(':');
string[] split = DisplayAspectRatio.Split(':');
var num = double.Parse(split[0]);
var den = double.Parse(split[1]);
dar = num / den;
@ -106,7 +136,7 @@ public record VideoStream( @@ -106,7 +136,7 @@ public record VideoStream(
}
else
{
string[] split = SampleAspectRatio.Split(':');
string[] split = MaybeSampleAspectRatio.Split(':');
var num = double.Parse(split[0]);
var den = double.Parse(split[1]);
return num / den;

19
ErsatzTV.Infrastructure/Jellyfin/JellyfinApiClient.cs

@ -895,7 +895,18 @@ public class JellyfinApiClient : IJellyfinApiClient @@ -895,7 +895,18 @@ public class JellyfinApiClient : IJellyfinApiClient
}
JellyfinMediaSourceResponse mediaSource = response.MediaSources.Head();
IList<JellyfinMediaStreamResponse> streams = mediaSource.MediaStreams;
// jellyfin includes external streams first, obscuring real stream indexes
// from the source file
int streamIndexOffset = mediaSource.MediaStreams
.Filter(s => s.IsExternal)
.Map(s => s.Index + 1)
.OrderByDescending(i => i)
.FirstOrDefault();
IList<JellyfinMediaStreamResponse> streams = mediaSource.MediaStreams
.Filter(s => s.IsExternal == false)
.ToList();
Option<JellyfinMediaStreamResponse> maybeVideoStream =
streams.Find(s => s.Type == JellyfinMediaStreamType.Video);
return maybeVideoStream.Map(
@ -948,7 +959,7 @@ public class JellyfinApiClient : IJellyfinApiClient @@ -948,7 +959,7 @@ public class JellyfinApiClient : IJellyfinApiClient
{
MediaVersionId = version.Id,
MediaStreamKind = MediaStreamKind.Video,
Index = videoStream.Index,
Index = videoStream.Index - streamIndexOffset,
Codec = videoStream.Codec,
Profile = (videoStream.Profile ?? string.Empty).ToLowerInvariant(),
Default = videoStream.IsDefault,
@ -968,7 +979,7 @@ public class JellyfinApiClient : IJellyfinApiClient @@ -968,7 +979,7 @@ public class JellyfinApiClient : IJellyfinApiClient
{
MediaVersionId = version.Id,
MediaStreamKind = MediaStreamKind.Audio,
Index = audioStream.Index,
Index = audioStream.Index - streamIndexOffset,
Codec = audioStream.Codec,
Profile = (audioStream.Profile ?? string.Empty).ToLowerInvariant(),
Channels = audioStream.Channels ?? 2,
@ -988,7 +999,7 @@ public class JellyfinApiClient : IJellyfinApiClient @@ -988,7 +999,7 @@ public class JellyfinApiClient : IJellyfinApiClient
{
MediaVersionId = version.Id,
MediaStreamKind = MediaStreamKind.Subtitle,
Index = subtitleStream.Index,
Index = subtitleStream.Index - streamIndexOffset,
Codec = subtitleStream.Codec,
Default = subtitleStream.IsDefault,
Forced = subtitleStream.IsForced,

1
ErsatzTV.Infrastructure/Jellyfin/Models/JellyfinMediaStreamResponse.cs

@ -11,6 +11,7 @@ public class JellyfinMediaStreamResponse @@ -11,6 +11,7 @@ public class JellyfinMediaStreamResponse
public int Index { get; set; }
public bool IsDefault { get; set; }
public bool IsForced { get; set; }
public bool IsExternal { get; set; }
public string Profile { get; set; }
public string AspectRatio { get; set; }
public int? Channels { get; set; }

Loading…
Cancel
Save