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.";
}
}