Exemplo n.º 1
0
        /// <summary>
        /// Validates RtpHeaderExtensionParameteters. It may modify given data by adding missing
        /// fields with default values.
        /// It throws if invalid.
        /// </summary>
        public static void ValidateRtpHeaderExtensionParameters(RtpHeaderExtensionParameters ext)
        {
            if (ext == null)
            {
                throw new ArgumentNullException(nameof(ext));
            }

            // uri is mandatory.
            if (ext.Uri.IsNullOrEmpty())
            {
                throw new ArgumentException(nameof(ext.Uri));
            }

            // id is mandatory.
            // 在 Node.js 实现在,判断了 id 的数据类型。在强类型语言中不需要。

            // encrypt is optional. If unset set it to false.
            if (!ext.Encrypt.HasValue)
            {
                ext.Encrypt = false;
            }

            // parameters is optional. If unset, set it to an empty object.
            // TODO: (alby)强类型无法转 Empty 对象。
            if (ext.Parameters == null)
            {
                ext.Parameters = new Dictionary <string, object>();
            }

            foreach (var item in ext.Parameters)
            {
                var key   = item.Key;
                var value = item.Value;

                if (value == null)
                {
                    ext.Parameters[item.Key] = "";
                    value = "";
                }

                if (!value.IsStringType() && !value.IsNumericType())
                {
                    throw new ArgumentOutOfRangeException($"invalid codec parameter[key:${ key }, value:${ value }]");
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generate RTP parameters to be internally used by Consumers given the RTP
        /// parameters in a Producer and the RTP capabilities in the Router.
        /// </summary>
        public static RtpParameters GetConsumableRtpParameters(MediaKind kind, RtpParameters parameters, RtpCapabilities caps, RtpMapping rtpMapping)
        {
            var consumableParams = new RtpParameters
            {
                Codecs           = new List <RtpCodecParameters>(),
                HeaderExtensions = new List <RtpHeaderExtensionParameters>(),
                Encodings        = new List <RtpEncodingParameters>(),
                Rtcp             = new RtcpParameters(),
            };

            foreach (var codec in parameters.Codecs)
            {
                if (IsRtxMimeType(codec.MimeType))
                {
                    continue;
                }

                var consumableCodecPt = rtpMapping.Codecs
                                        .Where(entry => entry.PayloadType == codec.PayloadType)
                                        .Select(m => m.MappedPayloadType)
                                        .FirstOrDefault();

                var matchedCapCodec = caps.Codecs
                                      .Where(capCodec => capCodec.PreferredPayloadType == consumableCodecPt)
                                      .FirstOrDefault();

                var consumableCodec = new RtpCodecParameters
                {
                    MimeType     = matchedCapCodec.MimeType,
                    PayloadType  = matchedCapCodec.PreferredPayloadType.Value, // TODO: (alby)注意 null 引用
                    ClockRate    = matchedCapCodec.ClockRate,
                    Channels     = matchedCapCodec.Channels,
                    Parameters   = codec.Parameters, // Keep the Producer codec parameters.
                    RtcpFeedback = matchedCapCodec.RtcpFeedback
                };

                consumableParams.Codecs.Add(consumableCodec);

                var consumableCapRtxCodec = caps.Codecs
                                            .Where(capRtxCodec => IsRtxMimeType(capRtxCodec.MimeType) && MatchCodecsWithPayloadTypeAndApt(consumableCodec.PayloadType, capRtxCodec.Parameters))
                                            .FirstOrDefault();

                if (consumableCapRtxCodec != null)
                {
                    var consumableRtxCodec = new RtpCodecParameters
                    {
                        MimeType     = consumableCapRtxCodec.MimeType,
                        PayloadType  = consumableCapRtxCodec.PreferredPayloadType.Value, // TODO: (alby)注意 null 引用
                        ClockRate    = consumableCapRtxCodec.ClockRate,
                        Channels     = consumableCapRtxCodec.Channels,
                        Parameters   = consumableCapRtxCodec.Parameters, // Keep the Producer codec parameters.
                        RtcpFeedback = consumableCapRtxCodec.RtcpFeedback
                    };

                    consumableParams.Codecs.Add(consumableRtxCodec);
                }
            }

            foreach (var capExt in caps.HeaderExtensions) // TODO: (alby)注意 null 引用
            {
                // Just take RTP header extension that can be used in Consumers.
                if (capExt.Kind != kind || (capExt.Direction != RtpHeaderExtensionDirection.SendReceive && capExt.Direction != RtpHeaderExtensionDirection.SendOnly))
                {
                    continue;
                }

                var consumableExt = new RtpHeaderExtensionParameters
                {
                    Uri        = capExt.Uri,
                    Id         = capExt.PreferredId,
                    Encrypt    = capExt.PreferredEncrypt,
                    Parameters = new Dictionary <string, object>(),
                };

                consumableParams.HeaderExtensions.Add(consumableExt);
            }

            // Clone Producer encodings since we'll mangle them.
            var consumableEncodings = parameters.Encodings.DeepClone <List <RtpEncodingParameters> >();

            for (var i = 0; i < consumableEncodings.Count; ++i)
            {
                var consumableEncoding = consumableEncodings[i];
                var mappedSsrc         = rtpMapping.Encodings[i].MappedSsrc;

                // Remove useless fields.
                // 在 Node.js 实现中,rid, rtx, codecPayloadType 被 delete 了。
                consumableEncoding.Rid = null;
                consumableEncoding.Rtx = null;
                consumableEncoding.CodecPayloadType = null;

                // Set the mapped ssrc.
                consumableEncoding.Ssrc = mappedSsrc;

                consumableParams.Encodings.Add(consumableEncoding);
            }

            consumableParams.Rtcp = new RtcpParameters
            {
                CNAME       = parameters.Rtcp.CNAME, // TODO: (alby)注意 null 引用
                ReducedSize = true,
                Mux         = true,
            };

            return(consumableParams);
        }