diff options
Diffstat (limited to 'Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs')
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs new file mode 100644 index 000000000..a33b0945b --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -0,0 +1,145 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Emby.Server.Implementations.IO; +using MediaBrowser.Model.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.System; +using System.Globalization; +using MediaBrowser.Controller.IO; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts +{ + public class SharedHttpStream : LiveStream, IDirectStreamProvider + { + private readonly IHttpClient _httpClient; + private readonly IServerApplicationHost _appHost; + + public SharedHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment) + : base(mediaSource, environment, fileSystem, logger, appPaths) + { + _httpClient = httpClient; + _appHost = appHost; + OriginalStreamId = originalStreamId; + EnableStreamSharing = true; + } + + public override async Task Open(CancellationToken openCancellationToken) + { + LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); + + var mediaSource = OriginalMediaSource; + + var url = mediaSource.Path; + + FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath)); + + var typeName = GetType().Name; + Logger.Info("Opening " + typeName + " Live stream from {0}", url); + + var response = await _httpClient.SendAsync(new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None, + BufferContent = false, + + // Increase a little bit + TimeoutMs = 30000, + + EnableHttpCompression = false, + + LogResponse = true, + LogResponseHeaders = true + + }, "GET").ConfigureAwait(false); + + var extension = "ts"; + var requiresRemux = false; + + var contentType = response.ContentType ?? string.Empty; + if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 || + contentType.IndexOf("matroska", 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); + + var taskCompletionSource = new TaskCompletionSource<bool>(); + StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); + + //OpenedMediaSource.Protocol = MediaProtocol.File; + //OpenedMediaSource.Path = tempFile; + //OpenedMediaSource.ReadAtNativeFramerate = true; + + OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + OpenedMediaSource.Protocol = MediaProtocol.Http; + + //OpenedMediaSource.Path = _tempFilePath; + //OpenedMediaSource.Protocol = MediaProtocol.File; + //OpenedMediaSource.SupportsDirectPlay = false; + //OpenedMediaSource.SupportsDirectStream = true; + //OpenedMediaSource.SupportsTranscoding = true; + await taskCompletionSource.Task.ConfigureAwait(false); + } + + protected override void CloseInternal() + { + LiveStreamCancellationTokenSource.Cancel(); + } + + private Task StartStreaming(HttpResponseInfo response, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) + { + return Task.Run(async () => + { + try + { + using (response) + { + using (var stream = response.Content) + { + Logger.Info("Beginning {0} stream to {1}", GetType().Name, TempFilePath); + + using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) + { + StreamHelper.CopyTo(stream, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken); + } + } + } + } + catch (OperationCanceledException) + { + } + catch (Exception ex) + { + Logger.ErrorException("Error copying live stream.", ex); + } + EnableStreamSharing = false; + await DeleteTempFile(TempFilePath).ConfigureAwait(false); + }); + } + + private void Resolve(TaskCompletionSource<bool> openTaskCompletionSource) + { + openTaskCompletionSource.TrySetResult(true); + } + } +} |
