[feat] modify the implementation of rtx packet

This commit is contained in:
dijunkun
2025-03-31 17:34:28 +08:00
parent 794d57eb40
commit f9717f8481
8 changed files with 166 additions and 17 deletions

View File

@@ -29,6 +29,11 @@ class CopyOnWriteBuffer {
buffer_ = std::make_shared<std::vector<uint8_t>>(data, data + size); buffer_ = std::make_shared<std::vector<uint8_t>>(data, data + size);
} }
void InsertDataAt(size_t offset, const uint8_t* data, size_t size) {
EnsureUnique();
buffer_->insert(buffer_->begin() + offset, data, data + size);
}
const uint8_t* data() const { return buffer_ ? buffer_->data() : nullptr; } const uint8_t* data() const { return buffer_ ? buffer_->data() : nullptr; }
size_t size() const { return buffer_ ? buffer_->size() : 0; } size_t size() const { return buffer_ ? buffer_->size() : 0; }

View File

@@ -239,6 +239,12 @@ class RtpPacket {
} }
public: public:
struct Extension {
uint8_t id;
uint8_t len;
std::vector<uint8_t> data;
};
// Get Header // Get Header
uint32_t Version() const { return version_; } uint32_t Version() const { return version_; }
bool HasPadding() const { return has_padding_; } bool HasPadding() const { return has_padding_; }
@@ -252,6 +258,8 @@ class RtpPacket {
uint32_t Ssrc() const { return ssrc_; } uint32_t Ssrc() const { return ssrc_; }
std::vector<uint32_t> Csrcs() const { return csrcs_; }; std::vector<uint32_t> Csrcs() const { return csrcs_; };
uint16_t ExtensionProfile() const { return extension_profile_; } uint16_t ExtensionProfile() const { return extension_profile_; }
uint16_t ExtensionLen() const { return extension_len_; }
std::vector<Extension> Extensions() const { return extensions_; }
uint32_t GetAbsoluteSendTimestamp(uint32_t *abs_send_time) const { uint32_t GetAbsoluteSendTimestamp(uint32_t *abs_send_time) const {
if (!extensions_.empty()) { if (!extensions_.empty()) {
@@ -305,11 +313,6 @@ class RtpPacket {
// Extension header // Extension header
uint16_t extension_profile_ = 0; uint16_t extension_profile_ = 0;
uint16_t extension_len_ = 0; uint16_t extension_len_ = 0;
struct Extension {
uint8_t id;
uint8_t len;
std::vector<uint8_t> data;
};
std::vector<Extension> extensions_; std::vector<Extension> extensions_;
// Payload // Payload

View File

@@ -34,4 +34,97 @@ void RtpPacketToSend::set_packet_type(RtpPacketMediaType type) {
packet_type_ = type; packet_type_ = type;
} }
void AddAbsSendTimeExtension(std::vector<uint8_t>& rtp_packet_frame) {
uint16_t extension_profile = 0xBEDE; // One-byte header extension
uint8_t sub_extension_id = 3; // ID for Absolute Send Time
uint8_t sub_extension_length =
2; // Length of the extension data in bytes minus 1
uint32_t abs_send_time =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
abs_send_time &= 0x00FFFFFF; // Absolute Send Time is 24 bits
// Add extension profile
rtp_packet_frame.push_back((extension_profile >> 8) & 0xFF);
rtp_packet_frame.push_back(extension_profile & 0xFF);
// Add extension length (in 32-bit words, minus one)
rtp_packet_frame.push_back(
0x00); // Placeholder for length, will be updated later
rtp_packet_frame.push_back(0x01); // One 32-bit word
// Add Absolute Send Time extension
rtp_packet_frame.push_back((sub_extension_id << 4) | sub_extension_length);
rtp_packet_frame.push_back((abs_send_time >> 16) & 0xFF);
rtp_packet_frame.push_back((abs_send_time >> 8) & 0xFF);
rtp_packet_frame.push_back(abs_send_time & 0xFF);
}
bool RtpPacketToSend::BuildRtxPacket() {
if (!retransmitted_sequence_number_.has_value()) {
return false;
}
uint8_t version = Version();
uint8_t has_padding = HasPadding();
uint8_t has_extension = HasExtension();
uint8_t csrc_count = Csrcs().size();
bool marker = Marker();
uint8_t payload_type = PayloadType();
uint16_t sequence_number = SequenceNumber();
uint32_t ssrc = Ssrc();
std::vector<uint32_t> csrcs = Csrcs();
uint32_t timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
if (!csrc_count) {
}
SetPayloadType(rtp::PAYLOAD_TYPE::RTX);
rtp_packet_frame_.clear();
rtp_packet_frame_.push_back((version << 6) | (has_padding << 5) |
(has_extension << 4) | csrc_count);
rtp_packet_frame_.push_back((marker << 7) | payload_type);
rtp_packet_frame_.push_back((sequence_number >> 8) & 0xFF);
rtp_packet_frame_.push_back(sequence_number & 0xFF);
rtp_packet_frame_.push_back((timestamp >> 24) & 0xFF);
rtp_packet_frame_.push_back((timestamp >> 16) & 0xFF);
rtp_packet_frame_.push_back((timestamp >> 8) & 0xFF);
rtp_packet_frame_.push_back(timestamp & 0xFF);
rtp_packet_frame_.push_back((ssrc >> 24) & 0xFF);
rtp_packet_frame_.push_back((ssrc >> 16) & 0xFF);
rtp_packet_frame_.push_back((ssrc >> 8) & 0xFF);
rtp_packet_frame_.push_back(ssrc & 0xFF);
for (uint32_t index = 0; index < csrc_count && !csrcs.empty(); index++) {
rtp_packet_frame_.push_back((csrcs[index] >> 24) & 0xFF);
rtp_packet_frame_.push_back((csrcs[index] >> 16) & 0xFF);
rtp_packet_frame_.push_back((csrcs[index] >> 8) & 0xFF);
rtp_packet_frame_.push_back(csrcs[index] & 0xFF);
}
if (has_extension) {
std::vector<Extension> extensions = Extensions();
AddAbsSendTimeExtension(rtp_packet_frame_);
uint32_t abs_send_time = 0;
LOG_WARN("abs {}", GetAbsoluteSendTimestamp(&abs_send_time));
}
rtp_packet_frame_.push_back((retransmitted_sequence_number_.value() >> 8) &
0xFF);
rtp_packet_frame_.push_back(retransmitted_sequence_number_.value() & 0xFF);
rtp_packet_frame_.insert(rtp_packet_frame_.end(), Payload(),
Payload() + PayloadSize());
Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
return true;
}
} // namespace webrtc } // namespace webrtc

View File

@@ -44,6 +44,8 @@ class RtpPacketToSend : public ::RtpPacket {
~RtpPacketToSend(); ~RtpPacketToSend();
bool BuildRtxPacket();
// Time in local time base as close as it can to frame capture time. // Time in local time base as close as it can to frame capture time.
webrtc::Timestamp capture_time() const { return capture_time_; } webrtc::Timestamp capture_time() const { return capture_time_; }
void set_capture_time(webrtc::Timestamp time) { capture_time_ = time; } void set_capture_time(webrtc::Timestamp time) { capture_time_ = time; }
@@ -169,6 +171,9 @@ class RtpPacketToSend : public ::RtpPacket {
bool is_red_ = false; bool is_red_ = false;
bool send_as_ect1_ = false; bool send_as_ect1_ = false;
std::optional<TimeDelta> time_in_send_queue_; std::optional<TimeDelta> time_in_send_queue_;
private:
std::vector<uint8_t> rtp_packet_frame_;
}; };
} // namespace webrtc } // namespace webrtc

View File

@@ -0,0 +1,32 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-03-31
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _RTX_PACKET_H_
#define _RTX_PACKET_H_
#include "rtp_packet.h"
#include "rtp_packet_to_send.h"
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | RTP Header |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | OSN | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
// | Original RTP Packet Payload |
// | |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class RtxPacket {
public:
RtxPacket();
~RtxPacket();
void Build(RtpPacket& rtp_packet, uint32_t origin_ssrc, uint16_t seq_no);
};
#endif

View File

@@ -217,9 +217,16 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
rtp_packet_h264->Build(rtp_packet.Buffer().data(), rtp_packet.Size())) { rtp_packet_h264->Build(rtp_packet.Buffer().data(), rtp_packet.Size())) {
rtp_packet_h264->GetFrameHeaderInfo(); rtp_packet_h264->GetFrameHeaderInfo();
if (rtp_packet.PayloadType() != rtp::PAYLOAD_TYPE::RTX) { if (rtp_packet.PayloadType() == rtp::PAYLOAD_TYPE::RTX) {
receive_side_congestion_controller_.OnReceivedPacket( receive_side_congestion_controller_.OnReceivedPacket(
rtp_packet_received, MediaType::VIDEO); rtp_packet_received, MediaType::VIDEO);
size_t osn_offset = rtp_packet.HeaderSize();
uint16_t osn = rtp_packet.Buffer().data()[osn_offset] << 8 |
rtp_packet.Buffer().data()[osn_offset + 1];
uint32_t abs_send_time = 0;
LOG_WARN("!!!!!!!!!!! osn = {}, abs {}", osn,
rtp_packet.GetAbsoluteSendTimestamp(&abs_send_time));
nack_->OnReceivedPacket(rtp_packet.SequenceNumber(), true); nack_->OnReceivedPacket(rtp_packet.SequenceNumber(), true);
} else { } else {
nack_->OnReceivedPacket(rtp_packet.SequenceNumber(), false); nack_->OnReceivedPacket(rtp_packet.SequenceNumber(), false);

View File

@@ -49,6 +49,9 @@ void VideoChannelSend::OnSentRtpPacket(
if (packet->retransmitted_sequence_number()) { if (packet->retransmitted_sequence_number()) {
rtp_packet_history_.MarkPacketAsSent( rtp_packet_history_.MarkPacketAsSent(
*packet->retransmitted_sequence_number()); *packet->retransmitted_sequence_number());
LOG_WARN("resend seq {}, original seq {} mark as sent",
packet->SequenceNumber(),
packet->retransmitted_sequence_number().value());
} else if (packet->PayloadType() != rtp::PAYLOAD_TYPE::H264 - 1) { } else if (packet->PayloadType() != rtp::PAYLOAD_TYPE::H264 - 1) {
rtp_packet_history_.PutRtpPacket(std::move(packet), clock_->CurrentTime()); rtp_packet_history_.PutRtpPacket(std::move(packet), clock_->CurrentTime());
} }
@@ -124,11 +127,17 @@ int32_t VideoChannelSend::ReSendPacket(uint16_t packet_id) {
retransmit_packet = retransmit_packet =
std::make_unique<webrtc::RtpPacketToSend>(stored_packet); std::make_unique<webrtc::RtpPacketToSend>(stored_packet);
if (retransmit_packet) { retransmit_packet->SetSsrc(rtx_ssrc_);
retransmit_packet->set_retransmitted_sequence_number( retransmit_packet->SetPayloadType(rtp::PAYLOAD_TYPE::RTX);
stored_packet.SequenceNumber());
retransmit_packet->set_original_ssrc(stored_packet.Ssrc()); retransmit_packet->set_retransmitted_sequence_number(
} stored_packet.SequenceNumber());
LOG_WARN(
"???????????? resend seq {}",
retransmit_packet->retransmitted_sequence_number().value());
retransmit_packet->set_original_ssrc(stored_packet.Ssrc());
retransmit_packet->BuildRtxPacket();
return retransmit_packet; return retransmit_packet;
}); });
if (packet_size == 0) { if (packet_size == 0) {
@@ -142,8 +151,6 @@ int32_t VideoChannelSend::ReSendPacket(uint16_t packet_id) {
return -1; return -1;
} }
packet->SetSsrc(rtx_ssrc_);
packet->SetPayloadType(rtp::PAYLOAD_TYPE::RTX);
packet->set_packet_type(webrtc::RtpPacketMediaType::kRetransmission); packet->set_packet_type(webrtc::RtpPacketMediaType::kRetransmission);
packet->set_fec_protect_packet(false); packet->set_fec_protect_packet(false);

View File

@@ -68,10 +68,7 @@ class PacketSenderImp : public PacketSender,
ssrc_seq_[packet->Ssrc()] = 1; ssrc_seq_[packet->Ssrc()] = 1;
} }
if (packet->packet_type().value() != packet->UpdateSequenceNumber(ssrc_seq_[packet->Ssrc()]++);
webrtc::RtpPacketMediaType::kRetransmission) {
packet->UpdateSequenceNumber(ssrc_seq_[packet->Ssrc()]++);
}
on_sent_packet_func_(std::move(packet)); on_sent_packet_func_(std::move(packet));
} }