/// <summary> /// <para>Events:</para> /// <para>@emits transportclose</para></para> /// <para>@emits score - (score: ProducerScore[])</para> /// <para>@emits videoorientationchange - (videoOrientation: ProducerVideoOrientation)</para> /// <para>@emits trace - (trace: ProducerTraceEventData)</para> /// <para>@emits @close</para> /// <para>Observer events:</para> /// <para>@emits close</para> /// <para>@emits pause</para> /// <para>@emits resume</para> /// <para>@emits score - (score: ProducerScore[])</para> /// <para>@emits videoorientationchange - (videoOrientation: ProducerVideoOrientation)</para> /// <para>@emits trace - (trace: ProducerTraceEventData)</para> /// </summary> /// <param name="loggerFactory"></param> /// <param name="producerInternalData"></param> /// <param name="kind"></param> /// <param name="rtpParameters"></param> /// <param name="type"></param> /// <param name="consumableRtpParameters"></param> /// <param name="channel"></param> /// <param name="appData"></param> /// <param name="paused"></param> public Producer(ILoggerFactory loggerFactory, ProducerInternalData producerInternalData, MediaKind kind, RtpParameters rtpParameters, ProducerType type, RtpParameters consumableRtpParameters, Channel channel, PayloadChannel payloadChannel, Dictionary <string, object>?appData, bool paused ) { _logger = loggerFactory.CreateLogger <Producer>(); // Internal _internal = producerInternalData; // Data Kind = kind; RtpParameters = rtpParameters; Type = type; ConsumableRtpParameters = consumableRtpParameters; _channel = channel; _payloadChannel = payloadChannel; AppData = appData; _paused = paused; if (_isCheckConsumer) { _checkConsumersTimer = new Timer(CheckConsumers, null, TimeSpan.FromSeconds(CheckConsumersTimeSeconds), TimeSpan.FromMilliseconds(-1)); } HandleWorkerNotifications(); }
/// <summary> /// Validates RtpParameters. It may modify given data by adding missing /// fields with default values. /// It throws if invalid. /// </summary> public static void ValidateRtpParameters(RtpParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // mid is optional. // 在 Node.js 实现中,判断了 mid 的数据类型。在强类型语言中不需要。 // codecs is mandatory. if (parameters.Codecs == null) { throw new ArgumentException(nameof(parameters.Codecs)); } foreach (var codec in parameters.Codecs) { ValidateRtpCodecParameters(codec); } // headerExtensions is optional. If unset, fill with an empty array. if (parameters.HeaderExtensions == null) { parameters.HeaderExtensions = new List <RtpHeaderExtensionParameters>(); } foreach (var ext in parameters.HeaderExtensions) { ValidateRtpHeaderExtensionParameters(ext); } // encodings is optional. If unset, fill with an empty array. if (parameters.Encodings == null) { parameters.Encodings = new List <RtpEncodingParameters>(); } foreach (var encoding in parameters.Encodings) { ValidateRtpEncodingParameters(encoding); } // rtcp is optional. If unset, fill with an empty object. if (parameters.Rtcp == null) { // 对 RtcpParameters 序列化时,CNAME 为 null 会忽略,因为客户端库对其有校验。 parameters.Rtcp = new RtcpParameters(); } ValidateRtcpParameters(parameters.Rtcp); }