Merge pull request #11399 from jellyfin/audio-remux

This commit is contained in:
Cody Robibero 2024-07-18 08:12:20 -04:00 committed by GitHub
commit 4239de1ee7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 107 additions and 10 deletions

View file

@ -108,7 +108,7 @@ namespace MediaBrowser.Model.Dlna
var inputAudioSampleRate = audioStream?.SampleRate;
var inputAudioBitDepth = audioStream?.BitDepth;
if (directPlayMethod.HasValue)
if (directPlayMethod is PlayMethod.DirectPlay)
{
var profile = options.Profile;
var audioFailureConditions = GetProfileConditionsForAudio(profile.CodecProfiles, item.Container, audioStream?.Codec, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, true);
@ -124,6 +124,46 @@ namespace MediaBrowser.Model.Dlna
}
}
if (directPlayMethod is PlayMethod.DirectStream)
{
var remuxContainer = item.TranscodingContainer ?? "ts";
var supportedHlsContainers = new[] { "ts", "mp4" };
// If the container specified for the profile is an HLS supported container, use that container instead, overriding the preference
// The client should be responsible to ensure this container is compatible
remuxContainer = Array.Exists(supportedHlsContainers, element => string.Equals(element, directPlayInfo.Profile?.Container, StringComparison.OrdinalIgnoreCase)) ? directPlayInfo.Profile?.Container : remuxContainer;
bool codeIsSupported;
if (item.TranscodingSubProtocol == MediaStreamProtocol.hls)
{
// Enforce HLS audio codec restrictions
if (string.Equals(remuxContainer, "mp4", StringComparison.OrdinalIgnoreCase))
{
codeIsSupported = _supportedHlsAudioCodecsMp4.Contains(directPlayInfo.Profile?.AudioCodec ?? directPlayInfo.Profile?.Container);
}
else
{
codeIsSupported = _supportedHlsAudioCodecsTs.Contains(directPlayInfo.Profile?.AudioCodec ?? directPlayInfo.Profile?.Container);
}
}
else
{
// Let's assume the client has given a correct container for http
codeIsSupported = true;
}
if (codeIsSupported)
{
playlistItem.PlayMethod = directPlayMethod.Value;
playlistItem.Container = remuxContainer;
playlistItem.TranscodeReasons = transcodeReasons;
playlistItem.SubProtocol = item.TranscodingSubProtocol;
item.TranscodingContainer = remuxContainer;
return playlistItem;
}
transcodeReasons |= TranscodeReason.AudioCodecNotSupported;
playlistItem.TranscodeReasons = transcodeReasons;
}
TranscodingProfile? transcodingProfile = null;
foreach (var tcProfile in options.Profile.TranscodingProfiles)
{
@ -379,6 +419,7 @@ namespace MediaBrowser.Model.Dlna
var directPlayProfile = options.Profile.DirectPlayProfiles
.FirstOrDefault(x => x.Type == DlnaProfileType.Audio && IsAudioDirectPlaySupported(x, item, audioStream));
TranscodeReason transcodeReasons = 0;
if (directPlayProfile is null)
{
_logger.LogDebug(
@ -387,14 +428,25 @@ namespace MediaBrowser.Model.Dlna
item.Path ?? "Unknown path",
audioStream.Codec ?? "Unknown codec");
return (null, null, GetTranscodeReasonsFromDirectPlayProfile(item, null, audioStream, options.Profile.DirectPlayProfiles));
}
var directStreamProfile = options.Profile.DirectPlayProfiles
.FirstOrDefault(x => x.Type == DlnaProfileType.Audio && IsAudioDirectStreamSupported(x, item, audioStream));
TranscodeReason transcodeReasons = 0;
if (directStreamProfile is not null)
{
directPlayProfile = directStreamProfile;
transcodeReasons |= TranscodeReason.ContainerNotSupported;
}
else
{
return (null, null, GetTranscodeReasonsFromDirectPlayProfile(item, null, audioStream, options.Profile.DirectPlayProfiles));
}
}
// The profile describes what the device supports
// If device requirements are satisfied then allow both direct stream and direct play
if (item.SupportsDirectPlay)
// Note: As of 10.10 codebase, SupportsDirectPlay is always true because the MediaSourceInfo initializes this key as true
// Need to check additionally for current transcode reasons
if (item.SupportsDirectPlay && transcodeReasons == 0)
{
if (!IsBitrateLimitExceeded(item, options.GetMaxBitrate(true) ?? 0))
{
@ -414,7 +466,10 @@ namespace MediaBrowser.Model.Dlna
{
if (!IsBitrateLimitExceeded(item, options.GetMaxBitrate(true) ?? 0))
{
if (options.EnableDirectStream)
// Note: as of 10.10 codebase, the options.EnableDirectStream is always false due to
// "direct-stream http streaming is currently broken"
// Don't check that option for audio as we always assume that is supported
if (transcodeReasons == TranscodeReason.ContainerNotSupported)
{
return (directPlayProfile, PlayMethod.DirectStream, transcodeReasons);
}
@ -2129,5 +2184,24 @@ namespace MediaBrowser.Model.Dlna
return true;
}
private static bool IsAudioDirectStreamSupported(DirectPlayProfile profile, MediaSourceInfo item, MediaStream audioStream)
{
// Check container type, this should NOT be supported
// If the container is supported, the file should be directly played
if (!profile.SupportsContainer(item.Container))
{
// Check audio codec, we cannot use the SupportsAudioCodec here
// Because that one assumes empty container supports all codec, which is just useless
string? audioCodec = audioStream?.Codec;
if (string.Equals(profile.AudioCodec, audioCodec, StringComparison.OrdinalIgnoreCase) ||
string.Equals(profile.Container, audioCodec, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
}