bool UlpfecReceiver::AddReceivedRedPacket(const RtpPacketReceived& rtp_packet) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
// TODO(bugs.webrtc.org/11993): We get here via Call::DeliverRtp, so should be
// moved to the network thread.
if (rtp_packet.Ssrc() != ssrc_) {
RTC_LOG(LS_WARNING)
<<"Received RED packet with different SSRC than expected; dropping.";
returnfalse;
}
if (rtp_packet.size() > IP_PACKET_SIZE) {
RTC_LOG(LS_WARNING) <<"Received RED packet with length exceeds maximum IP ""packet size; dropping.";
returnfalse;
}
staticconstexpruint8_t kRedHeaderLength =1;
if (rtp_packet.payload_size() ==0) {
RTC_LOG(LS_WARNING) <<"Corrupt/truncated FEC packet.";
returnfalse;
}
// Remove RED header of incoming packet and store as a virtual RTP packet.
auto received_packet = std::make_unique<ForwardErrorCorrection::ReceivedPacket>();
received_packet->pkt =new ForwardErrorCorrection::Packet();
// Get payload type from RED header and sequence number from RTP header.
uint8_t payload_type = rtp_packet.payload()[0] &0x7f;
received_packet->is_fec = payload_type == ulpfec_payload_type_;
received_packet->is_recovered = rtp_packet.recovered();
received_packet->ssrc = rtp_packet.Ssrc();
received_packet->seq_num = rtp_packet.SequenceNumber();
received_packet->extensions = rtp_packet.extension_manager();
if (rtp_packet.payload()[0] &0x80) {
// f bit set in RED header, i.e. there are more than one RED header blocks.
// WebRTC never generates multiple blocks in a RED packet for FEC.
RTC_LOG(LS_WARNING) <<"More than 1 block in RED packet is not supported.";
returnfalse;
}
++packet_counter_.num_packets;
packet_counter_.num_bytes += rtp_packet.size();
if (packet_counter_.first_packet_time == Timestamp::MinusInfinity()) {
packet_counter_.first_packet_time = clock_->CurrentTime();
}
if (received_packet->is_fec) {
++packet_counter_.num_fec_packets;
// everything behind the RED header
received_packet->pkt->data = rtp_packet.Buffer().Slice(rtp_packet.headers_size() + kRedHeaderLength,
rtp_packet.payload_size() - kRedHeaderLength);
} else {
received_packet->pkt->data.EnsureCapacity(rtp_packet.size() - kRedHeaderLength);
// Copy RTP header.
received_packet->pkt->data.SetData(rtp_packet.data(),
rtp_packet.headers_size());
// Set payload type.
uint8_t& payload_type_byte = received_packet->pkt->data.MutableData()[1];
payload_type_byte &=0x80; // Reset RED payload type.
payload_type_byte += payload_type; // Set media payload type.
// Copy payload and padding data, after the RED header.
received_packet->pkt->data.AppendData(
rtp_packet.data() + rtp_packet.headers_size() + kRedHeaderLength,
rtp_packet.size() - rtp_packet.headers_size() - kRedHeaderLength);
}
if (received_packet->pkt->data.size() >0) {
received_packets_.push_back(std::move(received_packet));
}
returntrue;
}
视频RED封装
bool RTPSenderVideo::SendVideo(int payload_type,
std::optional<VideoCodecType> codec_type,
uint32_t rtp_timestamp,
Timestamp capture_time,
ArrayView<constuint8_t> payload,
size_t encoder_output_size,
RTPVideoHeader video_header,
TimeDelta expected_retransmission_time,
std::vector<uint32_t> csrcs) {
...
if (red_enabled()) {
// TODO(sprang): Consider packetizing directly into packets with the RED
// header already in place, to avoid this copy.
std::unique_ptr<RtpPacketToSend> red_packet(new RtpPacketToSend(*packet));
BuildRedPayload(*packet, red_packet.get());
red_packet->SetPayloadType(*red_payload_type_);
red_packet->set_is_red(true);
// Append `red_packet` instead of `packet` to output.
red_packet->set_packet_type(RtpPacketMediaType::kVideo);
red_packet->set_allow_retransmission(packet->allow_retransmission());
rtp_packets.emplace_back(std::move(red_packet));
} ß...
}