Example #1
0
        public override async Task Open(CancellationToken openCancellationToken)
        {
            LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();

            var mediaSource = OriginalMediaSource;

            var url = mediaSource.Path;

            Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath) ?? throw new InvalidOperationException("Path can't be a root directory."));

            var typeName = GetType().Name;

            Logger.LogInformation("Opening {StreamType} Live stream from {Url}", typeName, url);

            // Response stream is disposed manually.
            var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                           .GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None)
                           .ConfigureAwait(false);

            var contentType = response.Content.Headers.ContentType?.ToString() ?? string.Empty;

            if (contentType.Contains("matroska", StringComparison.OrdinalIgnoreCase) ||
                contentType.Contains("mp4", StringComparison.OrdinalIgnoreCase) ||
                contentType.Contains("dash", StringComparison.OrdinalIgnoreCase) ||
                contentType.Contains("mpegURL", StringComparison.OrdinalIgnoreCase) ||
                contentType.Contains("text/", StringComparison.OrdinalIgnoreCase))
            {
                // Close the stream without any sharing features
                response.Dispose();
                return;
            }

            SetTempFilePath("ts");

            var taskCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);

            // OpenedMediaSource.Protocol = MediaProtocol.File;
            // OpenedMediaSource.Path = tempFile;
            // OpenedMediaSource.ReadAtNativeFramerate = true;

            MediaSource.Path     = _appHost.GetApiUrlForLocalAccess() + "/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;
            var res = await taskCompletionSource.Task.ConfigureAwait(false);

            if (!res)
            {
                Logger.LogWarning("Zero bytes copied from stream {StreamType} to {FilePath} but no exception raised", GetType().Name, TempFilePath);
                throw new EndOfStreamException(string.Format(CultureInfo.InvariantCulture, "Zero bytes copied from stream {0}", GetType().Name));
            }
        }
Example #2
0
        private void RegisterServerEndpoints()
        {
            var udn           = CreateUuid(_appHost.SystemId);
            var descriptorUri = "/dlna/" + udn + "/description.xml";

            var bindAddresses = NetworkManager.CreateCollection(
                _networkManager.GetInternalBindAddresses()
                .Where(i => i.AddressFamily == AddressFamily.InterNetwork || (i.AddressFamily == AddressFamily.InterNetworkV6 && i.Address.ScopeId != 0)));

            if (bindAddresses.Count == 0)
            {
                // No interfaces returned, so use loopback.
                bindAddresses = _networkManager.GetLoopbacks();
            }

            foreach (IPNetAddress address in bindAddresses)
            {
                if (address.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    // Not supporting IPv6 right now
                    continue;
                }

                // Limit to LAN addresses only
                if (!_networkManager.IsInLocalNetwork(address))
                {
                    continue;
                }

                var fullService = "urn:schemas-upnp-org:device:MediaServer:1";

                _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);

                var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(false) + descriptorUri);

                var device = new SsdpRootDevice
                {
                    CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info.
                    Location      = uri.Uri,                    // Must point to the URL that serves your devices UPnP description document.
                    Address       = address.Address,
                    PrefixLength  = address.PrefixLength,
                    FriendlyName  = "Jellyfin",
                    Manufacturer  = "Jellyfin",
                    ModelName     = "Jellyfin Server",
                    Uuid          = udn
                                    // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                };

                SetProperies(device, fullService);
                _publisher.AddDevice(device);

                var embeddedDevices = new[]
                {
                    "urn:schemas-upnp-org:service:ContentDirectory:1",
                    "urn:schemas-upnp-org:service:ConnectionManager:1",
                    // "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"
                };

                foreach (var subDevice in embeddedDevices)
                {
                    var embeddedDevice = new SsdpEmbeddedDevice
                    {
                        FriendlyName = device.FriendlyName,
                        Manufacturer = device.Manufacturer,
                        ModelName    = device.ModelName,
                        Uuid         = udn
                                       // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
                    };

                    SetProperies(embeddedDevice, subDevice);
                    device.AddDevice(embeddedDevice);
                }
            }
        }
        private async Task <IEnumerable <MediaSourceInfo> > GetMediaSourcesInternal(BaseItem item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
        {
            IEnumerable <MediaSourceInfo> sources;

            var forceRequireOpening = false;

            try
            {
                if (activeRecordingInfo != null)
                {
                    sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken)
                              .ConfigureAwait(false);
                }
                else
                {
                    sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
                              .ConfigureAwait(false);
                }
            }
            catch (NotImplementedException)
            {
                sources = _mediaSourceManager.GetStaticMediaSources(item, false);

                forceRequireOpening = true;
            }

            var list = sources.ToList();

            foreach (var source in list)
            {
                source.Type = MediaSourceType.Default;
                source.BufferMs ??= 1500;

                if (source.RequiresOpening || forceRequireOpening)
                {
                    source.RequiresOpening = true;
                }

                if (source.RequiresOpening)
                {
                    var openKeys = new List <string>
                    {
                        item.GetType().Name,
                        item.Id.ToString("N", CultureInfo.InvariantCulture),
                        source.Id ?? string.Empty
                    };

                    source.OpenToken = string.Join(StreamIdDelimiter, openKeys);
                }

                // Dummy this up so that direct play checks can still run
                if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)
                {
                    source.Path = _appHost.GetApiUrlForLocalAccess();
                }
            }

            _logger.LogDebug("MediaSources: {@MediaSources}", list);

            return(list);
        }