mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] modify the implementation of rtx packet
This commit is contained in:
@@ -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; }
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
32
src/rtp/rtp_packet/rtx_packet.h
Normal file
32
src/rtp/rtp_packet/rtx_packet.h
Normal 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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user