image.png

1、拿到采集后的视频帧,交给编码器进行编码
2、编码后的数据交给On开头的函数回调传过去
3、然后来到RtpSenderVideo::SendVideo生成打包器,对拆包数据进行冗余计算打包
4、最后将原始数据和冗余数据一起打包发送出去。

SendVideo

image.png
num_packets 该帧数据可以打包为多少个包。
red_enabled() 默认返回0,因为webrtc默认开始redfec

AddpacketAndGenerateFec

image.png
// Maximum number of media packets that can be protected
// by these packet masks.
constexpr sizet kUlpfecMaxMediaPackets = 48;
fec冗余包生成好后,添加到ForwardErrorCorrection::PacketList media_packets
;容器中。
marker_bit :rtp包的m位是否已经值1.

  1. void UlpfecGenerator::AddPacketAndGenerateFec(const RtpPacketToSend& packet) {
  2. RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
  3. RTC_DCHECK(generated_fec_packets_.empty());
  4. {
  5. MutexLock lock(&mutex_);
  6. if (pending_params_) {
  7. current_params_ = *pending_params_;
  8. pending_params_.reset();
  9. if (CurrentParams().fec_rate > kHighProtectionThreshold) {
  10. min_num_media_packets_ = kMinMediaPackets;
  11. } else {
  12. min_num_media_packets_ = 1;
  13. }
  14. }
  15. }
  16. if (packet.is_key_frame()) {
  17. media_contains_keyframe_ = true;
  18. }
  19. const bool complete_frame = packet.Marker();
  20. if (media_packets_.size() < kUlpfecMaxMediaPackets) {
  21. // Our packet masks can only protect up to |kUlpfecMaxMediaPackets| packets.
  22. auto fec_packet = std::make_unique<ForwardErrorCorrection::Packet>();
  23. fec_packet->data = packet.Buffer();
  24. media_packets_.push_back(std::move(fec_packet));
  25. // Keep a copy of the last RTP packet, so we can copy the RTP header
  26. // from it when creating newly generated ULPFEC+RED packets.
  27. RTC_DCHECK_GE(packet.headers_size(), kRtpHeaderSize);
  28. last_media_packet_ = packet;
  29. }
  30. if (complete_frame) {
  31. ++num_protected_frames_;
  32. }
  33. auto params = CurrentParams();
  34. // Produce FEC over at most |params_.max_fec_frames| frames, or as soon as:
  35. // (1) the excess overhead (actual overhead - requested/target overhead) is
  36. // less than |kMaxExcessOverhead|, and
  37. // (2) at least |min_num_media_packets_| media packets is reached.
  38. if (complete_frame &&
  39. (num_protected_frames_ >= params.max_fec_frames ||
  40. (ExcessOverheadBelowMax() && MinimumMediaPacketsReached()))) {
  41. // We are not using Unequal Protection feature of the parity erasure code.
  42. constexpr int kNumImportantPackets = 0;
  43. constexpr bool kUseUnequalProtection = false;
  44. fec_->EncodeFec(media_packets_, params.fec_rate, kNumImportantPackets,
  45. kUseUnequalProtection, params.fec_mask_type,
  46. &generated_fec_packets_);
  47. if (generated_fec_packets_.empty()) {
  48. ResetState();
  49. }
  50. }
  51. }

EncodeFec

image.png

ForwardErrorCorrection::GenerateFecPayloads

  1. void ForwardErrorCorrection::GenerateFecPayloads(
  2. const PacketList& media_packets,
  3. size_t num_fec_packets) {
  4. RTC_DCHECK(!media_packets.empty());
  5. for (size_t i = 0; i < num_fec_packets; ++i) {
  6. Packet* const fec_packet = &generated_fec_packets_[i];
  7. size_t pkt_mask_idx = i * packet_mask_size_;
  8. const size_t min_packet_mask_size = fec_header_writer_->MinPacketMaskSize(
  9. &packet_masks_[pkt_mask_idx], packet_mask_size_);
  10. const size_t fec_header_size =
  11. fec_header_writer_->FecHeaderSize(min_packet_mask_size);
  12. size_t media_pkt_idx = 0;
  13. auto media_packets_it = media_packets.cbegin();
  14. uint16_t prev_seq_num =
  15. ParseSequenceNumber((*media_packets_it)->data.data());
  16. while (media_packets_it != media_packets.end()) {
  17. Packet* const media_packet = media_packets_it->get();
  18. const uint8_t* media_packet_data = media_packet->data.cdata();
  19. // Should |media_packet| be protected by |fec_packet|?
  20. if (packet_masks_[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) {
  21. size_t media_payload_length =
  22. media_packet->data.size() - kRtpHeaderSize;
  23. bool first_protected_packet = (fec_packet->data.size() == 0);
  24. size_t fec_packet_length = fec_header_size + media_payload_length;
  25. if (fec_packet_length > fec_packet->data.size()) {
  26. // Recall that XORing with zero (which the FEC packets are prefilled
  27. // with) is the identity operator, thus all prior XORs are
  28. // still correct even though we expand the packet length here.
  29. fec_packet->data.SetSize(fec_packet_length);
  30. }
  31. if (first_protected_packet) {
  32. uint8_t* data = fec_packet->data.MutableData();
  33. // Write P, X, CC, M, and PT recovery fields.
  34. // Note that bits 0, 1, and 16 are overwritten in FinalizeFecHeaders.
  35. memcpy(&data[0], &media_packet_data[0], 2);
  36. // Write length recovery field. (This is a temporary location for
  37. // ULPFEC.)
  38. ByteWriter<uint16_t>::WriteBigEndian(&data[2], media_payload_length);
  39. // Write timestamp recovery field.
  40. memcpy(&data[4], &media_packet_data[4], 4);
  41. // Write payload.
  42. if (media_payload_length > 0) {
  43. memcpy(&data[fec_header_size], &media_packet_data[kRtpHeaderSize],
  44. media_payload_length);
  45. }
  46. } else {
  47. XorHeaders(*media_packet, fec_packet);
  48. XorPayloads(*media_packet, media_payload_length, fec_header_size,
  49. fec_packet);
  50. }
  51. }
  52. media_packets_it++;
  53. if (media_packets_it != media_packets.end()) {
  54. uint16_t seq_num =
  55. ParseSequenceNumber((*media_packets_it)->data.data());
  56. media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num);
  57. prev_seq_num = seq_num;
  58. }
  59. pkt_mask_idx += media_pkt_idx / 8;
  60. media_pkt_idx %= 8;
  61. }
  62. RTC_DCHECK_GT(fec_packet->data.size(), 0)
  63. << "Packet mask is wrong or poorly designed.";
  64. }
  65. }