posts

vnn01

Ulpfec_Generator_GetFecPackets

tags
webrtc

总结

  • UlpfecGenerator::GetFecPackets
  • GetFecPackets 负责将已生成的 FEC 包(generated_fec_packets_)全部封装成 RTP RED 包返回。RTP 头部全部复用最后一个媒体包(last_media_packet_)。如果没有 FEC 包,直接返回空。每次调用后内部状态会被重置,并更新 FEC 发送速率统计。
  • RTP RED包的说明:https://tools.ietf.org/html/rfc2198

概况序列图

细节序列图

代码

std::vector<std::unique_ptr<RtpPacketToSend>> UlpfecGenerator::GetFecPackets() {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
  if (generated_fec_packets_.empty()) {
    return std::vector<std::unique_ptr<RtpPacketToSend>>();
  }

  // Wrap FEC packet (including FEC headers) in a RED packet. Since the
  // FEC packets in `generated_fec_packets_` don't have RTP headers, we
  // reuse the header from the last media packet.
  RTC_CHECK(last_media_packet_.has_value());
  last_media_packet_->SetPayloadSize(0);

  std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets;
  fec_packets.reserve(generated_fec_packets_.size());

  size_t total_fec_size_bytes = 0;
  for (const auto* fec_packet : generated_fec_packets_) {
    std::unique_ptr<RtpPacketToSend> red_packet =
        std::make_unique<RtpPacketToSend>(*last_media_packet_);
    red_packet->SetPayloadType(red_payload_type_);      //设置payload!
    red_packet->SetMarker(false);
    uint8_t* payload_buffer = red_packet->SetPayloadSize(
        kRedForFecHeaderLength + fec_packet->data.size());
    // Primary RED header with F bit unset.
    // See https://tools.ietf.org/html/rfc2198#section-3
    payload_buffer[0] = ulpfec_payload_type_;  // RED header.
    memcpy(&payload_buffer[1], fec_packet->data.data(),
           fec_packet->data.size());
    total_fec_size_bytes += red_packet->size();
    red_packet->set_packet_type(RtpPacketMediaType::kForwardErrorCorrection);
    red_packet->set_allow_retransmission(false);
    red_packet->set_is_red(true);
    red_packet->set_fec_protect_packet(false);
    fec_packets.push_back(std::move(red_packet));
  }

  ResetState();

  MutexLock lock(&mutex_);
  fec_bitrate_.Update(total_fec_size_bytes, env_.clock().CurrentTime());

  return fec_packets;
}

思考

  • FEC包的序号这里没有设置,在哪里设置?
    • ModuleRtpRtcpImpl2::AssignSequenceNumber
void ModuleRtpRtcpImpl2::AssignSequenceNumber(RtpPacketToSend& packet) {
  RTC_DCHECK_RUN_ON(&rtp_sender_->sequencing_checker);
  bool is_flexfec =
      packet.packet_type() == RtpPacketMediaType::kForwardErrorCorrection &&
      packet.Ssrc() == rtp_sender_->packet_generator.FlexfecSsrc();
  if (!is_flexfec) {
    rtp_sender_->sequencer.Sequence(packet);
  }
}

Links to this note