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

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

// 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.
void UlpfecGenerator::AddPacketAndGenerateFec(const RtpPacketToSend& packet) {RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);RTC_DCHECK(generated_fec_packets_.empty());{MutexLock lock(&mutex_);if (pending_params_) {current_params_ = *pending_params_;pending_params_.reset();if (CurrentParams().fec_rate > kHighProtectionThreshold) {min_num_media_packets_ = kMinMediaPackets;} else {min_num_media_packets_ = 1;}}}if (packet.is_key_frame()) {media_contains_keyframe_ = true;}const bool complete_frame = packet.Marker();if (media_packets_.size() < kUlpfecMaxMediaPackets) {// Our packet masks can only protect up to |kUlpfecMaxMediaPackets| packets.auto fec_packet = std::make_unique<ForwardErrorCorrection::Packet>();fec_packet->data = packet.Buffer();media_packets_.push_back(std::move(fec_packet));// Keep a copy of the last RTP packet, so we can copy the RTP header// from it when creating newly generated ULPFEC+RED packets.RTC_DCHECK_GE(packet.headers_size(), kRtpHeaderSize);last_media_packet_ = packet;}if (complete_frame) {++num_protected_frames_;}auto params = CurrentParams();// Produce FEC over at most |params_.max_fec_frames| frames, or as soon as:// (1) the excess overhead (actual overhead - requested/target overhead) is// less than |kMaxExcessOverhead|, and// (2) at least |min_num_media_packets_| media packets is reached.if (complete_frame &&(num_protected_frames_ >= params.max_fec_frames ||(ExcessOverheadBelowMax() && MinimumMediaPacketsReached()))) {// We are not using Unequal Protection feature of the parity erasure code.constexpr int kNumImportantPackets = 0;constexpr bool kUseUnequalProtection = false;fec_->EncodeFec(media_packets_, params.fec_rate, kNumImportantPackets,kUseUnequalProtection, params.fec_mask_type,&generated_fec_packets_);if (generated_fec_packets_.empty()) {ResetState();}}}
EncodeFec
ForwardErrorCorrection::GenerateFecPayloads
void ForwardErrorCorrection::GenerateFecPayloads(const PacketList& media_packets,size_t num_fec_packets) {RTC_DCHECK(!media_packets.empty());for (size_t i = 0; i < num_fec_packets; ++i) {Packet* const fec_packet = &generated_fec_packets_[i];size_t pkt_mask_idx = i * packet_mask_size_;const size_t min_packet_mask_size = fec_header_writer_->MinPacketMaskSize(&packet_masks_[pkt_mask_idx], packet_mask_size_);const size_t fec_header_size =fec_header_writer_->FecHeaderSize(min_packet_mask_size);size_t media_pkt_idx = 0;auto media_packets_it = media_packets.cbegin();uint16_t prev_seq_num =ParseSequenceNumber((*media_packets_it)->data.data());while (media_packets_it != media_packets.end()) {Packet* const media_packet = media_packets_it->get();const uint8_t* media_packet_data = media_packet->data.cdata();// Should |media_packet| be protected by |fec_packet|?if (packet_masks_[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) {size_t media_payload_length =media_packet->data.size() - kRtpHeaderSize;bool first_protected_packet = (fec_packet->data.size() == 0);size_t fec_packet_length = fec_header_size + media_payload_length;if (fec_packet_length > fec_packet->data.size()) {// Recall that XORing with zero (which the FEC packets are prefilled// with) is the identity operator, thus all prior XORs are// still correct even though we expand the packet length here.fec_packet->data.SetSize(fec_packet_length);}if (first_protected_packet) {uint8_t* data = fec_packet->data.MutableData();// Write P, X, CC, M, and PT recovery fields.// Note that bits 0, 1, and 16 are overwritten in FinalizeFecHeaders.memcpy(&data[0], &media_packet_data[0], 2);// Write length recovery field. (This is a temporary location for// ULPFEC.)ByteWriter<uint16_t>::WriteBigEndian(&data[2], media_payload_length);// Write timestamp recovery field.memcpy(&data[4], &media_packet_data[4], 4);// Write payload.if (media_payload_length > 0) {memcpy(&data[fec_header_size], &media_packet_data[kRtpHeaderSize],media_payload_length);}} else {XorHeaders(*media_packet, fec_packet);XorPayloads(*media_packet, media_payload_length, fec_header_size,fec_packet);}}media_packets_it++;if (media_packets_it != media_packets.end()) {uint16_t seq_num =ParseSequenceNumber((*media_packets_it)->data.data());media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num);prev_seq_num = seq_num;}pkt_mask_idx += media_pkt_idx / 8;media_pkt_idx %= 8;}RTC_DCHECK_GT(fec_packet->data.size(), 0)<< "Packet mask is wrong or poorly designed.";}}
