posts

vnn01

Ulpfec_Receiver_ProcessReceivedFec

tags
webrtc Ulpfec_dec

总结

  • UlpfecReceiver::ProcessReceivedFec
  • 将缓存的ForwardEorrorCorrection::Packet媒体包以RtpPacketReceived格式回调给recovered_packet_callback,并尝试调用ForwardErrorCorrection::DecodeFec恢复数据。 统一将恢复出来数据包,回调给recovered_packet_callback。

序列图

细节序列图

相关代码

void UlpfecReceiver::ProcessReceivedFec() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);

  // If we iterate over `received_packets_` and it contains a packet that cause
  // us to recurse back to this function (for example a RED packet encapsulating
  // a RED packet), then we will recurse forever. To avoid this we swap
  // `received_packets_` with an empty vector so that the next recursive call
  // wont iterate over the same packet again. This also solves the problem of
  // not modifying the vector we are currently iterating over (packets are added
  // in AddReceivedRedPacket).
  std::vector<std::unique_ptr<ForwardErrorCorrection::ReceivedPacket>>
      received_packets;
  received_packets.swap(received_packets_);
  RtpHeaderExtensionMap* last_recovered_extension_map = nullptr;
  size_t num_recovered_packets = 0;

  for (const auto& received_packet : received_packets) {
    // Send received media packet to VCM.
    if (!received_packet->is_fec) {
      ForwardErrorCorrection::Packet* packet = received_packet->pkt.get();

      RtpPacketReceived rtp_packet(&received_packet->extensions);
      if (!rtp_packet.Parse(std::move(packet->data))) {
        RTC_LOG(LS_WARNING) << "Corrupted media packet";
        continue;
      }
      recovered_packet_callback_->OnRecoveredPacket(rtp_packet);
      // Some header extensions need to be zeroed in `received_packet` since
      // they are written to the packet after FEC encoding. We try to do it
      // without a copy of the underlying Copy-On-Write buffer, but if a
      // reference is held by `recovered_packet_callback_->OnRecoveredPacket` a
      // copy will still be made in 'rtp_packet.ZeroMutableExtensions()'.
      rtp_packet.ZeroMutableExtensions();
      packet->data = rtp_packet.Buffer();
    }
    if (!received_packet->is_recovered) {
      // Do not pass recovered packets to FEC. Recovered packet might have
      // different set of the RTP header extensions and thus different byte
      // representation than the original packet, That will corrupt
      // FEC calculation.
      ForwardErrorCorrection::DecodeFecResult decode_result =
          fec_->DecodeFec(*received_packet, &recovered_packets_);
      last_recovered_extension_map = &received_packet->extensions;
      num_recovered_packets += decode_result.num_recovered_packets;
    }
  }

  if (num_recovered_packets == 0) {
    return;
  }

  // Send any recovered media packets to VCM.
  for (const auto& recovered_packet : recovered_packets_) {
    if (recovered_packet->returned) {
      // Already sent to the VCM and the jitter buffer.
      continue;
    }
    ForwardErrorCorrection::Packet* packet = recovered_packet->pkt.get();
    ++packet_counter_.num_recovered_packets;
    // Set this flag first; in case the recovered packet carries a RED
    // header, OnRecoveredPacket will recurse back here.
    recovered_packet->returned = true;
    RtpPacketReceived parsed_packet(last_recovered_extension_map);
    if (!parsed_packet.Parse(packet->data)) {
      continue;
    }
    parsed_packet.set_recovered(true);
    recovered_packet_callback_->OnRecoveredPacket(parsed_packet);
  }
}

Links to this note