diff options
Diffstat (limited to 'Emby.Server.Implementations/LiveTv')
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 28 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 22 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 114 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 11 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs | 32 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs | 22 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs (renamed from Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs) | 73 |
7 files changed, 236 insertions, 66 deletions
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index be5e57539b..9992c71ecf 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1052,10 +1052,27 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _liveStreamsSemaphore.Release(); } + } + + public async Task<List<ILiveStream>> GetLiveStreams(TunerHostInfo host, CancellationToken cancellationToken) + { + //await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + //try + //{ + var hostId = host.Id; + + return _liveStreams + .Where(i => string.Equals(i.TunerHostId, hostId, StringComparison.OrdinalIgnoreCase)) + .ToList(); + //} + //finally + //{ + // _liveStreamsSemaphore.Release(); + //} } - private async Task<Tuple<ILiveStream, MediaSourceInfo, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) + private async Task<Tuple<ILiveStream, MediaSourceInfo>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) { _logger.Info("Streaming Channel " + channelId); @@ -1072,7 +1089,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount); - return new Tuple<ILiveStream, MediaSourceInfo, ITunerHost>(result, openedMediaSource, result.TunerHost); + return new Tuple<ILiveStream, MediaSourceInfo>(result, openedMediaSource); } foreach (var hostInstance in _liveTvManager.TunerHosts) @@ -1086,13 +1103,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV result.SharedStreamIds.Add(openedMediaSource.Id); _liveStreams.Add(result); - result.TunerHost = hostInstance; result.OriginalStreamId = streamId; _logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}", streamId, openedMediaSource.Id, openedMediaSource.LiveStreamId); - return new Tuple<ILiveStream, MediaSourceInfo, ITunerHost>(result, openedMediaSource, hostInstance); + return new Tuple<ILiveStream, MediaSourceInfo>(result, openedMediaSource); } catch (FileNotFoundException) { @@ -2445,6 +2461,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { existingTimer.Status = RecordingStatus.Cancelled; } + else if (!existingTimer.IsManual) + { + existingTimer.Status = RecordingStatus.New; + } if (existingTimer.Status != RecordingStatus.Cancelled) { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 718620ab57..7e72d1b1a1 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1232,6 +1232,8 @@ namespace Emby.Server.Implementations.LiveTv var newChannelIdList = new List<Guid>(); var newProgramIdList = new List<Guid>(); + var cleanDatabase = true; + foreach (var service in _services) { cancellationToken.ThrowIfCancellationRequested(); @@ -1254,6 +1256,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + cleanDatabase = false; _logger.ErrorException("Error refreshing channels for service", ex); } @@ -1264,8 +1267,11 @@ namespace Emby.Server.Implementations.LiveTv progress.Report(100 * percent); } - await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false); - await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false); + if (cleanDatabase) + { + await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false); + await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false); + } var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault(); @@ -1291,8 +1297,9 @@ namespace Emby.Server.Implementations.LiveTv { progress.Report(10); - var allChannels = await GetChannels(service, cancellationToken).ConfigureAwait(false); - var allChannelsList = allChannels.ToList(); + var allChannelsList = (await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false)) + .Select(i => new Tuple<string, ChannelInfo>(service.Name, i)) + .ToList(); var list = new List<LiveTvChannel>(); @@ -1507,13 +1514,6 @@ namespace Emby.Server.Implementations.LiveTv return 7; } - private async Task<IEnumerable<Tuple<string, ChannelInfo>>> GetChannels(ILiveTvService service, CancellationToken cancellationToken) - { - var channels = await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false); - - return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i)); - } - private DateTime _lastRecordingRefreshTime; private async Task RefreshRecordings(Guid internalLiveTvFolderId, CancellationToken cancellationToken) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 59346cdec2..74758e906c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -105,7 +105,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private class HdHomerunChannelInfo : ChannelInfo { public bool IsLegacyTuner { get; set; } - public string Url { get; set; } } protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) @@ -124,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun VideoCodec = i.VideoCodec, ChannelType = ChannelType.TV, IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase), - Url = i.URL + Path = i.URL }).Cast<ChannelInfo>().ToList(); } @@ -148,7 +147,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { using (var response = await _httpClient.SendAsync(new HttpRequestOptions() { - Url = string.Format("{0}/discover.json", GetApiUrl(info, false)), + Url = string.Format("{0}/discover.json", GetApiUrl(info)), CancellationToken = cancellationToken, TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), BufferContent = false @@ -195,13 +194,80 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - private async Task<List<LiveTvTunerInfo>> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) + private async Task<List<LiveTvTunerInfo>> GetTunerInfosHttp(TunerHostInfo info, CancellationToken cancellationToken) + { + var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); + + using (var stream = await _httpClient.Get(new HttpRequestOptions() + { + Url = string.Format("{0}/tuners.html", GetApiUrl(info)), + CancellationToken = cancellationToken, + TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), + BufferContent = false + })) + { + var tuners = new List<LiveTvTunerInfo>(); + using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) + { + while (!sr.EndOfStream) + { + string line = StripXML(sr.ReadLine()); + if (line.Contains("Channel")) + { + LiveTvTunerStatus status; + var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = line.Substring(0, index - 1); + var currentChannel = line.Substring(index + 7); + if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } + tuners.Add(new LiveTvTunerInfo + { + Name = name, + SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, + ProgramName = currentChannel, + Status = status + }); + } + } + } + return tuners; + } + } + + private static string StripXML(string source) + { + char[] buffer = new char[source.Length]; + int bufferIndex = 0; + bool inside = false; + + for (int i = 0; i < source.Length; i++) + { + char let = source[i]; + if (let == '<') + { + inside = true; + continue; + } + if (let == '>') + { + inside = false; + continue; + } + if (!inside) + { + buffer[bufferIndex] = let; + bufferIndex++; + } + } + return new string(buffer, 0, bufferIndex); + } + + private async Task<List<LiveTvTunerInfo>> GetTunerInfosUdp(TunerHostInfo info, CancellationToken cancellationToken) { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); var tuners = new List<LiveTvTunerInfo>(); - var uri = new Uri(GetApiUrl(info, false)); + var uri = new Uri(GetApiUrl(info)); using (var manager = new HdHomerunManager(_socketFactory, Logger)) { @@ -246,7 +312,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return list; } - private string GetApiUrl(TunerHostInfo info, bool isPlayback) + public async Task<List<LiveTvTunerInfo>> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) + { + // TODO Need faster way to determine UDP vs HTTP + var channels = await GetChannels(info, true, cancellationToken); + + var hdHomerunChannelInfo = channels.FirstOrDefault() as HdHomerunChannelInfo; + + if (hdHomerunChannelInfo == null || hdHomerunChannelInfo.IsLegacyTuner) + { + return await GetTunerInfosUdp(info, cancellationToken).ConfigureAwait(false); + } + + return await GetTunerInfosHttp(info, cancellationToken).ConfigureAwait(false); + } + + private string GetApiUrl(TunerHostInfo info) { var url = info.Url; @@ -260,16 +341,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun url = "http://" + url; } - var uri = new Uri(url); - - if (isPlayback) - { - var builder = new UriBuilder(uri); - builder.Port = 5004; - uri = builder.Uri; - } - - return uri.AbsoluteUri.TrimEnd('/'); + return new Uri(url).AbsoluteUri.TrimEnd('/'); } private class Channels @@ -392,7 +464,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun nal = "0"; } - var url = GetApiUrl(info, false); + var url = GetApiUrl(info); var id = profile; if (string.IsNullOrWhiteSpace(id)) @@ -526,7 +598,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner) { - return new HdHomerunUdpStream(mediaSource, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Url), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); + return new HdHomerunUdpStream(mediaSource, info, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Path), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); } // The UDP method is not working reliably on OSX, and on BSD it hasn't been tested yet @@ -537,7 +609,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { mediaSource.Protocol = MediaProtocol.Http; - var httpUrl = GetApiUrl(info, true) + "/auto/v" + hdhrId; + var httpUrl = channelInfo.Path; // If raw was used, the tuner doesn't support params if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -546,10 +618,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } mediaSource.Path = httpUrl; - return new HdHomerunHttpStream(mediaSource, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); + return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); } - return new HdHomerunUdpStream(mediaSource, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number, profile), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); + return new HdHomerunUdpStream(mediaSource, info, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number, profile), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); } public async Task Validate(TunerHostInfo info) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 06326d26c6..6e93055be0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -11,6 +11,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using MediaBrowser.Model.System; +using MediaBrowser.Model.LiveTv; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { @@ -23,8 +24,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly int _numTuners; private readonly INetworkManager _networkManager; - public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment) - : base(mediaSource, environment, fileSystem, logger, appPaths) + public HdHomerunUdpStream(MediaSourceInfo mediaSource, TunerHostInfo tunerHostInfo, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment) + : base(mediaSource, tunerHostInfo, environment, fileSystem, logger, appPaths) { _appHost = appHost; _socketFactory = socketFactory; @@ -32,6 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun OriginalStreamId = originalStreamId; _channelCommands = channelCommands; _numTuners = numTuners; + EnableStreamSharing = true; } public override async Task Open(CancellationToken openCancellationToken) @@ -105,9 +107,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun await taskCompletionSource.Task.ConfigureAwait(false); } - public override void Close() + protected override void CloseInternal() { - Logger.Info("Closing HDHR UDP live stream"); LiveStreamCancellationTokenSource.Cancel(); } @@ -134,6 +135,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun openTaskCompletionSource.TrySetException(ex); } + EnableStreamSharing = false; + try { await hdHomerunManager.StopStreaming().ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 8620987355..f6758e94e2 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.System; +using MediaBrowser.Model.LiveTv; namespace Emby.Server.Implementations.LiveTv.TunerHosts { @@ -21,7 +22,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { get { return SharedStreamIds.Count; } } - public ITunerHost TunerHost { get; set; } + public string OriginalStreamId { get; set; } public bool EnableStreamSharing { get; set; } public string UniqueId { get; private set; } @@ -29,12 +30,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public List<string> SharedStreamIds { get; private set; } protected readonly IEnvironmentInfo Environment; protected readonly IFileSystem FileSystem; + protected readonly IServerApplicationPaths AppPaths; - protected readonly string TempFilePath; + protected string TempFilePath; protected readonly ILogger Logger; protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource(); - public LiveStream(MediaSourceInfo mediaSource, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths) + public string TunerHostId { get; private set; } + + public LiveStream(MediaSourceInfo mediaSource, TunerHostInfo tuner, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths) { OriginalMediaSource = mediaSource; Environment = environment; @@ -44,7 +48,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts EnableStreamSharing = true; SharedStreamIds = new List<string>(); UniqueId = Guid.NewGuid().ToString("N"); - TempFilePath = Path.Combine(appPaths.GetTranscodingTempPath(), UniqueId + ".ts"); + TunerHostId = tuner.Id; + + AppPaths = appPaths; + + SetTempFilePath("ts"); + } + + protected void SetTempFilePath(string extension) + { + TempFilePath = Path.Combine(AppPaths.GetTranscodingTempPath(), UniqueId + "." + extension); } public virtual Task Open(CancellationToken openCancellationToken) @@ -52,7 +65,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.FromResult(true); } - public virtual void Close() + public void Close() + { + EnableStreamSharing = false; + + Logger.Info("Closing " + GetType().Name); + + CloseInternal(); + } + + protected virtual void CloseInternal() { } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 9fc6687d14..c96d1f3592 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -77,10 +77,28 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) { + var tunerCount = info.TunerCount; + + if (tunerCount > 0) + { + var liveStreams = await EmbyTV.EmbyTV.Current.GetLiveStreams(info, cancellationToken).ConfigureAwait(false); + + if (liveStreams.Count >= info.TunerCount) + { + throw new LiveTvConflictException(); + } + } + var sources = await GetChannelStreamMediaSources(info, channelId, cancellationToken).ConfigureAwait(false); - var liveStream = new LiveStream(sources.First(), _environment, FileSystem, Logger, Config.ApplicationPaths); - return liveStream; + var mediaSource = sources.First(); + + if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping) + { + return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); + } + + return new LiveStream(mediaSource, info, _environment, FileSystem, Logger, Config.ApplicationPaths); } public async Task Validate(TunerHostInfo info) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 7e0e5fc5c9..cc2cb3e5ee 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -14,20 +14,22 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; using System.Globalization; using MediaBrowser.Controller.IO; +using MediaBrowser.Model.LiveTv; -namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +namespace Emby.Server.Implementations.LiveTv.TunerHosts { - public class HdHomerunHttpStream : LiveStream, IDirectStreamProvider + public class SharedHttpStream : LiveStream, IDirectStreamProvider { private readonly IHttpClient _httpClient; private readonly IServerApplicationHost _appHost; - public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment) - : base(mediaSource, environment, fileSystem, logger, appPaths) + public SharedHttpStream(MediaSourceInfo mediaSource, TunerHostInfo tunerHostInfo, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment) + : base(mediaSource, tunerHostInfo, environment, fileSystem, logger, appPaths) { _httpClient = httpClient; _appHost = appHost; OriginalStreamId = originalStreamId; + EnableStreamSharing = true; } public override async Task Open(CancellationToken openCancellationToken) @@ -40,7 +42,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath)); - Logger.Info("Opening HDHR Live stream from {0}", url); + var typeName = GetType().Name; + Logger.Info("Opening " + typeName + " Live stream from {0}", url); var response = await _httpClient.SendAsync(new HttpRequestOptions { @@ -51,13 +54,41 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Increase a little bit TimeoutMs = 30000, - EnableHttpCompression = false + EnableHttpCompression = false, + + LogResponse = true, + LogResponseHeaders = true }, "GET").ConfigureAwait(false); - Logger.Info("Opened HDHR stream from {0}", url); + var extension = "ts"; + var requiresRemux = false; + + var contentType = response.ContentType ?? string.Empty; + if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1) + { + requiresRemux = true; + } + else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 || + contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 || + contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1) + { + requiresRemux = true; + } + + // Close the stream without any sharing features + if (requiresRemux) + { + using (response) + { + return; + } + } + + SetTempFilePath(extension); - StartStreaming(response, LiveStreamCancellationTokenSource.Token); + var taskCompletionSource = new TaskCompletionSource<bool>(); + StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; @@ -66,20 +97,28 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; OpenedMediaSource.Protocol = MediaProtocol.Http; + if (OpenedMediaSource.SupportsProbing) + { + await Task.Delay(3000).ConfigureAwait(false); + } + + //OpenedMediaSource.Path = TempFilePath; + //OpenedMediaSource.Protocol = MediaProtocol.File; + //OpenedMediaSource.Path = _tempFilePath; //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.SupportsDirectPlay = false; //OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsTranscoding = true; + await taskCompletionSource.Task.ConfigureAwait(false); } - public override void Close() + protected override void CloseInternal() { - Logger.Info("Closing HDHR live stream"); LiveStreamCancellationTokenSource.Cancel(); } - private Task StartStreaming(HttpResponseInfo response, CancellationToken cancellationToken) + private Task StartStreaming(HttpResponseInfo response, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) { return Task.Run(async () => { @@ -89,12 +128,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { using (var stream = response.Content) { - Logger.Info("Beginning HdHomerunHttpStream stream to file"); + Logger.Info("Beginning {0} stream to {1}", GetType().Name, TempFilePath); - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath)); using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) { - StreamHelper.CopyTo(stream, fileStream, 81920, null, cancellationToken); + StreamHelper.CopyTo(stream, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken); } } } @@ -106,17 +144,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { Logger.ErrorException("Error copying live stream.", ex); } - + EnableStreamSharing = false; await DeleteTempFile(TempFilePath).ConfigureAwait(false); }); } private void Resolve(TaskCompletionSource<bool> openTaskCompletionSource) { - Task.Run(() => - { - openTaskCompletionSource.TrySetResult(true); - }); + openTaskCompletionSource.TrySetResult(true); } } } |
