diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index c188376fe6..919e51eccf 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -859,19 +859,12 @@ namespace MediaBrowser.Api.Playback state.LiveTvStreamId = streamInfo.Id; - if (!string.IsNullOrEmpty(streamInfo.Path)) - { - state.MediaPath = streamInfo.Path; - } - else if (!string.IsNullOrEmpty(streamInfo.Url)) - { - state.MediaPath = streamInfo.Url; - } + state.MediaPath = streamInfo.Path; + state.InputProtocol = streamInfo.Protocol; await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false); - - state.InputProtocol = GetProtocol(state.MediaPath); - AttachMediaStreamInfo(state, streamInfo.MediaStreams, state.VideoRequest, state.RequestedUrl); + + AttachMediaStreamInfo(state, streamInfo, state.VideoRequest, state.RequestedUrl); checkCodecs = true; } @@ -882,19 +875,12 @@ namespace MediaBrowser.Api.Playback state.LiveTvStreamId = streamInfo.Id; - if (!string.IsNullOrEmpty(streamInfo.Path)) - { - state.MediaPath = streamInfo.Path; - } - else if (!string.IsNullOrEmpty(streamInfo.Url)) - { - state.MediaPath = streamInfo.Url; - } + state.MediaPath = streamInfo.Path; + state.InputProtocol = streamInfo.Protocol; await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false); - state.InputProtocol = GetProtocol(state.MediaPath); - AttachMediaStreamInfo(state, streamInfo.MediaStreams, state.VideoRequest, state.RequestedUrl); + AttachMediaStreamInfo(state, streamInfo, state.VideoRequest, state.RequestedUrl); checkCodecs = true; } @@ -1006,7 +992,7 @@ namespace MediaBrowser.Api.Playback await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } - if (state.IsInputVideo && transcodingJob.Type == Api.TranscodingJobType.Progressive) + if (state.IsInputVideo && transcodingJob.Type == TranscodingJobType.Progressive) { await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false); @@ -1712,6 +1698,23 @@ namespace MediaBrowser.Api.Playback return state; } + private void AttachMediaStreamInfo(StreamState state, + ChannelMediaInfo mediaInfo, + VideoStreamRequest videoRequest, + string requestedUrl) + { + var mediaSource = mediaInfo.ToMediaSource(); + + state.InputProtocol = mediaSource.Protocol; + state.MediaPath = mediaSource.Path; + state.RunTimeTicks = mediaSource.RunTimeTicks; + state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; + state.InputBitrate = mediaSource.Bitrate; + state.InputFileSize = mediaSource.Size; + + AttachMediaStreamInfo(state, mediaSource.MediaStreams, videoRequest, requestedUrl); + } + private void AttachMediaStreamInfo(StreamState state, List mediaStreams, VideoStreamRequest videoRequest, diff --git a/MediaBrowser.Api/Playback/Hls/MpegDashService.cs b/MediaBrowser.Api/Playback/Hls/MpegDashService.cs index 1150220158..baa6233809 100644 --- a/MediaBrowser.Api/Playback/Hls/MpegDashService.cs +++ b/MediaBrowser.Api/Playback/Hls/MpegDashService.cs @@ -103,7 +103,9 @@ namespace MediaBrowser.Api.Playback.Hls var builder = new StringBuilder(); - var duration = "PT0H02M11.00S"; + var time = TimeSpan.FromTicks(state.RunTimeTicks.Value); + + var duration = "PT" + time.Hours.ToString("00", UsCulture) + "H" + time.Minutes.ToString("00", UsCulture) + "M" + time.Seconds.ToString("00", UsCulture) + ".00S"; builder.Append(""); builder.AppendFormat( @@ -239,16 +241,17 @@ namespace MediaBrowser.Api.Playback.Hls { var seconds = TimeSpan.FromTicks(state.RunTimeTicks ?? 0).TotalSeconds; - builder.Append(""); - var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); var index = 0; + builder.Append(""); while (seconds > 0) { - builder.AppendFormat("", index.ToString(UsCulture), SecurityElement.Escape(queryString)); + var segmentUrl = string.Format("{0}.ts{1}", index.ToString(UsCulture), SecurityElement.Escape(queryString)); + + builder.AppendFormat("", segmentUrl); seconds -= state.SegmentLength; index++; diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs index f16fd11205..64a4f355c3 100644 --- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs @@ -1,6 +1,10 @@ -using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Controller.Channels { @@ -31,6 +35,8 @@ namespace MediaBrowser.Controller.Channels public long? RunTimeTicks { get; set; } + public string Id { get; set; } + public ChannelMediaInfo() { RequiredHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -38,5 +44,67 @@ namespace MediaBrowser.Controller.Channels // This is most common Protocol = MediaProtocol.Http; } + + public MediaSourceInfo ToMediaSource() + { + var id = Path.GetMD5().ToString("N"); + + var source = new MediaSourceInfo + { + MediaStreams = GetMediaStreams(this).ToList(), + + Container = Container, + Protocol = Protocol, + Path = Path, + RequiredHttpHeaders = RequiredHttpHeaders, + RunTimeTicks = RunTimeTicks, + Name = id, + Id = id + }; + + var bitrate = (AudioBitrate ?? 0) + (VideoBitrate ?? 0); + + if (bitrate > 0) + { + source.Bitrate = bitrate; + } + + return source; + } + + private IEnumerable GetMediaStreams(ChannelMediaInfo info) + { + var list = new List(); + + 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; + } } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 370ac2e756..fcd973ec29 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dto; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; @@ -154,7 +155,7 @@ namespace MediaBrowser.Controller.LiveTv /// The identifier. /// The cancellation token. /// Task{Stream}. - Task GetRecordingStream(string id, CancellationToken cancellationToken); + Task GetRecordingStream(string id, CancellationToken cancellationToken); /// /// Gets the channel stream. @@ -162,7 +163,7 @@ namespace MediaBrowser.Controller.LiveTv /// The identifier. /// The cancellation token. /// Task{StreamResponseInfo}. - Task GetChannelStream(string id, CancellationToken cancellationToken); + Task GetChannelStream(string id, CancellationToken cancellationToken); /// /// Gets the program. diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index 3abbe500fc..eda69b164e 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Channels; namespace MediaBrowser.Controller.LiveTv { @@ -172,7 +173,7 @@ namespace MediaBrowser.Controller.LiveTv /// The recording identifier. /// The cancellation token. /// Task{Stream}. - Task GetRecordingStream(string recordingId, CancellationToken cancellationToken); + Task GetRecordingStream(string recordingId, CancellationToken cancellationToken); /// /// Gets the channel stream. @@ -180,7 +181,7 @@ namespace MediaBrowser.Controller.LiveTv /// The channel identifier. /// The cancellation token. /// Task{Stream}. - Task GetChannelStream(string channelId, CancellationToken cancellationToken); + Task GetChannelStream(string channelId, CancellationToken cancellationToken); /// /// Closes the live stream. diff --git a/MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs b/MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs deleted file mode 100644 index 019c9d31a5..0000000000 --- a/MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediaBrowser.Model.Entities; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.LiveTv -{ - public class LiveStreamInfo - { - /// - /// Gets or sets the path. - /// - /// The path. - public string Path { get; set; } - - /// - /// Gets or sets the URL. - /// - /// The URL. - public string Url { get; set; } - - /// - /// Gets or sets the identifier. - /// - /// The identifier. - public string Id { get; set; } - - /// - /// Gets or sets the media container. - /// - /// The media container. - public string MediaContainer { get; set; } - - /// - /// Gets or sets the media streams. - /// - /// The media streams. - public List MediaStreams { get; set; } - - public LiveStreamInfo() - { - MediaStreams = new List(); - } - } -} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 8ae605b629..7039a00eb2 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -181,7 +181,6 @@ - diff --git a/MediaBrowser.Model/Connect/ConnectAuthenticationResult.cs b/MediaBrowser.Model/Connect/ConnectAuthenticationResult.cs index 4dcbf69041..0df035e575 100644 --- a/MediaBrowser.Model/Connect/ConnectAuthenticationResult.cs +++ b/MediaBrowser.Model/Connect/ConnectAuthenticationResult.cs @@ -4,10 +4,10 @@ namespace MediaBrowser.Model.Connect public class ConnectAuthenticationResult { /// - /// Gets or sets the user identifier. + /// Gets or sets the user. /// - /// The user identifier. - public string UserId { get; set; } + /// The user. + public ConnectUser User { get; set; } /// /// Gets or sets the access token. /// diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index b9d2182150..f1075f77de 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -359,71 +359,13 @@ namespace MediaBrowser.Server.Implementations.Channels private MediaSourceInfo GetMediaSource(IChannelMediaItem item, ChannelMediaInfo info) { - var id = info.Path.GetMD5().ToString("N"); + var source = info.ToMediaSource(); - var source = new MediaSourceInfo - { - MediaStreams = GetMediaStreams(info).ToList(), - - Container = info.Container, - Protocol = info.Protocol, - Path = info.Path, - RequiredHttpHeaders = info.RequiredHttpHeaders, - RunTimeTicks = item.RunTimeTicks, - Name = id, - Id = id - }; - - var bitrate = (info.AudioBitrate ?? 0) + (info.VideoBitrate ?? 0); - - if (bitrate > 0) - { - source.Bitrate = bitrate; - } - - if (item is ChannelVideoItem && info.Protocol != MediaProtocol.Rtmp) - { - - } + source.RunTimeTicks = source.RunTimeTicks ?? item.RunTimeTicks; return source; } - private IEnumerable GetMediaStreams(ChannelMediaInfo info) - { - var list = new List(); - - 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 IEnumerable SortMediaInfoResults(IEnumerable channelMediaSources) { var list = channelMediaSources.ToList(); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 64f7a3373f..23a2da4fd0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -344,24 +345,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - public async Task GetRecordingStream(string id, CancellationToken cancellationToken) + public async Task GetRecordingStream(string id, CancellationToken cancellationToken) { return await GetLiveStream(id, false, cancellationToken).ConfigureAwait(false); } - public async Task GetChannelStream(string id, CancellationToken cancellationToken) + public async Task GetChannelStream(string id, CancellationToken cancellationToken) { return await GetLiveStream(id, true, cancellationToken).ConfigureAwait(false); } - private async Task GetLiveStream(string id, bool isChannel, CancellationToken cancellationToken) + private async Task GetLiveStream(string id, bool isChannel, CancellationToken cancellationToken) { await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { var service = ActiveService; - LiveStreamInfo info; + ChannelMediaInfo info; if (isChannel) { @@ -406,55 +407,41 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - private void Sanitize(LiveStreamInfo info) + private void Sanitize(ChannelMediaInfo info) { // Clean some bad data coming from providers - foreach (var stream in info.MediaStreams) + if (info.AudioBitrate.HasValue && info.AudioBitrate <= 0) { - if (stream.BitDepth.HasValue && stream.BitDepth <= 0) - { - stream.BitDepth = null; - } - if (stream.BitRate.HasValue && stream.BitRate <= 0) - { - stream.BitRate = null; - } - if (stream.Channels.HasValue && stream.Channels <= 0) - { - stream.Channels = null; - } - if (stream.AverageFrameRate.HasValue && stream.AverageFrameRate <= 0) - { - stream.AverageFrameRate = null; - } - if (stream.RealFrameRate.HasValue && stream.RealFrameRate <= 0) - { - stream.RealFrameRate = null; - } - if (stream.Width.HasValue && stream.Width <= 0) - { - stream.Width = null; - } - if (stream.Height.HasValue && stream.Height <= 0) - { - stream.Height = null; - } - if (stream.SampleRate.HasValue && stream.SampleRate <= 0) - { - stream.SampleRate = null; - } - if (stream.Level.HasValue && stream.Level <= 0) - { - stream.Level = null; - } - if (stream.PacketLength.HasValue && stream.PacketLength <= 0) - { - stream.PacketLength = null; - } - - // Don't trust the provider values - stream.Index = -1; + info.AudioBitrate = null; + } + if (info.VideoBitrate.HasValue && info.VideoBitrate <= 0) + { + info.VideoBitrate = null; + } + if (info.AudioChannels.HasValue && info.AudioChannels <= 0) + { + info.AudioChannels = null; + } + if (info.Framerate.HasValue && info.Framerate <= 0) + { + info.Framerate = null; + } + if (info.Width.HasValue && info.Width <= 0) + { + info.Width = null; + } + if (info.Height.HasValue && info.Height <= 0) + { + info.Height = null; + } + if (info.AudioSampleRate.HasValue && info.AudioSampleRate <= 0) + { + info.AudioSampleRate = null; + } + if (info.VideoLevel.HasValue && info.VideoLevel <= 0) + { + info.VideoLevel = null; } } @@ -1702,7 +1689,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv class LiveStreamData { - internal LiveStreamInfo Info; + internal ChannelMediaInfo Info; internal int ConsumerCount; internal string ItemId; internal bool IsChannel; diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 6f280c45af..a776cd0599 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.484 + 3.0.486 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 95197afc68..faeb5b0cf1 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.484 + 3.0.486 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 4264b28500..b73d4a80f7 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.484 + 3.0.486 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 2820c4f9d3..fa1a9aa62e 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.484 + 3.0.486 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +