|
|
|
@ -1,5 +1,3 @@
|
|
|
|
|
#nullable disable
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
|
|
|
@ -37,29 +35,20 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
_logger = logger;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="StreamBuilder"/> class.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="logger">The <see cref="ILogger"/> object.</param>
|
|
|
|
|
public StreamBuilder(ILogger<StreamBuilder> logger)
|
|
|
|
|
: this(new FullTranscoderSupport(), logger)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the optimal audio stream.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="options">The <see cref="MediaOptions"/> object to get the audio stream from.</param>
|
|
|
|
|
/// <returns>The <see cref="StreamInfo"/> of the optimal audio stream.</returns>
|
|
|
|
|
public StreamInfo GetOptimalAudioStream(MediaOptions options)
|
|
|
|
|
public StreamInfo? GetOptimalAudioStream(MediaOptions options)
|
|
|
|
|
{
|
|
|
|
|
ValidateMediaOptions(options, false);
|
|
|
|
|
|
|
|
|
|
var mediaSources = new List<MediaSourceInfo>();
|
|
|
|
|
foreach (var mediaSource in options.MediaSources)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(options.MediaSourceId) ||
|
|
|
|
|
string.Equals(mediaSource.Id, options.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
if (string.IsNullOrEmpty(options.MediaSourceId)
|
|
|
|
|
|| string.Equals(mediaSource.Id, options.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
mediaSources.Add(mediaSource);
|
|
|
|
|
}
|
|
|
|
@ -68,7 +57,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
var streams = new List<StreamInfo>();
|
|
|
|
|
foreach (var mediaSourceInfo in mediaSources)
|
|
|
|
|
{
|
|
|
|
|
StreamInfo streamInfo = GetOptimalAudioStream(mediaSourceInfo, options);
|
|
|
|
|
StreamInfo? streamInfo = GetOptimalAudioStream(mediaSourceInfo, options);
|
|
|
|
|
if (streamInfo is not null)
|
|
|
|
|
{
|
|
|
|
|
streams.Add(streamInfo);
|
|
|
|
@ -84,7 +73,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return GetOptimalStream(streams, options.GetMaxBitrate(true) ?? 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private StreamInfo GetOptimalAudioStream(MediaSourceInfo item, MediaOptions options)
|
|
|
|
|
private StreamInfo? GetOptimalAudioStream(MediaSourceInfo item, MediaOptions options)
|
|
|
|
|
{
|
|
|
|
|
var playlistItem = new StreamInfo
|
|
|
|
|
{
|
|
|
|
@ -138,7 +127,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TranscodingProfile transcodingProfile = null;
|
|
|
|
|
TranscodingProfile? transcodingProfile = null;
|
|
|
|
|
foreach (var tcProfile in options.Profile.TranscodingProfiles)
|
|
|
|
|
{
|
|
|
|
|
if (tcProfile.Type == playlistItem.MediaType
|
|
|
|
@ -190,15 +179,15 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="options">The <see cref="MediaOptions"/> object to get the video stream from.</param>
|
|
|
|
|
/// <returns>The <see cref="StreamInfo"/> of the optimal video stream.</returns>
|
|
|
|
|
public StreamInfo GetOptimalVideoStream(MediaOptions options)
|
|
|
|
|
public StreamInfo? GetOptimalVideoStream(MediaOptions options)
|
|
|
|
|
{
|
|
|
|
|
ValidateMediaOptions(options, true);
|
|
|
|
|
|
|
|
|
|
var mediaSources = new List<MediaSourceInfo>();
|
|
|
|
|
foreach (var mediaSourceInfo in options.MediaSources)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(options.MediaSourceId) ||
|
|
|
|
|
string.Equals(mediaSourceInfo.Id, options.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
if (string.IsNullOrEmpty(options.MediaSourceId)
|
|
|
|
|
|| string.Equals(mediaSourceInfo.Id, options.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
mediaSources.Add(mediaSourceInfo);
|
|
|
|
|
}
|
|
|
|
@ -223,7 +212,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return GetOptimalStream(streams, options.GetMaxBitrate(false) ?? 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static StreamInfo GetOptimalStream(List<StreamInfo> streams, long maxBitrate)
|
|
|
|
|
private static StreamInfo? GetOptimalStream(List<StreamInfo> streams, long maxBitrate)
|
|
|
|
|
=> SortMediaSources(streams, maxBitrate).FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
private static IOrderedEnumerable<StreamInfo> SortMediaSources(List<StreamInfo> streams, long maxBitrate)
|
|
|
|
@ -366,7 +355,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
/// <param name="type">The <see cref="DlnaProfileType"/>.</param>
|
|
|
|
|
/// <param name="playProfile">The <see cref="DirectPlayProfile"/> object to get the video stream from.</param>
|
|
|
|
|
/// <returns>The the normalized input container.</returns>
|
|
|
|
|
public static string NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, DeviceProfile profile, DlnaProfileType type, DirectPlayProfile playProfile = null)
|
|
|
|
|
public static string? NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, DeviceProfile? profile, DlnaProfileType type, DirectPlayProfile? playProfile = null)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(inputContainer))
|
|
|
|
|
{
|
|
|
|
@ -394,7 +383,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return formats[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private (DirectPlayProfile Profile, PlayMethod? PlayMethod, TranscodeReason TranscodeReasons) GetAudioDirectPlayProfile(MediaSourceInfo item, MediaStream audioStream, MediaOptions options)
|
|
|
|
|
private (DirectPlayProfile? Profile, PlayMethod? PlayMethod, TranscodeReason TranscodeReasons) GetAudioDirectPlayProfile(MediaSourceInfo item, MediaStream audioStream, MediaOptions options)
|
|
|
|
|
{
|
|
|
|
|
var directPlayProfile = options.Profile.DirectPlayProfiles
|
|
|
|
|
.FirstOrDefault(x => x.Type == DlnaProfileType.Audio && IsAudioDirectPlaySupported(x, item, audioStream));
|
|
|
|
@ -449,7 +438,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return (directPlayProfile, null, transcodeReasons);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static TranscodeReason GetTranscodeReasonsFromDirectPlayProfile(MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream, IEnumerable<DirectPlayProfile> directPlayProfiles)
|
|
|
|
|
private static TranscodeReason GetTranscodeReasonsFromDirectPlayProfile(MediaSourceInfo item, MediaStream? videoStream, MediaStream audioStream, IEnumerable<DirectPlayProfile> directPlayProfiles)
|
|
|
|
|
{
|
|
|
|
|
var mediaType = videoStream is null ? DlnaProfileType.Audio : DlnaProfileType.Video;
|
|
|
|
|
|
|
|
|
@ -575,7 +564,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void SetStreamInfoOptionsFromDirectPlayProfile(MediaOptions options, MediaSourceInfo item, StreamInfo playlistItem, DirectPlayProfile directPlayProfile)
|
|
|
|
|
private static void SetStreamInfoOptionsFromDirectPlayProfile(MediaOptions options, MediaSourceInfo item, StreamInfo playlistItem, DirectPlayProfile? directPlayProfile)
|
|
|
|
|
{
|
|
|
|
|
var container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Video, directPlayProfile);
|
|
|
|
|
var protocol = "http";
|
|
|
|
@ -587,7 +576,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
playlistItem.SubProtocol = protocol;
|
|
|
|
|
|
|
|
|
|
playlistItem.VideoCodecs = new[] { item.VideoStream.Codec };
|
|
|
|
|
playlistItem.AudioCodecs = ContainerProfile.SplitValue(directPlayProfile.AudioCodec);
|
|
|
|
|
playlistItem.AudioCodecs = ContainerProfile.SplitValue(directPlayProfile?.AudioCodec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private StreamInfo BuildVideoItem(MediaSourceInfo item, MediaOptions options)
|
|
|
|
@ -646,7 +635,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
isEligibleForDirectPlay,
|
|
|
|
|
isEligibleForDirectStream);
|
|
|
|
|
|
|
|
|
|
DirectPlayProfile directPlayProfile = null;
|
|
|
|
|
DirectPlayProfile? directPlayProfile = null;
|
|
|
|
|
if (isEligibleForDirectPlay || isEligibleForDirectStream)
|
|
|
|
|
{
|
|
|
|
|
// See if it can be direct played
|
|
|
|
@ -677,16 +666,16 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
playlistItem.AudioStreamIndex = audioStream?.Index;
|
|
|
|
|
if (audioStream is not null)
|
|
|
|
|
{
|
|
|
|
|
playlistItem.AudioCodecs = ContainerProfile.SplitValue(directPlayProfile.AudioCodec);
|
|
|
|
|
playlistItem.AudioCodecs = ContainerProfile.SplitValue(directPlayProfile?.AudioCodec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetStreamInfoOptionsFromDirectPlayProfile(options, item, playlistItem, directPlayProfile);
|
|
|
|
|
BuildStreamVideoItem(playlistItem, options, item, videoStream, audioStream, candidateAudioStreams, directPlayProfile.Container, directPlayProfile.VideoCodec, directPlayProfile.AudioCodec);
|
|
|
|
|
BuildStreamVideoItem(playlistItem, options, item, videoStream, audioStream, candidateAudioStreams, directPlayProfile?.Container, directPlayProfile?.VideoCodec, directPlayProfile?.AudioCodec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (subtitleStream is not null)
|
|
|
|
|
{
|
|
|
|
|
var subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, _transcoderSupport, directPlayProfile.Container, null);
|
|
|
|
|
var subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, _transcoderSupport, directPlayProfile?.Container, null);
|
|
|
|
|
|
|
|
|
|
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
|
|
|
|
|
playlistItem.SubtitleFormat = subtitleProfile.Format;
|
|
|
|
@ -748,7 +737,14 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return playlistItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private TranscodingProfile GetVideoTranscodeProfile(MediaSourceInfo item, MediaOptions options, MediaStream videoStream, MediaStream audioStream, IEnumerable<MediaStream> candidateAudioStreams, MediaStream subtitleStream, StreamInfo playlistItem)
|
|
|
|
|
private TranscodingProfile? GetVideoTranscodeProfile(
|
|
|
|
|
MediaSourceInfo item,
|
|
|
|
|
MediaOptions options,
|
|
|
|
|
MediaStream? videoStream,
|
|
|
|
|
MediaStream? audioStream,
|
|
|
|
|
IEnumerable<MediaStream> candidateAudioStreams,
|
|
|
|
|
MediaStream? subtitleStream,
|
|
|
|
|
StreamInfo playlistItem)
|
|
|
|
|
{
|
|
|
|
|
if (!(item.SupportsTranscoding || item.SupportsDirectStream))
|
|
|
|
|
{
|
|
|
|
@ -795,7 +791,16 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return transcodingProfiles.FirstOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BuildStreamVideoItem(StreamInfo playlistItem, MediaOptions options, MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream, IEnumerable<MediaStream> candidateAudioStreams, string container, string videoCodec, string audioCodec)
|
|
|
|
|
private void BuildStreamVideoItem(
|
|
|
|
|
StreamInfo playlistItem,
|
|
|
|
|
MediaOptions options,
|
|
|
|
|
MediaSourceInfo item,
|
|
|
|
|
MediaStream? videoStream,
|
|
|
|
|
MediaStream? audioStream,
|
|
|
|
|
IEnumerable<MediaStream> candidateAudioStreams,
|
|
|
|
|
string? container,
|
|
|
|
|
string? videoCodec,
|
|
|
|
|
string? audioCodec)
|
|
|
|
|
{
|
|
|
|
|
// Prefer matching video codecs
|
|
|
|
|
var videoCodecs = ContainerProfile.SplitValue(videoCodec);
|
|
|
|
@ -862,12 +867,12 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
int? bitDepth = videoStream?.BitDepth;
|
|
|
|
|
int? videoBitrate = videoStream?.BitRate;
|
|
|
|
|
double? videoLevel = videoStream?.Level;
|
|
|
|
|
string videoProfile = videoStream?.Profile;
|
|
|
|
|
string videoRangeType = videoStream?.VideoRangeType;
|
|
|
|
|
string? videoProfile = videoStream?.Profile;
|
|
|
|
|
string? videoRangeType = videoStream?.VideoRangeType;
|
|
|
|
|
float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
|
|
|
|
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
|
|
|
|
bool? isInterlaced = videoStream?.IsInterlaced;
|
|
|
|
|
string videoCodecTag = videoStream?.CodecTag;
|
|
|
|
|
string? videoCodecTag = videoStream?.CodecTag;
|
|
|
|
|
bool? isAvc = videoStream?.IsAVC;
|
|
|
|
|
|
|
|
|
|
TransportStreamTimestamp? timestamp = videoStream is null ? TransportStreamTimestamp.None : item.Timestamp;
|
|
|
|
@ -903,11 +908,11 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate);
|
|
|
|
|
|
|
|
|
|
bool? isSecondaryAudio = audioStream is null ? null : item.IsSecondaryAudio(audioStream);
|
|
|
|
|
int? inputAudioBitrate = audioStream is null ? null : audioStream.BitRate;
|
|
|
|
|
int? audioChannels = audioStream is null ? null : audioStream.Channels;
|
|
|
|
|
string audioProfile = audioStream is null ? null : audioStream.Profile;
|
|
|
|
|
int? inputAudioSampleRate = audioStream is null ? null : audioStream.SampleRate;
|
|
|
|
|
int? inputAudioBitDepth = audioStream is null ? null : audioStream.BitDepth;
|
|
|
|
|
int? inputAudioBitrate = audioStream?.BitRate;
|
|
|
|
|
int? audioChannels = audioStream?.Channels;
|
|
|
|
|
string? audioProfile = audioStream?.Profile;
|
|
|
|
|
int? inputAudioSampleRate = audioStream?.SampleRate;
|
|
|
|
|
int? inputAudioBitDepth = audioStream?.BitDepth;
|
|
|
|
|
|
|
|
|
|
var appliedAudioConditions = options.Profile.CodecProfiles
|
|
|
|
|
.Where(i => i.Type == CodecType.VideoAudio &&
|
|
|
|
@ -955,7 +960,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
playlistItem?.TranscodeReasons);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int GetDefaultAudioBitrate(string audioCodec, int? audioChannels)
|
|
|
|
|
private static int GetDefaultAudioBitrate(string? audioCodec, int? audioChannels)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(audioCodec))
|
|
|
|
|
{
|
|
|
|
@ -988,9 +993,9 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return 192000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int GetAudioBitrate(long maxTotalBitrate, string[] targetAudioCodecs, MediaStream audioStream, StreamInfo item)
|
|
|
|
|
private static int GetAudioBitrate(long maxTotalBitrate, string[] targetAudioCodecs, MediaStream? audioStream, StreamInfo item)
|
|
|
|
|
{
|
|
|
|
|
string targetAudioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0];
|
|
|
|
|
string? targetAudioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0];
|
|
|
|
|
|
|
|
|
|
int? targetAudioChannels = item.GetTargetAudioChannels(targetAudioCodec);
|
|
|
|
|
|
|
|
|
@ -1081,13 +1086,13 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return 7168000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private (DirectPlayProfile Profile, PlayMethod? PlayMethod, int? AudioStreamIndex, TranscodeReason TranscodeReasons) GetVideoDirectPlayProfile(
|
|
|
|
|
private (DirectPlayProfile? Profile, PlayMethod? PlayMethod, int? AudioStreamIndex, TranscodeReason TranscodeReasons) GetVideoDirectPlayProfile(
|
|
|
|
|
MediaOptions options,
|
|
|
|
|
MediaSourceInfo mediaSource,
|
|
|
|
|
MediaStream videoStream,
|
|
|
|
|
MediaStream audioStream,
|
|
|
|
|
MediaStream? videoStream,
|
|
|
|
|
MediaStream? audioStream,
|
|
|
|
|
ICollection<MediaStream> candidateAudioStreams,
|
|
|
|
|
MediaStream subtitleStream,
|
|
|
|
|
MediaStream? subtitleStream,
|
|
|
|
|
bool isEligibleForDirectPlay,
|
|
|
|
|
bool isEligibleForDirectStream)
|
|
|
|
|
{
|
|
|
|
@ -1110,12 +1115,12 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
int? bitDepth = videoStream?.BitDepth;
|
|
|
|
|
int? videoBitrate = videoStream?.BitRate;
|
|
|
|
|
double? videoLevel = videoStream?.Level;
|
|
|
|
|
string videoProfile = videoStream?.Profile;
|
|
|
|
|
string videoRangeType = videoStream?.VideoRangeType;
|
|
|
|
|
string? videoProfile = videoStream?.Profile;
|
|
|
|
|
string? videoRangeType = videoStream?.VideoRangeType;
|
|
|
|
|
float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
|
|
|
|
|
bool? isAnamorphic = videoStream?.IsAnamorphic;
|
|
|
|
|
bool? isInterlaced = videoStream?.IsInterlaced;
|
|
|
|
|
string videoCodecTag = videoStream?.CodecTag;
|
|
|
|
|
string? videoCodecTag = videoStream?.CodecTag;
|
|
|
|
|
bool? isAvc = videoStream?.IsAVC;
|
|
|
|
|
|
|
|
|
|
TransportStreamTimestamp? timestamp = videoStream is null ? TransportStreamTimestamp.None : mediaSource.Timestamp;
|
|
|
|
@ -1203,14 +1208,14 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check video codec
|
|
|
|
|
string videoCodec = videoStream?.Codec;
|
|
|
|
|
string? videoCodec = videoStream?.Codec;
|
|
|
|
|
if (!directPlayProfile.SupportsVideoCodec(videoCodec))
|
|
|
|
|
{
|
|
|
|
|
directPlayProfileReasons |= TranscodeReason.VideoCodecNotSupported;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check audio codec
|
|
|
|
|
MediaStream selectedAudioStream = null;
|
|
|
|
|
MediaStream? selectedAudioStream = null;
|
|
|
|
|
if (candidateAudioStreams.Any())
|
|
|
|
|
{
|
|
|
|
|
selectedAudioStream = candidateAudioStreams.FirstOrDefault(audioStream => directPlayProfile.SupportsAudioCodec(audioStream.Codec));
|
|
|
|
@ -1331,8 +1336,8 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
SubtitleProfile[] subtitleProfiles,
|
|
|
|
|
PlayMethod playMethod,
|
|
|
|
|
ITranscoderSupport transcoderSupport,
|
|
|
|
|
string outputContainer,
|
|
|
|
|
string transcodingSubProtocol)
|
|
|
|
|
string? outputContainer,
|
|
|
|
|
string? transcodingSubProtocol)
|
|
|
|
|
{
|
|
|
|
|
if (!subtitleStream.IsExternal && (playMethod != PlayMethod.Transcode || !string.Equals(transcodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)))
|
|
|
|
|
{
|
|
|
|
@ -1405,7 +1410,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsSubtitleEmbedSupported(string transcodingContainer)
|
|
|
|
|
private static bool IsSubtitleEmbedSupported(string? transcodingContainer)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(transcodingContainer))
|
|
|
|
|
{
|
|
|
|
@ -1427,7 +1432,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static SubtitleProfile GetExternalSubtitleProfile(MediaSourceInfo mediaSource, MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, bool allowConversion)
|
|
|
|
|
private static SubtitleProfile? GetExternalSubtitleProfile(MediaSourceInfo mediaSource, MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, bool allowConversion)
|
|
|
|
|
{
|
|
|
|
|
foreach (var profile in subtitleProfiles)
|
|
|
|
|
{
|
|
|
|
@ -1560,7 +1565,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
private static IEnumerable<ProfileCondition> GetProfileConditionsForAudio(
|
|
|
|
|
IEnumerable<CodecProfile> codecProfiles,
|
|
|
|
|
string container,
|
|
|
|
|
string codec,
|
|
|
|
|
string? codec,
|
|
|
|
|
int? audioChannels,
|
|
|
|
|
int? audioBitrate,
|
|
|
|
|
int? audioSampleRate,
|
|
|
|
@ -1580,7 +1585,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
return conditions.Where(condition => !ConditionProcessor.IsAudioConditionSatisfied(condition, audioChannels, audioBitrate, audioSampleRate, audioBitDepth));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ApplyTranscodingConditions(StreamInfo item, IEnumerable<ProfileCondition> conditions, string qualifier, bool enableQualifiedConditions, bool enableNonQualifiedConditions)
|
|
|
|
|
private void ApplyTranscodingConditions(StreamInfo item, IEnumerable<ProfileCondition> conditions, string? qualifier, bool enableQualifiedConditions, bool enableNonQualifiedConditions)
|
|
|
|
|
{
|
|
|
|
|
foreach (ProfileCondition condition in conditions)
|
|
|
|
|
{
|
|
|
|
@ -2056,7 +2061,7 @@ namespace MediaBrowser.Model.Dlna
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check audio codec
|
|
|
|
|
string audioCodec = audioStream?.Codec;
|
|
|
|
|
string? audioCodec = audioStream?.Codec;
|
|
|
|
|
if (!profile.SupportsAudioCodec(audioCodec))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|