diff options
Diffstat (limited to 'MediaBrowser.Model/Dlna/StreamInfo.cs')
| -rw-r--r-- | MediaBrowser.Model/Dlna/StreamInfo.cs | 301 |
1 files changed, 190 insertions, 111 deletions
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 4eb1c0a8e..3977a9ab0 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Model.Dlna public string Container { get; set; } - public string Protocol { get; set; } + public string SubProtocol { get; set; } public long StartPositionTicks { get; set; } @@ -51,7 +51,7 @@ namespace MediaBrowser.Model.Dlna public int? MaxVideoBitDepth { get; set; } public int? MaxRefFrames { get; set; } - + public float? MaxFramerate { get; set; } public DeviceProfile DeviceProfile { get; set; } @@ -69,7 +69,7 @@ namespace MediaBrowser.Model.Dlna public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; } public string SubtitleFormat { get; set; } - public LiveMediaInfoResult PlaybackInfo { get; set; } + public PlaybackInfoResponse PlaybackInfo { get; set; } public string MediaSourceId { @@ -81,7 +81,8 @@ namespace MediaBrowser.Model.Dlna public bool IsDirectStream { - get { + get + { return PlayMethod == PlayMethod.DirectStream || PlayMethod == PlayMethod.DirectPlay; } @@ -89,7 +90,47 @@ namespace MediaBrowser.Model.Dlna public string ToUrl(string baseUrl, string accessToken) { - return ToDlnaUrl(baseUrl, accessToken); + if (PlayMethod == PlayMethod.DirectPlay) + { + return MediaSource.Path; + } + + if (string.IsNullOrEmpty(baseUrl)) + { + throw new ArgumentNullException(baseUrl); + } + + List<string> list = new List<string>(); + foreach (NameValuePair pair in BuildParams(this, accessToken)) + { + if (string.IsNullOrEmpty(pair.Value)) + { + continue; + } + + // Try to keep the url clean by omitting defaults + if (StringHelper.EqualsIgnoreCase(pair.Name, "StartTimeTicks") && + StringHelper.EqualsIgnoreCase(pair.Value, "0")) + { + continue; + } + if (StringHelper.EqualsIgnoreCase(pair.Name, "SubtitleStreamIndex") && + StringHelper.EqualsIgnoreCase(pair.Value, "-1")) + { + continue; + } + if (StringHelper.EqualsIgnoreCase(pair.Name, "Static") && + StringHelper.EqualsIgnoreCase(pair.Value, "false")) + { + continue; + } + + list.Add(string.Format("{0}={1}", pair.Name, pair.Value)); + } + + string queryString = string.Join("&", list.ToArray()); + + return GetUrl(baseUrl, queryString); } public string ToDlnaUrl(string baseUrl, string accessToken) @@ -99,115 +140,111 @@ namespace MediaBrowser.Model.Dlna return MediaSource.Path; } + string dlnaCommand = BuildDlnaParam(this, accessToken); + return GetUrl(baseUrl, dlnaCommand); + } + + private string GetUrl(string baseUrl, string queryString) + { if (string.IsNullOrEmpty(baseUrl)) { throw new ArgumentNullException(baseUrl); } - string dlnaCommand = BuildDlnaParam(this); - string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container; baseUrl = baseUrl.TrimEnd('/'); if (MediaType == DlnaProfileType.Audio) { - return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand); + return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } - if (StringHelper.EqualsIgnoreCase(Protocol, "hls")) + if (StringHelper.EqualsIgnoreCase(SubProtocol, "hls")) { - return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, dlnaCommand); + return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand); + return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } - private static string BuildDlnaParam(StreamInfo item) + private static string BuildDlnaParam(StreamInfo item, string accessToken) { - List<string> list = new List<string> - { - item.DeviceProfileId ?? string.Empty, - item.DeviceId ?? string.Empty, - item.MediaSourceId ?? string.Empty, - (item.IsDirectStream).ToString().ToLower(), - item.VideoCodec ?? string.Empty, - item.AudioCodec ?? string.Empty, - item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty, - item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty, - item.VideoBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoBitrate.Value) : string.Empty, - item.AudioBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioBitrate.Value) : string.Empty, - item.MaxAudioChannels.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxAudioChannels.Value) : string.Empty, - item.MaxFramerate.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxFramerate.Value) : string.Empty, - item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty, - item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty, - StringHelper.ToStringCultureInvariant(item.StartPositionTicks), - item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : string.Empty - }; + List<string> list = new List<string>(); - list.Add(item.IsDirectStream ? string.Empty : DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture)); - list.Add(item.MaxRefFrames.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxRefFrames.Value) : string.Empty); - list.Add(item.MaxVideoBitDepth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxVideoBitDepth.Value) : string.Empty); - list.Add(item.VideoProfile ?? string.Empty); - list.Add(item.Cabac.HasValue ? item.Cabac.Value.ToString() : string.Empty); + foreach (NameValuePair pair in BuildParams(item, accessToken)) + { + list.Add(pair.Value); + } - string streamId = item.PlaybackInfo == null ? null : item.PlaybackInfo.StreamId; - list.Add(streamId ?? string.Empty); - return string.Format("Params={0}", string.Join(";", list.ToArray())); } - public List<SubtitleStreamInfo> GetExternalSubtitles(bool includeSelectedTrackOnly) - { - List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>(); + private static List<NameValuePair> BuildParams(StreamInfo item, string accessToken) + { + List<NameValuePair> list = new List<NameValuePair>(); + + 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().ToLower())); + list.Add(new NameValuePair("VideoCodec", item.VideoCodec ?? string.Empty)); + list.Add(new NameValuePair("AudioCodec", item.AudioCodec ?? string.Empty)); + list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty)); + list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty)); + list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoBitrate.Value) : string.Empty)); + list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioBitrate.Value) : string.Empty)); + list.Add(new NameValuePair("MaxAudioChannels", item.MaxAudioChannels.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxAudioChannels.Value) : string.Empty)); + list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxFramerate.Value) : string.Empty)); + list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); + list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); + list.Add(new NameValuePair("StartTimeTicks", StringHelper.ToStringCultureInvariant(item.StartPositionTicks))); + list.Add(new NameValuePair("Level", item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : string.Empty)); + + list.Add(new NameValuePair("ClientTime", item.IsDirectStream ? string.Empty : DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture))); + list.Add(new NameValuePair("MaxRefFrames", item.MaxRefFrames.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxRefFrames.Value) : string.Empty)); + list.Add(new NameValuePair("MaxVideoBitDepth", item.MaxVideoBitDepth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxVideoBitDepth.Value) : string.Empty)); + list.Add(new NameValuePair("Profile", item.VideoProfile ?? string.Empty)); + list.Add(new NameValuePair("Cabac", item.Cabac.HasValue ? item.Cabac.Value.ToString() : string.Empty)); + + string playSessionId = item.PlaybackInfo == null ? null : item.PlaybackInfo.PlaySessionId; + list.Add(new NameValuePair("PlaySessionId", playSessionId ?? string.Empty)); + list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); + + string liveStreamId = item.MediaSource == null ? null : item.MediaSource.LiveStreamId; + list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); - // First add the selected track - if (SubtitleStreamIndex.HasValue) - { - foreach (MediaStream stream in MediaSource.MediaStreams) - { - if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) - { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream); + return list; + } - if (info != null) - { - list.Add(info); - } - } - } - } + public List<SubtitleStreamInfo> GetExternalSubtitles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + { + List<SubtitleStreamInfo> list = GetSubtitleProfiles(includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); + List<SubtitleStreamInfo> newList = new List<SubtitleStreamInfo>(); - if (!includeSelectedTrackOnly) + // First add the selected track + foreach (SubtitleStreamInfo stream in list) { - foreach (MediaStream stream in MediaSource.MediaStreams) + if (stream.DeliveryMethod == SubtitleDeliveryMethod.External) { - if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) - { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream); - - if (info != null) - { - list.Add(info); - } - } + newList.Add(stream); } } - return list; + return newList; } - public List<SubtitleStreamInfo> GetExternalSubtitles(string baseUrl, string accessToken, bool includeSelectedTrackOnly) + public List<SubtitleStreamInfo> GetSubtitleProfiles(bool includeSelectedTrackOnly, string baseUrl, string accessToken) { - if (string.IsNullOrEmpty(baseUrl)) - { - throw new ArgumentNullException(baseUrl); - } + return GetSubtitleProfiles(includeSelectedTrackOnly, false, baseUrl, accessToken); + } + public List<SubtitleStreamInfo> GetSubtitleProfiles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + { List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>(); // HLS will preserve timestamps so we can just grab the full subtitle stream - long startPositionTicks = StringHelper.EqualsIgnoreCase(Protocol, "hls") + long startPositionTicks = StringHelper.EqualsIgnoreCase(SubProtocol, "hls") ? 0 : StartPositionTicks; @@ -218,12 +255,7 @@ namespace MediaBrowser.Model.Dlna { if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks); - - if (info != null) - { - list.Add(info); - } + AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks); } } } @@ -234,54 +266,65 @@ namespace MediaBrowser.Model.Dlna { if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks); - - if (info != null) - { - list.Add(info); - } + AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks); } } } - + return list; } - private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks) + private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream); - - if (info != null) + if (enableAllProfiles) { - info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", - baseUrl, - ItemId, - MediaSourceId, - StringHelper.ToStringCultureInvariant(stream.Index), - StringHelper.ToStringCultureInvariant(startPositionTicks), - SubtitleFormat); + foreach (SubtitleProfile profile in DeviceProfile.SubtitleProfiles) + { + SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }); + + list.Add(info); + } } + else + { + SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles); - return info; + list.Add(info); + } } - private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream) + private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles) { - SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, DeviceProfile.SubtitleProfiles, Context); - - if (subtitleProfile.Method != SubtitleDeliveryMethod.External) - { - return null; - } - - return new SubtitleStreamInfo + SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, Context); + SubtitleStreamInfo info = new SubtitleStreamInfo { IsForced = stream.IsForced, Language = stream.Language, Name = stream.Language ?? "Unknown", - Format = SubtitleFormat, - Index = stream.Index + Format = subtitleProfile.Format, + Index = stream.Index, + DeliveryMethod = subtitleProfile.Method }; + + if (info.DeliveryMethod == SubtitleDeliveryMethod.External) + { + if (MediaSource.Protocol == MediaProtocol.File || !StringHelper.EqualsIgnoreCase(stream.Codec, subtitleProfile.Format)) + { + info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", + baseUrl, + ItemId, + MediaSourceId, + StringHelper.ToStringCultureInvariant(stream.Index), + StringHelper.ToStringCultureInvariant(startPositionTicks), + subtitleProfile.Format); + } + else + { + info.Url = stream.Path; + } + } + + return info; } /// <summary> @@ -613,6 +656,42 @@ namespace MediaBrowser.Model.Dlna } } + public int? TargetVideoStreamCount + { + get + { + if (IsDirectStream) + { + return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue); + } + return GetMediaStreamCount(MediaStreamType.Video, 1); + } + } + + public int? TargetAudioStreamCount + { + get + { + if (IsDirectStream) + { + return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue); + } + return GetMediaStreamCount(MediaStreamType.Audio, 1); + } + } + + private int? GetMediaStreamCount(MediaStreamType type, int limit) + { + var count = MediaSource.GetStreamCount(type); + + if (count.HasValue) + { + count = Math.Min(count.Value, limit); + } + + return count; + } + public List<MediaStream> GetSelectableAudioStreams() { return GetSelectableStreams(MediaStreamType.Audio); |
