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);
        }
Exemple #3
0
        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));
            }
        }