SDP中支持FEC
AssignPayloadTypesAndDefaultCodecs
设置本地SDP中支持RedFEC和UlpFEC
当前自己使用的webrtc版本的是 GetPayloadTypesAndDefaultCodecs
// This function will assign dynamic payload types (in the range [96, 127]) to// the input codecs, and also add ULPFEC, RED, FlexFEC, and associated RTX// codecs for recognized codecs (VP8, VP9, H264, and RED). It will also add// default feedback params to the codecs.// is_decoder_factory is needed to keep track of the implict assumption that any// H264 decoder also supports constrained base line profile.// Also, is_decoder_factory is used to decide whether FlexFEC video format// should be advertised as supported.// TODO(kron): Perhaps it is better to move the implicit knowledge to the place// where codecs are negotiated.template <class T>std::vector<VideoCodec> GetPayloadTypesAndDefaultCodecs(const T* factory,bool is_decoder_factory,const webrtc::WebRtcKeyValueConfig& trials) {if (!factory) {return {};}std::vector<webrtc::SdpVideoFormat> supported_formats =factory->GetSupportedFormats();if (is_decoder_factory) {AddH264ConstrainedBaselineProfileToSupportedFormats(&supported_formats);}if (supported_formats.empty())return std::vector<VideoCodec>();// Due to interoperability issues with old Chrome/WebRTC versions only use// the lower range for new codecs.static const int kFirstDynamicPayloadTypeLowerRange = 35;static const int kLastDynamicPayloadTypeLowerRange = 65;static const int kFirstDynamicPayloadTypeUpperRange = 96;static const int kLastDynamicPayloadTypeUpperRange = 127;int payload_type_upper = kFirstDynamicPayloadTypeUpperRange;int payload_type_lower = kFirstDynamicPayloadTypeLowerRange;supported_formats.push_back(webrtc::SdpVideoFormat(kRedCodecName));supported_formats.push_back(webrtc::SdpVideoFormat(kUlpfecCodecName));// flexfec-03 is supported as// - receive codec unless WebRTC-FlexFEC-03-Advertised is disabled// - send codec if WebRTC-FlexFEC-03-Advertised is enabledif ((is_decoder_factory &&!IsDisabled(trials, "WebRTC-FlexFEC-03-Advertised")) ||(!is_decoder_factory &&IsEnabled(trials, "WebRTC-FlexFEC-03-Advertised"))) {webrtc::SdpVideoFormat flexfec_format(kFlexfecCodecName);// This value is currently arbitrarily set to 10 seconds. (The unit// is microseconds.) This parameter MUST be present in the SDP, but// we never use the actual value anywhere in our code however.// TODO(brandtr): Consider honouring this value in the sender and receiver.flexfec_format.parameters = {{kFlexfecFmtpRepairWindow, "10000000"}};supported_formats.push_back(flexfec_format);}std::vector<VideoCodec> output_codecs;for (const webrtc::SdpVideoFormat& format : supported_formats) {VideoCodec codec(format);bool isCodecValidForLowerRange =absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName) ||absl::EqualsIgnoreCase(codec.name, kAv1CodecName);if (!isCodecValidForLowerRange) {codec.id = payload_type_upper++;} else {codec.id = payload_type_lower++;}AddDefaultFeedbackParams(&codec, trials);output_codecs.push_back(codec);if (payload_type_upper > kLastDynamicPayloadTypeUpperRange) {RTC_LOG(LS_ERROR)<< "Out of dynamic payload types [96,127], skipping the rest.";// TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12194):// continue in lower range.break;}if (payload_type_lower > kLastDynamicPayloadTypeLowerRange) {// TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12248):// return an error.RTC_LOG(LS_ERROR)<< "Out of dynamic payload types [35,65], skipping the rest.";break;}// Add associated RTX codec for non-FEC codecs.if (!absl::EqualsIgnoreCase(codec.name, kUlpfecCodecName) &&!absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName)) {if (!isCodecValidForLowerRange) {output_codecs.push_back(VideoCodec::CreateRtxCodec(payload_type_upper++, codec.id));} else {output_codecs.push_back(VideoCodec::CreateRtxCodec(payload_type_lower++, codec.id));}if (payload_type_upper > kLastDynamicPayloadTypeUpperRange) {RTC_LOG(LS_ERROR)<< "Out of dynamic payload types [96,127], skipping rtx.";// TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12194):// continue in lower range.break;}if (payload_type_lower > kLastDynamicPayloadTypeLowerRange) {// TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12248):// return an error.RTC_LOG(LS_ERROR)<< "Out of dynamic payload types [35,65], skipping rtx.";break;}}}return output_codecs;}
创建FEC控制器

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\video_coding\fec_controller_default.h
FecControllerDefault 函数: 计算和维护fec所有使用的参数
创建FEC对象

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\rtp_rtcp\source\forward_error_correction.h
std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateUlpfec(uint32_t ssrc)std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateFlexfec(uint32_t ssrc,uint32_t protected_media_ssrc)
MaybeCreateFecGenerator 函数判断创建redfec或者ulpfec
// TODO(brandtr): Update this function when we support multistream protection.std::unique_ptr<VideoFecGenerator> MaybeCreateFecGenerator(Clock* clock,const RtpConfig& rtp,const std::map<uint32_t, RtpState>& suspended_ssrcs,int simulcast_index,const WebRtcKeyValueConfig& trials) {// If flexfec is configured that takes priority.if (rtp.flexfec.payload_type >= 0) {RTC_DCHECK_GE(rtp.flexfec.payload_type, 0);RTC_DCHECK_LE(rtp.flexfec.payload_type, 127);if (rtp.flexfec.ssrc == 0) {RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. ""Therefore disabling FlexFEC.";return nullptr;}if (rtp.flexfec.protected_media_ssrcs.empty()) {RTC_LOG(LS_WARNING)<< "FlexFEC is enabled, but no protected media SSRC given. ""Therefore disabling FlexFEC.";return nullptr;}if (rtp.flexfec.protected_media_ssrcs.size() > 1) {RTC_LOG(LS_WARNING)<< "The supplied FlexfecConfig contained multiple protected ""media streams, but our implementation currently only ""supports protecting a single media stream. ""To avoid confusion, disabling FlexFEC completely.";return nullptr;}if (absl::c_find(rtp.flexfec.protected_media_ssrcs,rtp.ssrcs[simulcast_index]) ==rtp.flexfec.protected_media_ssrcs.end()) {// Media SSRC not among flexfec protected SSRCs.return nullptr;}const RtpState* rtp_state = nullptr;auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);if (it != suspended_ssrcs.end()) {rtp_state = &it->second;}RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());return std::make_unique<FlexfecSender>(rtp.flexfec.payload_type, rtp.flexfec.ssrc,rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,RTPSender::FecExtensionSizes(), rtp_state, clock);} else if (rtp.ulpfec.red_payload_type >= 0 &&rtp.ulpfec.ulpfec_payload_type >= 0 &&!ShouldDisableRedAndUlpfec(/*flexfec_enabled=*/false, rtp,trials)) {// Flexfec not configured, but ulpfec is and is not disabled.return std::make_unique<UlpfecGenerator>(rtp.ulpfec.red_payload_type, rtp.ulpfec.ulpfec_payload_type, clock);}// Not a single FEC is given.return nullptr;}
几个对象之间的关系

