diff options
Diffstat (limited to 'MediaBrowser.Model/Dlna/StreamBuilder.cs')
| -rw-r--r-- | MediaBrowser.Model/Dlna/StreamBuilder.cs | 374 |
1 files changed, 195 insertions, 179 deletions
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index af35e98ee..00c3234dd 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1,5 +1,4 @@ #nullable disable -#pragma warning disable CS1591 using System; using System.Collections.Generic; @@ -13,6 +12,9 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Model.Dlna { + /// <summary> + /// Class StreamBuilder. + /// </summary> public class StreamBuilder { // Aliases @@ -24,35 +26,49 @@ namespace MediaBrowser.Model.Dlna private readonly ILogger _logger; private readonly ITranscoderSupport _transcoderSupport; + /// <summary> + /// Initializes a new instance of the <see cref="StreamBuilder"/> class. + /// </summary> + /// <param name="transcoderSupport">The <see cref="ITranscoderSupport"/> object.</param> + /// <param name="logger">The <see cref="ILogger"/> object.</param> public StreamBuilder(ITranscoderSupport transcoderSupport, ILogger logger) { _transcoderSupport = transcoderSupport; _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) { } - public StreamInfo BuildAudioItem(AudioOptions options) + /// <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) { - ValidateAudioInput(options); + ValidateMediaOptions(options, false); var mediaSources = new List<MediaSourceInfo>(); - foreach (MediaSourceInfo i in options.MediaSources) + foreach (var mediaSource in options.MediaSources) { if (string.IsNullOrEmpty(options.MediaSourceId) || - string.Equals(i.Id, options.MediaSourceId, StringComparison.OrdinalIgnoreCase)) + string.Equals(mediaSource.Id, options.MediaSourceId, StringComparison.OrdinalIgnoreCase)) { - mediaSources.Add(i); + mediaSources.Add(mediaSource); } } var streams = new List<StreamInfo>(); foreach (MediaSourceInfo i in mediaSources) { - StreamInfo streamInfo = BuildAudioItem(i, options); + StreamInfo streamInfo = GetOptimalAudioStream(i, options); if (streamInfo is not null) { streams.Add(streamInfo); @@ -68,9 +84,115 @@ namespace MediaBrowser.Model.Dlna return GetOptimalStream(streams, options.GetMaxBitrate(true) ?? 0); } - public StreamInfo BuildVideoItem(VideoOptions options) + private StreamInfo GetOptimalAudioStream(MediaSourceInfo item, MediaOptions options) + { + var playlistItem = new StreamInfo + { + ItemId = options.ItemId, + MediaType = DlnaProfileType.Audio, + MediaSource = item, + RunTimeTicks = item.RunTimeTicks, + Context = options.Context, + DeviceProfile = options.Profile + }; + + if (options.ForceDirectPlay) + { + playlistItem.PlayMethod = PlayMethod.DirectPlay; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); + return playlistItem; + } + + if (options.ForceDirectStream) + { + playlistItem.PlayMethod = PlayMethod.DirectStream; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); + return playlistItem; + } + + MediaStream audioStream = item.GetDefaultAudioStream(null); + + var directPlayInfo = GetAudioDirectPlayProfile(item, audioStream, options); + + var directPlayMethod = directPlayInfo.PlayMethod; + var transcodeReasons = directPlayInfo.TranscodeReasons; + + var inputAudioChannels = audioStream?.Channels; + var inputAudioBitrate = audioStream?.BitDepth; + var inputAudioSampleRate = audioStream?.SampleRate; + var inputAudioBitDepth = audioStream?.BitDepth; + + if (directPlayMethod.HasValue) + { + var profile = options.Profile; + var audioFailureConditions = GetProfileConditionsForAudio(profile.CodecProfiles, item.Container, audioStream?.Codec, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, true); + var audioFailureReasons = AggregateFailureConditions(item, profile, "AudioCodecProfile", audioFailureConditions); + transcodeReasons |= audioFailureReasons; + + if (audioFailureReasons == 0) + { + playlistItem.PlayMethod = directPlayMethod.Value; + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio, directPlayInfo.Profile); + + return playlistItem; + } + } + + TranscodingProfile transcodingProfile = null; + foreach (TranscodingProfile i in options.Profile.TranscodingProfiles) + { + if (i.Type == playlistItem.MediaType + && i.Context == options.Context + && _transcoderSupport.CanEncodeToAudioCodec(i.AudioCodec ?? i.Container)) + { + transcodingProfile = i; + break; + } + } + + if (transcodingProfile != null) + { + if (!item.SupportsTranscoding) + { + return null; + } + + SetStreamInfoOptionsFromTranscodingProfile(item, playlistItem, transcodingProfile); + + var audioTranscodingConditions = GetProfileConditionsForAudio(options.Profile.CodecProfiles, transcodingProfile.Container, transcodingProfile.AudioCodec, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, false).ToArray(); + ApplyTranscodingConditions(playlistItem, audioTranscodingConditions, null, true, true); + + // Honor requested max channels + playlistItem.GlobalMaxAudioChannels = options.MaxAudioChannels; + + var configuredBitrate = options.GetMaxBitrate(true); + + long transcodingBitrate = options.AudioTranscodingBitrate ?? + (options.Context == EncodingContext.Streaming ? options.Profile.MusicStreamingTranscodingBitrate : null) ?? + configuredBitrate ?? + 128000; + + if (configuredBitrate.HasValue) + { + transcodingBitrate = Math.Min(configuredBitrate.Value, transcodingBitrate); + } + + var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate); + playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate); + } + + playlistItem.TranscodeReasons = transcodeReasons; + return playlistItem; + } + + /// <summary> + /// Gets the optimal video stream. + /// </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) { - ValidateInput(options); + ValidateMediaOptions(options, true); var mediaSources = new List<MediaSourceInfo>(); foreach (MediaSourceInfo i in options.MediaSources) @@ -236,6 +358,14 @@ namespace MediaBrowser.Model.Dlna } } + /// <summary> + /// Normalizes input container. + /// </summary> + /// <param name="inputContainer">The input container.</param> + /// <param name="profile">The <see cref="DeviceProfile"/>.</param> + /// <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) { if (string.IsNullOrEmpty(inputContainer)) @@ -264,108 +394,7 @@ namespace MediaBrowser.Model.Dlna return formats[0]; } - private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options) - { - StreamInfo playlistItem = new StreamInfo - { - ItemId = options.ItemId, - MediaType = DlnaProfileType.Audio, - MediaSource = item, - RunTimeTicks = item.RunTimeTicks, - Context = options.Context, - DeviceProfile = options.Profile - }; - - if (options.ForceDirectPlay) - { - playlistItem.PlayMethod = PlayMethod.DirectPlay; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); - return playlistItem; - } - - if (options.ForceDirectStream) - { - playlistItem.PlayMethod = PlayMethod.DirectStream; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); - return playlistItem; - } - - var audioStream = item.GetDefaultAudioStream(null); - - var directPlayInfo = GetAudioDirectPlayProfile(item, audioStream, options); - - var directPlayMethod = directPlayInfo.PlayMethod; - var transcodeReasons = directPlayInfo.TranscodeReasons; - - int? inputAudioChannels = audioStream?.Channels; - int? inputAudioBitrate = audioStream?.BitDepth; - int? inputAudioSampleRate = audioStream?.SampleRate; - int? inputAudioBitDepth = audioStream?.BitDepth; - - if (directPlayMethod.HasValue) - { - var profile = options.Profile; - var audioFailureConditions = GetProfileConditionsForAudio(profile.CodecProfiles, item.Container, audioStream?.Codec, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, true); - var audioFailureReasons = AggregateFailureConditions(item, profile, "AudioCodecProfile", audioFailureConditions); - transcodeReasons |= audioFailureReasons; - - if (audioFailureReasons == 0) - { - playlistItem.PlayMethod = directPlayMethod.Value; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio, directPlayInfo.Profile); - - return playlistItem; - } - } - - TranscodingProfile transcodingProfile = null; - foreach (var i in options.Profile.TranscodingProfiles) - { - if (i.Type == playlistItem.MediaType - && i.Context == options.Context - && _transcoderSupport.CanEncodeToAudioCodec(i.AudioCodec ?? i.Container)) - { - transcodingProfile = i; - break; - } - } - - if (transcodingProfile is not null) - { - if (!item.SupportsTranscoding) - { - return null; - } - - SetStreamInfoOptionsFromTranscodingProfile(item, playlistItem, transcodingProfile); - - var audioTranscodingConditions = GetProfileConditionsForAudio(options.Profile.CodecProfiles, transcodingProfile.Container, transcodingProfile.AudioCodec, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, false).ToArray(); - ApplyTranscodingConditions(playlistItem, audioTranscodingConditions, null, true, true); - - // Honor requested max channels - playlistItem.GlobalMaxAudioChannels = options.MaxAudioChannels; - - var configuredBitrate = options.GetMaxBitrate(true); - - long transcodingBitrate = options.AudioTranscodingBitrate ?? - (options.Context == EncodingContext.Streaming ? options.Profile.MusicStreamingTranscodingBitrate : null) ?? - configuredBitrate ?? - 128000; - - if (configuredBitrate.HasValue) - { - transcodingBitrate = Math.Min(configuredBitrate.Value, transcodingBitrate); - } - - var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate); - playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate); - } - - playlistItem.TranscodeReasons = transcodeReasons; - return playlistItem; - } - - private (DirectPlayProfile Profile, PlayMethod? PlayMethod, TranscodeReason TranscodeReasons) GetAudioDirectPlayProfile(MediaSourceInfo item, MediaStream audioStream, AudioOptions 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)); @@ -388,7 +417,7 @@ namespace MediaBrowser.Model.Dlna // If device requirements are satisfied then allow both direct stream and direct play if (item.SupportsDirectPlay) { - if (IsItemBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(true) ?? 0, PlayMethod.DirectPlay)) + if (!IsBitrateLimitExceeded(item, options.GetMaxBitrate(true) ?? 0)) { if (options.EnableDirectPlay) { @@ -404,7 +433,7 @@ namespace MediaBrowser.Model.Dlna // While options takes the network and other factors into account. Only applies to direct stream if (item.SupportsDirectStream) { - if (IsItemBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(true) ?? 0, PlayMethod.DirectStream)) + if (!IsBitrateLimitExceeded(item, options.GetMaxBitrate(true) ?? 0)) { if (options.EnableDirectStream) { @@ -427,7 +456,6 @@ namespace MediaBrowser.Model.Dlna var containerSupported = false; var audioSupported = false; var videoSupported = false; - TranscodeReason reasons = 0; foreach (var profile in directPlayProfiles) { @@ -447,6 +475,7 @@ namespace MediaBrowser.Model.Dlna } } + TranscodeReason reasons = 0; if (!containerSupported) { reasons |= TranscodeReason.ContainerNotSupported; @@ -547,7 +576,7 @@ namespace MediaBrowser.Model.Dlna } } - private static void SetStreamInfoOptionsFromDirectPlayProfile(VideoOptions 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"; @@ -562,7 +591,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.AudioCodecs = ContainerProfile.SplitValue(directPlayProfile.AudioCodec); } - private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options) + private StreamInfo BuildVideoItem(MediaSourceInfo item, MediaOptions options) { ArgumentNullException.ThrowIfNull(item); @@ -601,11 +630,15 @@ namespace MediaBrowser.Model.Dlna var videoStream = item.VideoStream; - var directPlayBitrateEligibility = IsBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectPlay); - var directStreamBitrateEligibility = IsBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectStream); - bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayBitrateEligibility == 0); - bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamBitrateEligibility == 0); - var transcodeReasons = directPlayBitrateEligibility | directStreamBitrateEligibility; + var bitrateLimitExceeded = IsBitrateLimitExceeded(item, options.GetMaxBitrate(false) ?? 0); + var isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || !bitrateLimitExceeded); + var isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || !bitrateLimitExceeded); + TranscodeReason transcodeReasons = 0; + + if (bitrateLimitExceeded) + { + transcodeReasons = TranscodeReason.ContainerBitrateExceedsLimit; + } _logger.LogDebug( "Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}", @@ -702,7 +735,7 @@ namespace MediaBrowser.Model.Dlna } } - _logger.LogInformation( + _logger.LogDebug( "StreamBuilder.BuildVideoItem( Profile={0}, Path={1}, AudioStreamIndex={2}, SubtitleStreamIndex={3} ) => ( PlayMethod={4}, TranscodeReason={5} ) {6}", options.Profile.Name ?? "Anonymous Profile", item.Path ?? "Unknown path", @@ -716,7 +749,7 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - private TranscodingProfile GetVideoTranscodeProfile(MediaSourceInfo item, VideoOptions 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)) { @@ -763,7 +796,7 @@ namespace MediaBrowser.Model.Dlna return transcodingProfiles.FirstOrDefault(); } - private void BuildStreamVideoItem(StreamInfo playlistItem, VideoOptions 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); @@ -867,7 +900,7 @@ namespace MediaBrowser.Model.Dlna // Honor requested max channels playlistItem.GlobalMaxAudioChannels = options.MaxAudioChannels; - int audioBitrate = GetAudioBitrate(options.GetMaxBitrate(false) ?? 0, playlistItem.TargetAudioCodec, audioStream, playlistItem); + int audioBitrate = GetAudioBitrate(options.GetMaxBitrate(true) ?? 0, playlistItem.TargetAudioCodec, audioStream, playlistItem); playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); bool? isSecondaryAudio = audioStream is null ? null : item.IsSecondaryAudio(audioStream); @@ -882,14 +915,14 @@ namespace MediaBrowser.Model.Dlna i.ContainsAnyCodec(audioCodec, container) && i.ApplyConditions.All(applyCondition => ConditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio))); isFirstAppliedCodecProfile = true; - foreach (var i in appliedAudioConditions) + foreach (var codecProfile in appliedAudioConditions) { var transcodingAudioCodecs = ContainerProfile.SplitValue(audioCodec); foreach (var transcodingAudioCodec in transcodingAudioCodecs) { - if (i.ContainsAnyCodec(transcodingAudioCodec, container)) + if (codecProfile.ContainsAnyCodec(transcodingAudioCodec, container)) { - ApplyTranscodingConditions(playlistItem, i.Conditions, transcodingAudioCodec, true, isFirstAppliedCodecProfile); + ApplyTranscodingConditions(playlistItem, codecProfile.Conditions, transcodingAudioCodec, true, isFirstAppliedCodecProfile); isFirstAppliedCodecProfile = false; break; } @@ -1050,7 +1083,7 @@ namespace MediaBrowser.Model.Dlna } private (DirectPlayProfile Profile, PlayMethod? PlayMethod, int? AudioStreamIndex, TranscodeReason TranscodeReasons) GetVideoDirectPlayProfile( - VideoOptions options, + MediaOptions options, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream, @@ -1237,7 +1270,7 @@ namespace MediaBrowser.Model.Dlna return (Profile: null, PlayMethod: null, AudioStreamIndex: null, TranscodeReasons: failureReasons); } - private TranscodeReason CheckVideoAudioStreamDirectPlay(VideoOptions options, MediaSourceInfo mediaSource, string container, MediaStream audioStream) + private TranscodeReason CheckVideoAudioStreamDirectPlay(MediaOptions options, MediaSourceInfo mediaSource, string container, MediaStream audioStream) { var profile = options.Profile; var audioFailureConditions = GetProfileConditionsForVideoAudio(profile.CodecProfiles, container, audioStream.Codec, audioStream.Channels, audioStream.BitRate, audioStream.SampleRate, audioStream.BitDepth, audioStream.Profile, mediaSource.IsSecondaryAudio(audioStream)); @@ -1274,23 +1307,17 @@ namespace MediaBrowser.Model.Dlna mediaSource.Path ?? "Unknown path"); } - private TranscodeReason IsBitrateEligibleForDirectPlayback( - MediaSourceInfo item, - long maxBitrate, - VideoOptions options, - PlayMethod playMethod) - { - bool result = IsItemBitrateEligibleForDirectPlayback(item, maxBitrate, playMethod); - if (!result) - { - return TranscodeReason.ContainerBitrateExceedsLimit; - } - else - { - return 0; - } - } - + /// <summary> + /// Normalizes input container. + /// </summary> + /// <param name="mediaSource">The <see cref="MediaSourceInfo"/>.</param> + /// <param name="subtitleStream">The <see cref="MediaStream"/> of the subtitle stream.</param> + /// <param name="subtitleProfiles">The list of supported <see cref="SubtitleProfile"/>s.</param> + /// <param name="playMethod">The <see cref="PlayMethod"/>.</param> + /// <param name="transcoderSupport">The <see cref="ITranscoderSupport"/>.</param> + /// <param name="outputContainer">The output container.</param> + /// <param name="transcodingSubProtocol">The subtitle transoding protocol.</param> + /// <returns>The the normalized input container.</returns> public static SubtitleProfile GetSubtitleProfile( MediaSourceInfo mediaSource, MediaStream subtitleStream, @@ -1448,14 +1475,8 @@ namespace MediaBrowser.Model.Dlna return null; } - private bool IsItemBitrateEligibleForDirectPlayback(MediaSourceInfo item, long maxBitrate, PlayMethod playMethod) + private bool IsBitrateLimitExceeded(MediaSourceInfo item, long maxBitrate) { - // Don't restrict by bitrate if coming from an external domain - if (item.IsRemote) - { - return true; - } - long requestedMaxBitrate = maxBitrate > 0 ? maxBitrate : 1000000; // If we don't know the bitrate, then force a transcode if requested max bitrate is under 40 mbps @@ -1464,40 +1485,22 @@ namespace MediaBrowser.Model.Dlna if (itemBitrate > requestedMaxBitrate) { _logger.LogDebug( - "Bitrate exceeds {PlayBackMethod} limit: media bitrate: {MediaBitrate}, max bitrate: {MaxBitrate}", - playMethod, + "Bitrate exceeds limit: media bitrate: {MediaBitrate}, max bitrate: {MaxBitrate}", itemBitrate, requestedMaxBitrate); - return false; - } - - return true; - } - - private static void ValidateInput(VideoOptions options) - { - ValidateAudioInput(options); - - if (options.AudioStreamIndex.HasValue && string.IsNullOrEmpty(options.MediaSourceId)) - { - throw new ArgumentException("MediaSourceId is required when a specific audio stream is requested"); + return true; } - if (options.SubtitleStreamIndex.HasValue && string.IsNullOrEmpty(options.MediaSourceId)) - { - throw new ArgumentException("MediaSourceId is required when a specific subtitle stream is requested"); - } + return false; } - private static void ValidateAudioInput(AudioOptions options) + private static void ValidateMediaOptions(MediaOptions options, Boolean IsMediaSource) { if (options.ItemId.Equals(default)) { - throw new ArgumentException("ItemId is required"); + ArgumentException.ThrowIfNullOrEmpty(options.DeviceId); } - ArgumentException.ThrowIfNullOrEmpty(options.DeviceId); - if (options.Profile is null) { throw new ArgumentException("Profile is required"); @@ -1507,6 +1510,19 @@ namespace MediaBrowser.Model.Dlna { throw new ArgumentException("MediaSources is required"); } + + if (IsMediaSource) + { + if (options.AudioStreamIndex.HasValue && string.IsNullOrEmpty(options.MediaSourceId)) + { + throw new ArgumentException("MediaSourceId is required when a specific audio stream is requested"); + } + + if (options.SubtitleStreamIndex.HasValue && string.IsNullOrEmpty(options.MediaSourceId)) + { + throw new ArgumentException("MediaSourceId is required when a specific subtitle stream is requested"); + } + } } private static IEnumerable<ProfileCondition> GetProfileConditionsForVideoAudio( @@ -1824,8 +1840,8 @@ namespace MediaBrowser.Model.Dlna continue; } - // change from split by | to comma - // strip spaces to avoid having to encode + // Change from split by | to comma + // Strip spaces to avoid having to encode var values = value .Split('|', StringSplitOptions.RemoveEmptyEntries); |
