public override async Task Open(CancellationToken openCancellationToken) { LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); var mediaSource = OriginalMediaSource; var url = mediaSource.Path; Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); var typeName = GetType().Name; Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None) .ConfigureAwait(false); var extension = "ts"; var requiresRemux = false; var contentType = response.Content.Headers.ContentType.ToString(); 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 || contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1) { requiresRemux = true; } // Close the stream without any sharing features if (requiresRemux) { using (response) { return; } } SetTempFilePath(extension); var taskCompletionSource = new TaskCompletionSource <bool>(); var now = DateTime.UtcNow; _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); // OpenedMediaSource.Protocol = MediaProtocol.File; // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // 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); if (taskCompletionSource.Task.Exception != null) { // Error happened while opening the stream so raise the exception again to inform the caller throw taskCompletionSource.Task.Exception; } if (!taskCompletionSource.Task.Result) { Logger.LogWarning("Zero bytes copied from stream {0} to {1} but no exception raised", GetType().Name, TempFilePath); throw new EndOfStreamException(String.Format(CultureInfo.InvariantCulture, "Zero bytes copied from stream {0}", GetType().Name)); } }
public override async Task Open(CancellationToken openCancellationToken) { LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); var mediaSource = OriginalMediaSource; var uri = new Uri(mediaSource.Path); var localPort = _networkManager.GetRandomUnusedUdpPort(); Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); var remoteAddress = IPAddress.Parse(uri.Host); IPAddress localAddress = null; using (var tcpClient = new TcpClient()) { try { await tcpClient.ConnectAsync(remoteAddress, HdHomerunManager.HdHomeRunPort).ConfigureAwait(false); localAddress = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address; tcpClient.Close(); } catch (Exception ex) { Logger.LogError(ex, "Unable to determine local ip address for Legacy HDHomerun stream."); return; } } var udpClient = new UdpClient(localPort, AddressFamily.InterNetwork); var hdHomerunManager = new HdHomerunManager(); try { // send url to start streaming await hdHomerunManager.StartStreaming( remoteAddress, localAddress, localPort, _channelCommands, _numTuners, openCancellationToken).ConfigureAwait(false); } catch (Exception ex) { using (udpClient) using (hdHomerunManager) { if (!(ex is OperationCanceledException)) { Logger.LogError(ex, "Error opening live stream:"); } throw; } } var taskCompletionSource = new TaskCompletionSource <bool>(); await StartStreaming( udpClient, hdHomerunManager, remoteAddress, taskCompletionSource, LiveStreamCancellationTokenSource.Token).ConfigureAwait(false); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; //OpenedMediaSource.ReadAtNativeFramerate = true; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; //OpenedMediaSource.SupportsDirectPlay = false; //OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsTranscoding = true; //await Task.Delay(5000).ConfigureAwait(false); await taskCompletionSource.Task.ConfigureAwait(false); }
public override async Task Open(CancellationToken openCancellationToken) { LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); var mediaSource = OriginalMediaSource; var url = mediaSource.Path; Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); var typeName = GetType().Name; Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url); var httpRequestOptions = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None, BufferContent = false, DecompressionMethod = CompressionMethods.None }; foreach (var header in mediaSource.RequiredHttpHeaders) { httpRequestOptions.RequestHeaders[header.Key] = header.Value; } var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false); 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 || contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1) { requiresRemux = true; } // Close the stream without any sharing features if (requiresRemux) { using (response) { return; } } SetTempFilePath(extension); var taskCompletionSource = new TaskCompletionSource <bool>(); var now = DateTime.UtcNow; _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; //OpenedMediaSource.ReadAtNativeFramerate = true; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; //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 async Task Open(CancellationToken openCancellationToken) { LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); var mediaSource = OriginalMediaSource; var url = mediaSource.Path; var encodingConfig = _configurationManager.GetConfiguration <EncodingOptions>("encoding"); Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); var typeName = GetType().Name; Logger.LogInformation("Opening {0} Live stream from {1}", typeName, url); var streamlinkProc = new Process(); streamlinkProc.StartInfo.FileName = Jellyfin.Plugin.Streamlink.Plugin.Instance.Configuration.StreamlinkPath; streamlinkProc.StartInfo.UseShellExecute = false; streamlinkProc.StartInfo.RedirectStandardOutput = true; streamlinkProc.StartInfo.ArgumentList.Add("--ffmpeg-ffmpeg=" + encodingConfig.EncoderAppPath); streamlinkProc.StartInfo.ArgumentList.Add("--quiet"); streamlinkProc.StartInfo.ArgumentList.Add("--stdout"); foreach (string arg in Jellyfin.Plugin.Streamlink.Plugin.Instance.Configuration.ExtraArguments.Split(" ")) { if (!string.IsNullOrWhiteSpace(arg)) { streamlinkProc.StartInfo.ArgumentList.Add(arg); } } streamlinkProc.StartInfo.ArgumentList.Add(url); streamlinkProc.StartInfo.ArgumentList.Add(Jellyfin.Plugin.Streamlink.Plugin.Instance.Configuration.StreamQuality); Logger.LogInformation( "Starting streamlink with: {0} {1}", streamlinkProc.StartInfo.FileName, String.Join(" ", streamlinkProc.StartInfo.ArgumentList) ); SetTempFilePath("ts"); var taskCompletionSource = new TaskCompletionSource <bool>(); var now = DateTime.UtcNow; #pragma warning disable CS4014 StartStreaming(streamlinkProc, taskCompletionSource, LiveStreamCancellationTokenSource.Token); MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; MediaSource.LiveStreamId = OriginalStreamId; await taskCompletionSource.Task.ConfigureAwait(false); if (taskCompletionSource.Task.Exception != null) { // Error happened while opening the stream so raise the exception again to inform the caller throw taskCompletionSource.Task.Exception; } if (!taskCompletionSource.Task.Result) { Logger.LogWarning("Zero bytes copied from stream {0} to {1} but no exception raised", GetType().Name, TempFilePath); throw new EndOfStreamException(String.Format(CultureInfo.InvariantCulture, "Zero bytes copied from stream {0}", GetType().Name)); } }