aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/LiveTv
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/LiveTv')
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs28
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs22
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs114
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs11
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs32
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs22
-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);
}
}
}