SDP中支持FEC

image.png

AssignPayloadTypesAndDefaultCodecs

设置本地SDP中支持RedFEC和UlpFEC
image.png
当前自己使用的webrtc版本的是 GetPayloadTypesAndDefaultCodecs

  1. // This function will assign dynamic payload types (in the range [96, 127]) to
  2. // the input codecs, and also add ULPFEC, RED, FlexFEC, and associated RTX
  3. // codecs for recognized codecs (VP8, VP9, H264, and RED). It will also add
  4. // default feedback params to the codecs.
  5. // is_decoder_factory is needed to keep track of the implict assumption that any
  6. // H264 decoder also supports constrained base line profile.
  7. // Also, is_decoder_factory is used to decide whether FlexFEC video format
  8. // should be advertised as supported.
  9. // TODO(kron): Perhaps it is better to move the implicit knowledge to the place
  10. // where codecs are negotiated.
  11. template <class T>
  12. std::vector<VideoCodec> GetPayloadTypesAndDefaultCodecs(
  13. const T* factory,
  14. bool is_decoder_factory,
  15. const webrtc::WebRtcKeyValueConfig& trials) {
  16. if (!factory) {
  17. return {};
  18. }
  19. std::vector<webrtc::SdpVideoFormat> supported_formats =
  20. factory->GetSupportedFormats();
  21. if (is_decoder_factory) {
  22. AddH264ConstrainedBaselineProfileToSupportedFormats(&supported_formats);
  23. }
  24. if (supported_formats.empty())
  25. return std::vector<VideoCodec>();
  26. // Due to interoperability issues with old Chrome/WebRTC versions only use
  27. // the lower range for new codecs.
  28. static const int kFirstDynamicPayloadTypeLowerRange = 35;
  29. static const int kLastDynamicPayloadTypeLowerRange = 65;
  30. static const int kFirstDynamicPayloadTypeUpperRange = 96;
  31. static const int kLastDynamicPayloadTypeUpperRange = 127;
  32. int payload_type_upper = kFirstDynamicPayloadTypeUpperRange;
  33. int payload_type_lower = kFirstDynamicPayloadTypeLowerRange;
  34. supported_formats.push_back(webrtc::SdpVideoFormat(kRedCodecName));
  35. supported_formats.push_back(webrtc::SdpVideoFormat(kUlpfecCodecName));
  36. // flexfec-03 is supported as
  37. // - receive codec unless WebRTC-FlexFEC-03-Advertised is disabled
  38. // - send codec if WebRTC-FlexFEC-03-Advertised is enabled
  39. if ((is_decoder_factory &&
  40. !IsDisabled(trials, "WebRTC-FlexFEC-03-Advertised")) ||
  41. (!is_decoder_factory &&
  42. IsEnabled(trials, "WebRTC-FlexFEC-03-Advertised"))) {
  43. webrtc::SdpVideoFormat flexfec_format(kFlexfecCodecName);
  44. // This value is currently arbitrarily set to 10 seconds. (The unit
  45. // is microseconds.) This parameter MUST be present in the SDP, but
  46. // we never use the actual value anywhere in our code however.
  47. // TODO(brandtr): Consider honouring this value in the sender and receiver.
  48. flexfec_format.parameters = {{kFlexfecFmtpRepairWindow, "10000000"}};
  49. supported_formats.push_back(flexfec_format);
  50. }
  51. std::vector<VideoCodec> output_codecs;
  52. for (const webrtc::SdpVideoFormat& format : supported_formats) {
  53. VideoCodec codec(format);
  54. bool isCodecValidForLowerRange =
  55. absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName) ||
  56. absl::EqualsIgnoreCase(codec.name, kAv1CodecName);
  57. if (!isCodecValidForLowerRange) {
  58. codec.id = payload_type_upper++;
  59. } else {
  60. codec.id = payload_type_lower++;
  61. }
  62. AddDefaultFeedbackParams(&codec, trials);
  63. output_codecs.push_back(codec);
  64. if (payload_type_upper > kLastDynamicPayloadTypeUpperRange) {
  65. RTC_LOG(LS_ERROR)
  66. << "Out of dynamic payload types [96,127], skipping the rest.";
  67. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12194):
  68. // continue in lower range.
  69. break;
  70. }
  71. if (payload_type_lower > kLastDynamicPayloadTypeLowerRange) {
  72. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12248):
  73. // return an error.
  74. RTC_LOG(LS_ERROR)
  75. << "Out of dynamic payload types [35,65], skipping the rest.";
  76. break;
  77. }
  78. // Add associated RTX codec for non-FEC codecs.
  79. if (!absl::EqualsIgnoreCase(codec.name, kUlpfecCodecName) &&
  80. !absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName)) {
  81. if (!isCodecValidForLowerRange) {
  82. output_codecs.push_back(
  83. VideoCodec::CreateRtxCodec(payload_type_upper++, codec.id));
  84. } else {
  85. output_codecs.push_back(
  86. VideoCodec::CreateRtxCodec(payload_type_lower++, codec.id));
  87. }
  88. if (payload_type_upper > kLastDynamicPayloadTypeUpperRange) {
  89. RTC_LOG(LS_ERROR)
  90. << "Out of dynamic payload types [96,127], skipping rtx.";
  91. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12194):
  92. // continue in lower range.
  93. break;
  94. }
  95. if (payload_type_lower > kLastDynamicPayloadTypeLowerRange) {
  96. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12248):
  97. // return an error.
  98. RTC_LOG(LS_ERROR)
  99. << "Out of dynamic payload types [35,65], skipping rtx.";
  100. break;
  101. }
  102. }
  103. }
  104. return output_codecs;
  105. }

创建FEC控制器

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

创建FEC对象

image.png
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\rtp_rtcp\source\forward_error_correction.h

  1. std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateUlpfec(
  2. uint32_t ssrc)
  3. std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateFlexfec(
  4. uint32_t ssrc,
  5. uint32_t protected_media_ssrc)

MaybeCreateFecGenerator 函数判断创建redfec或者ulpfec

  1. // TODO(brandtr): Update this function when we support multistream protection.
  2. std::unique_ptr<VideoFecGenerator> MaybeCreateFecGenerator(
  3. Clock* clock,
  4. const RtpConfig& rtp,
  5. const std::map<uint32_t, RtpState>& suspended_ssrcs,
  6. int simulcast_index,
  7. const WebRtcKeyValueConfig& trials) {
  8. // If flexfec is configured that takes priority.
  9. if (rtp.flexfec.payload_type >= 0) {
  10. RTC_DCHECK_GE(rtp.flexfec.payload_type, 0);
  11. RTC_DCHECK_LE(rtp.flexfec.payload_type, 127);
  12. if (rtp.flexfec.ssrc == 0) {
  13. RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
  14. "Therefore disabling FlexFEC.";
  15. return nullptr;
  16. }
  17. if (rtp.flexfec.protected_media_ssrcs.empty()) {
  18. RTC_LOG(LS_WARNING)
  19. << "FlexFEC is enabled, but no protected media SSRC given. "
  20. "Therefore disabling FlexFEC.";
  21. return nullptr;
  22. }
  23. if (rtp.flexfec.protected_media_ssrcs.size() > 1) {
  24. RTC_LOG(LS_WARNING)
  25. << "The supplied FlexfecConfig contained multiple protected "
  26. "media streams, but our implementation currently only "
  27. "supports protecting a single media stream. "
  28. "To avoid confusion, disabling FlexFEC completely.";
  29. return nullptr;
  30. }
  31. if (absl::c_find(rtp.flexfec.protected_media_ssrcs,
  32. rtp.ssrcs[simulcast_index]) ==
  33. rtp.flexfec.protected_media_ssrcs.end()) {
  34. // Media SSRC not among flexfec protected SSRCs.
  35. return nullptr;
  36. }
  37. const RtpState* rtp_state = nullptr;
  38. auto it = suspended_ssrcs.find(rtp.flexfec.ssrc);
  39. if (it != suspended_ssrcs.end()) {
  40. rtp_state = &it->second;
  41. }
  42. RTC_DCHECK_EQ(1U, rtp.flexfec.protected_media_ssrcs.size());
  43. return std::make_unique<FlexfecSender>(
  44. rtp.flexfec.payload_type, rtp.flexfec.ssrc,
  45. rtp.flexfec.protected_media_ssrcs[0], rtp.mid, rtp.extensions,
  46. RTPSender::FecExtensionSizes(), rtp_state, clock);
  47. } else if (rtp.ulpfec.red_payload_type >= 0 &&
  48. rtp.ulpfec.ulpfec_payload_type >= 0 &&
  49. !ShouldDisableRedAndUlpfec(/*flexfec_enabled=*/false, rtp,
  50. trials)) {
  51. // Flexfec not configured, but ulpfec is and is not disabled.
  52. return std::make_unique<UlpfecGenerator>(
  53. rtp.ulpfec.red_payload_type, rtp.ulpfec.ulpfec_payload_type, clock);
  54. }
  55. // Not a single FEC is given.
  56. return nullptr;
  57. }

几个对象之间的关系

image.png