Beispiel #1
0
        /// <summary>
        /// <para>Events:</para>
        /// <para>@emits transportclose</para>
        /// <para>@emits producerclose</para>
        /// <para>@emits producerpause</para>
        /// <para>@emits producerresume</para>
        /// <para>@emits score - (score: ConsumerScore)</para>
        /// <para>@emits layerschange - (layers: ConsumerLayers | undefined)</para>
        /// <para>@emits trace - (trace: ConsumerTraceEventData)</para>
        /// <para>@emits @close</para>
        /// <para>@emits @producerclose</para>
        /// <para>Observer events:</para>
        /// <para>@emits close</para>
        /// <para>@emits pause</para>
        /// <para>@emits resume</para>
        /// <para>@emits score - (score: ConsumerScore)</para>
        /// <para>@emits layerschange - (layers: ConsumerLayers | undefined)</para>
        /// <para>@emits rtp - (packet: Buffer)</para>
        /// <para>@emits trace - (trace: ConsumerTraceEventData)</para>
        /// </summary>
        /// <param name="loggerFactory"></param>
        /// <param name="consumerInternalData"></param>
        /// <param name="kind"></param>
        /// <param name="rtpParameters"></param>
        /// <param name="type"></param>
        /// <param name="channel"></param>
        /// <param name="appData"></param>
        /// <param name="paused"></param>
        /// <param name="producerPaused"></param>
        /// <param name="score"></param>
        /// <param name="preferredLayers"></param>
        public Consumer(ILoggerFactory loggerFactory,
                        ConsumerInternalData consumerInternalData,
                        MediaKind kind,
                        RtpParameters rtpParameters,
                        ConsumerType type,
                        Channel channel,
                        PayloadChannel payloadChannel,
                        Dictionary <string, object>?appData,
                        bool paused,
                        bool producerPaused,
                        ConsumerScore?score,
                        ConsumerLayers?preferredLayers
                        )
        {
            _logger = loggerFactory.CreateLogger <Consumer>();

            // Internal
            _internal = consumerInternalData;

            // Data
            Kind          = kind;
            RtpParameters = rtpParameters;
            Type          = type;

            _channel        = channel;
            _payloadChannel = payloadChannel;
            AppData         = appData;
            _paused         = paused;
            ProducerPaused  = producerPaused;
            Score           = score;
            PreferredLayers = preferredLayers;

            HandleWorkerNotifications();
        }
Beispiel #2
0
        /// <summary>
        /// Create a Consumer.
        /// </summary>
        /// <param name="consumerOptions"></param>
        /// <returns></returns>
        public override async Task <Consumer> ConsumeAsync(ConsumerOptions consumerOptions)
        {
            _logger.LogDebug("ConsumeAsync()");

            if (consumerOptions.ProducerId.IsNullOrWhiteSpace())
            {
                throw new Exception("missing producerId");
            }

            var producer = GetProducerById(consumerOptions.ProducerId);

            if (producer == null)
            {
                throw new Exception($"Producer with id {consumerOptions.ProducerId} not found");
            }

            // This may throw.
            var rtpParameters = ORTC.GetPipeConsumerRtpParameters(producer.ConsumableRtpParameters, Rtx);

            var @internal = new ConsumerInternalData
                            (
                Internal.RouterId,
                Internal.TransportId,
                consumerOptions.ProducerId,
                Guid.NewGuid().ToString()
                            );

            var reqData = new
            {
                producer.Kind,
                RtpParameters          = rtpParameters,
                Type                   = ConsumerType.Pipe,
                ConsumableRtpEncodings = producer.ConsumableRtpParameters.Encodings,
            };

            var status = await Channel.RequestAsync(MethodId.TRANSPORT_CONSUME, @internal, reqData);

            var responseData = JsonConvert.DeserializeObject <TransportConsumeResponseData>(status !);

            var data = new
            {
                producer.Kind,
                RtpParameters = rtpParameters,
                Type          = ConsumerType.Pipe,
            };

            // 在 Node.js 实现中, 创建 Consumer 对象时没提供 score 和 preferredLayers 参数,且 score = { score: 10, producerScore: 10 }。
            var consumer = new Consumer(_loggerFactory,
                                        @internal,
                                        data.Kind,
                                        data.RtpParameters,
                                        data.Type,
                                        Channel,
                                        AppData,
                                        responseData.Paused,
                                        responseData.ProducerPaused,
                                        responseData.Score,
                                        responseData.PreferredLayers);

            Consumers[consumer.Internal.ConsumerId] = consumer;

            consumer.On("@close", _ => Consumers.Remove(consumer.Internal.ConsumerId));
            consumer.On("@producerclose", _ => Consumers.Remove(consumer.Internal.ConsumerId));

            // Emit observer event.
            Observer.Emit("newconsumer", consumer);

            return(consumer);
        }
Beispiel #3
0
        /// <summary>
        /// Create a Consumer.
        /// </summary>
        /// <param name="consumerOptions"></param>
        /// <returns></returns>
        public virtual async Task <Consumer> ConsumeAsync(ConsumerOptions consumerOptions)
        {
            _logger.LogDebug("ConsumeAsync()");

            if (consumerOptions.ProducerId.IsNullOrWhiteSpace())
            {
                throw new ArgumentException("missing producerId");
            }

            if (consumerOptions.RtpCapabilities == null)
            {
                throw new ArgumentException(nameof(consumerOptions.RtpCapabilities));
            }

            if (!consumerOptions.Paused.HasValue)
            {
                consumerOptions.Paused = false;
            }

            // This may throw.
            ORTC.ValidateRtpCapabilities(consumerOptions.RtpCapabilities);

            var producer = GetProducerById(consumerOptions.ProducerId);

            if (producer == null)
            {
                throw new NullReferenceException($"Producer with id {consumerOptions.ProducerId} not found");
            }

            // This may throw.
            var rtpParameters = ORTC.GetConsumerRtpParameters(producer.ConsumableRtpParameters, consumerOptions.RtpCapabilities);

            // Set MID.
            rtpParameters.Mid = $"{_nextMidForConsumers++}";

            // We use up to 8 bytes for MID (string).
            if (_nextMidForConsumers == 100000000)
            {
                _logger.LogDebug($"ConsumeAsync() | reaching max MID value {_nextMidForConsumers}");

                _nextMidForConsumers = 0;
            }

            var @internal = new ConsumerInternalData
                            (
                Internal.RouterId,
                Internal.TransportId,
                consumerOptions.ProducerId,
                Guid.NewGuid().ToString()
                            );

            var reqData = new
            {
                producer.Kind,
                RtpParameters = rtpParameters,
                producer.Type,
                ConsumableRtpEncodings = producer.ConsumableRtpParameters.Encodings,
                consumerOptions.Paused,
                consumerOptions.PreferredLayers
            };

            var status = await Channel.RequestAsync(MethodId.TRANSPORT_CONSUME, @internal, reqData);

            var responseData = JsonConvert.DeserializeObject <TransportConsumeResponseData>(status);

            var data = new
            {
                producer.Kind,
                RtpParameters = rtpParameters,
                Type          = (ConsumerType)producer.Type, // 注意:类型转换
            };

            var consumer = new Consumer(_loggerFactory,
                                        @internal,
                                        data.Kind,
                                        data.RtpParameters,
                                        data.Type,
                                        Channel,
                                        AppData,
                                        responseData.Paused,
                                        responseData.ProducerPaused,
                                        responseData.Score,
                                        responseData.PreferredLayers);

            Consumers[consumer.Internal.ConsumerId] = consumer;

            consumer.On("@close", _ => Consumers.Remove(consumer.Internal.ConsumerId));
            consumer.On("@producerclose", _ => Consumers.Remove(consumer.Internal.ConsumerId));

            // Emit observer event.
            Observer.Emit("newconsumer", consumer);

            return(consumer);
        }