|
@@ -1427,13 +1427,12 @@ namespace MediaBrowser.Api.Playback
|
|
}
|
|
}
|
|
else if (item is IChannelMediaItem)
|
|
else if (item is IChannelMediaItem)
|
|
{
|
|
{
|
|
- var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(request.Id, CancellationToken.None).ConfigureAwait(false);
|
|
|
|
-
|
|
|
|
- var source = channelMediaSources.First();
|
|
|
|
|
|
+ var source = await GetChannelMediaInfo(request.Id, CancellationToken.None).ConfigureAwait(false);
|
|
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
|
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
|
state.IsRemote = source.IsRemote;
|
|
state.IsRemote = source.IsRemote;
|
|
state.MediaPath = source.Path;
|
|
state.MediaPath = source.Path;
|
|
state.RunTimeTicks = item.RunTimeTicks;
|
|
state.RunTimeTicks = item.RunTimeTicks;
|
|
|
|
+ mediaStreams = GetMediaStreams(source).ToList();
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -1479,28 +1478,7 @@ namespace MediaBrowser.Api.Playback
|
|
|
|
|
|
}).ToList();
|
|
}).ToList();
|
|
|
|
|
|
- if (videoRequest != null)
|
|
|
|
- {
|
|
|
|
- if (string.IsNullOrEmpty(videoRequest.VideoCodec))
|
|
|
|
- {
|
|
|
|
- videoRequest.VideoCodec = InferVideoCodec(url);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
|
|
|
|
- state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
|
|
|
|
- state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
|
|
|
|
-
|
|
|
|
- if (state.VideoStream != null && state.VideoStream.IsInterlaced)
|
|
|
|
- {
|
|
|
|
- state.DeInterlace = true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- EnforceResolutionLimit(state, videoRequest);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
|
|
|
|
- }
|
|
|
|
|
|
+ AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);
|
|
|
|
|
|
state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
|
|
state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
|
|
state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
|
|
state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
|
|
@@ -1538,6 +1516,96 @@ namespace MediaBrowser.Api.Playback
|
|
return state;
|
|
return state;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private void AttachMediaStreamInfo(StreamState state,
|
|
|
|
+ List<MediaStream> mediaStreams,
|
|
|
|
+ VideoStreamRequest videoRequest,
|
|
|
|
+ string requestedUrl)
|
|
|
|
+ {
|
|
|
|
+ if (videoRequest != null)
|
|
|
|
+ {
|
|
|
|
+ if (string.IsNullOrEmpty(videoRequest.VideoCodec))
|
|
|
|
+ {
|
|
|
|
+ videoRequest.VideoCodec = InferVideoCodec(requestedUrl);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
|
|
|
|
+ state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
|
|
|
|
+ state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
|
|
|
|
+
|
|
|
|
+ if (state.VideoStream != null && state.VideoStream.IsInterlaced)
|
|
|
|
+ {
|
|
|
|
+ state.DeInterlace = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ EnforceResolutionLimit(state, videoRequest);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private IEnumerable<MediaStream> GetMediaStreams(ChannelMediaInfo info)
|
|
|
|
+ {
|
|
|
|
+ var list = new List<MediaStream>();
|
|
|
|
+
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(info.VideoCodec) &&
|
|
|
|
+ !string.IsNullOrWhiteSpace(info.AudioCodec))
|
|
|
|
+ {
|
|
|
|
+ list.Add(new MediaStream
|
|
|
|
+ {
|
|
|
|
+ Type = MediaStreamType.Video,
|
|
|
|
+ Width = info.Width,
|
|
|
|
+ RealFrameRate = info.Framerate,
|
|
|
|
+ Profile = info.VideoProfile,
|
|
|
|
+ Level = info.VideoLevel,
|
|
|
|
+ Index = -1,
|
|
|
|
+ Height = info.Height,
|
|
|
|
+ Codec = info.VideoCodec,
|
|
|
|
+ BitRate = info.VideoBitrate,
|
|
|
|
+ AverageFrameRate = info.Framerate
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ list.Add(new MediaStream
|
|
|
|
+ {
|
|
|
|
+ Type = MediaStreamType.Audio,
|
|
|
|
+ Index = -1,
|
|
|
|
+ Codec = info.AudioCodec,
|
|
|
|
+ BitRate = info.AudioBitrate,
|
|
|
|
+ Channels = info.AudioChannels,
|
|
|
|
+ SampleRate = info.AudioSampleRate
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private async Task<ChannelMediaInfo> GetChannelMediaInfo(string id, CancellationToken cancellationToken)
|
|
|
|
+ {
|
|
|
|
+ var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(id, cancellationToken)
|
|
|
|
+ .ConfigureAwait(false);
|
|
|
|
+
|
|
|
|
+ var list = channelMediaSources.ToList();
|
|
|
|
+
|
|
|
|
+ var preferredWidth = ServerConfigurationManager.Configuration.ChannelOptions.PreferredStreamingWidth;
|
|
|
|
+
|
|
|
|
+ if (preferredWidth.HasValue)
|
|
|
|
+ {
|
|
|
|
+ var val = preferredWidth.Value;
|
|
|
|
+
|
|
|
|
+ return list
|
|
|
|
+ .OrderBy(i => Math.Abs(i.Width ?? 0 - val))
|
|
|
|
+ .ThenByDescending(i => i.Width ?? 0)
|
|
|
|
+ .ThenBy(list.IndexOf)
|
|
|
|
+ .First();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return list
|
|
|
|
+ .OrderByDescending(i => i.Width ?? 0)
|
|
|
|
+ .ThenBy(list.IndexOf)
|
|
|
|
+ .First();
|
|
|
|
+ }
|
|
|
|
+
|
|
private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
|
private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
|
{
|
|
{
|
|
if (videoStream.IsInterlaced)
|
|
if (videoStream.IsInterlaced)
|