diff options
Diffstat (limited to 'MediaBrowser.Model/Dlna/StreamInfo.cs')
| -rw-r--r-- | MediaBrowser.Model/Dlna/StreamInfo.cs | 324 |
1 files changed, 203 insertions, 121 deletions
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index e44152213..f9aab2d67 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -1,7 +1,12 @@ +#pragma warning disable CA1819 // Properties should not return arrays + using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; +using System.Text; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -871,202 +876,279 @@ public class StreamInfo /// </summary> /// <param name="baseUrl">The base Url.</param> /// <param name="accessToken">The access Token.</param> + /// <param name="query">Optional extra query.</param> /// <returns>A querystring representation of this object.</returns> - public string ToUrl(string baseUrl, string? accessToken) + public string ToUrl(string? baseUrl, string? accessToken, string? query) { - ArgumentException.ThrowIfNullOrEmpty(baseUrl); + var sb = new StringBuilder(); + if (!string.IsNullOrEmpty(baseUrl)) + { + sb.Append(baseUrl.TrimEnd('/')); + } - List<string> list = []; - foreach (NameValuePair pair in BuildParams(this, accessToken)) + if (MediaType == DlnaProfileType.Audio) { - if (string.IsNullOrEmpty(pair.Value)) - { - continue; - } + sb.Append("/audio/"); + } + else + { + sb.Append("/videos/"); + } - // Try to keep the url clean by omitting defaults - if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) - && string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) - { - continue; - } + sb.Append(ItemId); - if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) - && string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) - { - continue; - } + if (SubProtocol == MediaStreamProtocol.hls) + { + sb.Append("/master.m3u8?"); + } + else + { + sb.Append("/stream"); - if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) - && string.Equals(pair.Value, "false", StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(Container)) { - continue; + sb.Append('.'); + sb.Append(Container); } - var encodedValue = pair.Value.Replace(" ", "%20", StringComparison.Ordinal); + sb.Append('?'); + } + + if (!string.IsNullOrEmpty(DeviceProfileId)) + { + sb.Append("&DeviceProfileId="); + sb.Append(DeviceProfileId); + } - list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); + if (!string.IsNullOrEmpty(DeviceId)) + { + sb.Append("&DeviceId="); + sb.Append(DeviceId); } - string queryString = string.Join('&', list); + if (!string.IsNullOrEmpty(MediaSourceId)) + { + sb.Append("&MediaSourceId="); + sb.Append(MediaSourceId); + } - return GetUrl(baseUrl, queryString); - } + // default true so don't store. + if (IsDirectStream) + { + sb.Append("&Static=true"); + } - private string GetUrl(string baseUrl, string queryString) - { - ArgumentException.ThrowIfNullOrEmpty(baseUrl); + if (VideoCodecs.Count != 0) + { + sb.Append("&VideoCodec="); + sb.AppendJoin(',', VideoCodecs); + } - string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container; + if (AudioCodecs.Count != 0) + { + sb.Append("&AudioCodec="); + sb.AppendJoin(',', AudioCodecs); + } - baseUrl = baseUrl.TrimEnd('/'); + if (AudioStreamIndex.HasValue) + { + sb.Append("&AudioStreamIndex="); + sb.Append(AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture)); + } - if (MediaType == DlnaProfileType.Audio) + if (SubtitleStreamIndex.HasValue && SubtitleDeliveryMethod != SubtitleDeliveryMethod.External && SubtitleStreamIndex != -1) { - if (SubProtocol == MediaStreamProtocol.hls) - { - return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); - } + sb.Append("&SubtitleStreamIndex="); + sb.Append(SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture)); + sb.Append("&SubtitleMethod="); + sb.Append(SubtitleDeliveryMethod.ToString()); + } - return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + if (VideoBitrate.HasValue) + { + sb.Append("&VideoBitrate="); + sb.Append(VideoBitrate.Value.ToString(CultureInfo.InvariantCulture)); } - if (SubProtocol == MediaStreamProtocol.hls) + if (AudioBitrate.HasValue) { - return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + sb.Append("&AudioBitrate="); + sb.Append(AudioBitrate.Value.ToString(CultureInfo.InvariantCulture)); } - return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); - } + if (AudioSampleRate.HasValue) + { + sb.Append("&AudioSampleRate="); + sb.Append(AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture)); + } - private static List<NameValuePair> BuildParams(StreamInfo item, string? accessToken) - { - List<NameValuePair> list = []; + if (MaxFramerate.HasValue) + { + sb.Append("&MaxFramerate="); + sb.Append(MaxFramerate.Value.ToString(CultureInfo.InvariantCulture)); + } - string audioCodecs = item.AudioCodecs.Count == 0 ? - string.Empty : - string.Join(',', item.AudioCodecs); + if (MaxWidth.HasValue) + { + sb.Append("&MaxWidth="); + sb.Append(MaxWidth.Value.ToString(CultureInfo.InvariantCulture)); + } - string videoCodecs = item.VideoCodecs.Count == 0 ? - string.Empty : - string.Join(',', item.VideoCodecs); + if (MaxHeight.HasValue) + { + sb.Append("&MaxHeight="); + sb.Append(MaxHeight.Value.ToString(CultureInfo.InvariantCulture)); + } - list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); - list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); - list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty)); - list.Add(new NameValuePair("Static", item.IsDirectStream.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - list.Add(new NameValuePair("VideoCodec", videoCodecs)); - list.Add(new NameValuePair("AudioCodec", audioCodecs)); - list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && (item.AlwaysBurnInSubtitleWhenTranscoding || item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + if (SubProtocol == MediaStreamProtocol.hls) + { + if (!string.IsNullOrEmpty(Container)) + { + sb.Append("&SegmentContainer="); + sb.Append(Container); + } - list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + if (SegmentLength.HasValue) + { + sb.Append("&SegmentLength="); + sb.Append(SegmentLength.Value.ToString(CultureInfo.InvariantCulture)); + } - long startPositionTicks = item.StartPositionTicks; + if (MinSegments.HasValue) + { + sb.Append("&MinSegments="); + sb.Append(MinSegments.Value.ToString(CultureInfo.InvariantCulture)); + } - if (item.SubProtocol == MediaStreamProtocol.hls) - { - list.Add(new NameValuePair("StartTimeTicks", string.Empty)); + sb.Append("&BreakOnNonKeyFrames="); + sb.Append(BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCulture)); } else { - list.Add(new NameValuePair("StartTimeTicks", startPositionTicks.ToString(CultureInfo.InvariantCulture))); + if (StartPositionTicks != 0) + { + sb.Append("&StartTimeTicks="); + sb.Append(StartPositionTicks.ToString(CultureInfo.InvariantCulture)); + } } - list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); - list.Add(new NameValuePair("ApiKey", accessToken ?? string.Empty)); + if (!string.IsNullOrEmpty(PlaySessionId)) + { + sb.Append("&PlaySessionId="); + sb.Append(PlaySessionId); + } - string? liveStreamId = item.MediaSource?.LiveStreamId; - list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); + if (!string.IsNullOrEmpty(accessToken)) + { + sb.Append("&ApiKey="); + sb.Append(accessToken); + } - list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); + var liveStreamId = MediaSource?.LiveStreamId; + if (!string.IsNullOrEmpty(liveStreamId)) + { + sb.Append("&LiveStreamId="); + sb.Append(liveStreamId); + } - if (!item.IsDirectStream) + if (!IsDirectStream) { - if (item.RequireNonAnamorphic) + if (RequireNonAnamorphic) { - list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + sb.Append("&RequireNonAnamorphic="); + sb.Append(RequireNonAnamorphic.ToString(CultureInfo.InvariantCulture)); } - list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? item.TranscodingMaxAudioChannels.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - if (item.EnableSubtitlesInManifest) + if (TranscodingMaxAudioChannels.HasValue) { - list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + sb.Append("&TranscodingMaxAudioChannels="); + sb.Append(TranscodingMaxAudioChannels.Value.ToString(CultureInfo.InvariantCulture)); } - if (item.EnableMpegtsM2TsMode) + if (EnableSubtitlesInManifest) { - list.Add(new NameValuePair("EnableMpegtsM2TsMode", item.EnableMpegtsM2TsMode.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + sb.Append("&EnableSubtitlesInManifest="); + sb.Append(EnableSubtitlesInManifest.ToString(CultureInfo.InvariantCulture)); } - if (item.EstimateContentLength) + if (EnableMpegtsM2TsMode) { - list.Add(new NameValuePair("EstimateContentLength", item.EstimateContentLength.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + sb.Append("&EnableMpegtsM2TsMode="); + sb.Append(EnableMpegtsM2TsMode.ToString(CultureInfo.InvariantCulture)); } - if (item.TranscodeSeekInfo != TranscodeSeekInfo.Auto) + if (EstimateContentLength) { - list.Add(new NameValuePair("TranscodeSeekInfo", item.TranscodeSeekInfo.ToString().ToLowerInvariant())); + sb.Append("&EstimateContentLength="); + sb.Append(EstimateContentLength.ToString(CultureInfo.InvariantCulture)); } - if (item.CopyTimestamps) + if (TranscodeSeekInfo != TranscodeSeekInfo.Auto) { - list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + sb.Append("&TranscodeSeekInfo="); + sb.Append(TranscodeSeekInfo.ToString()); } - list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - - list.Add(new NameValuePair("EnableAudioVbrEncoding", item.EnableAudioVbrEncoding.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - list.Add(new NameValuePair("Tag", item.MediaSource?.ETag ?? string.Empty)); - - string subtitleCodecs = item.SubtitleCodecs.Count == 0 ? - string.Empty : - string.Join(",", item.SubtitleCodecs); - - list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); - - if (item.SubProtocol == MediaStreamProtocol.hls) - { - list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty)); + if (CopyTimestamps) + { + sb.Append("&CopyTimestamps="); + sb.Append(CopyTimestamps.ToString(CultureInfo.InvariantCulture)); + } - if (item.SegmentLength.HasValue) + if (RequireAvc) { - list.Add(new NameValuePair("SegmentLength", item.SegmentLength.Value.ToString(CultureInfo.InvariantCulture))); + sb.Append("&RequireAvc="); + sb.Append(RequireAvc.ToString(CultureInfo.InvariantCulture)); } - if (item.MinSegments.HasValue) + if (EnableAudioVbrEncoding) { - list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture))); + sb.Append("EnableAudioVbrEncoding="); + sb.Append(EnableAudioVbrEncoding.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); } + } - list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCulture))); + var etag = MediaSource?.ETag; + if (!string.IsNullOrEmpty(etag)) + { + sb.Append("&Tag="); + sb.Append(etag); } - foreach (var pair in item.StreamOptions) + if (SubtitleStreamIndex.HasValue && SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) { - if (string.IsNullOrEmpty(pair.Value)) - { - continue; - } + sb.Append("&SubtitleMethod="); + sb.AppendJoin(',', SubtitleDeliveryMethod); + } - // strip spaces to avoid having to encode h264 profile names - list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty, StringComparison.Ordinal))); + if (SubtitleStreamIndex.HasValue && SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed && SubtitleCodecs.Count != 0) + { + sb.Append("&SubtitleCodec="); + sb.AppendJoin(',', SubtitleCodecs); } - if (!item.IsDirectStream) + foreach (var pair in StreamOptions) { - list.Add(new NameValuePair("TranscodeReasons", item.TranscodeReasons.ToString())); + // Strip spaces to avoid having to encode h264 profile names + sb.Append('&'); + sb.Append(pair.Key); + sb.Append('='); + sb.Append(pair.Value.Replace(" ", string.Empty, StringComparison.Ordinal)); } - return list; + var transcodeReasonsValues = TranscodeReasons.GetUniqueFlags().ToArray(); + if (!IsDirectStream && transcodeReasonsValues.Length > 0) + { + sb.Append("&TranscodeReasons="); + sb.AppendJoin(',', transcodeReasonsValues); + } + + if (!string.IsNullOrEmpty(query)) + { + sb.Append(query); + } + + return sb.ToString(); } /// <summary> |
