diff --git a/src/common/copy_on_write_buffer.h b/src/common/copy_on_write_buffer.h index 95ca1b5..c7a6a9e 100644 --- a/src/common/copy_on_write_buffer.h +++ b/src/common/copy_on_write_buffer.h @@ -29,6 +29,11 @@ class CopyOnWriteBuffer { buffer_ = std::make_shared>(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; } size_t size() const { return buffer_ ? buffer_->size() : 0; } diff --git a/src/rtp/rtp_packet/rtp_packet.h b/src/rtp/rtp_packet/rtp_packet.h index 5894f2d..c071f20 100644 --- a/src/rtp/rtp_packet/rtp_packet.h +++ b/src/rtp/rtp_packet/rtp_packet.h @@ -239,6 +239,12 @@ class RtpPacket { } public: + struct Extension { + uint8_t id; + uint8_t len; + std::vector data; + }; + // Get Header uint32_t Version() const { return version_; } bool HasPadding() const { return has_padding_; } @@ -252,6 +258,8 @@ class RtpPacket { uint32_t Ssrc() const { return ssrc_; } std::vector Csrcs() const { return csrcs_; }; uint16_t ExtensionProfile() const { return extension_profile_; } + uint16_t ExtensionLen() const { return extension_len_; } + std::vector Extensions() const { return extensions_; } uint32_t GetAbsoluteSendTimestamp(uint32_t *abs_send_time) const { if (!extensions_.empty()) { @@ -305,11 +313,6 @@ class RtpPacket { // Extension header uint16_t extension_profile_ = 0; uint16_t extension_len_ = 0; - struct Extension { - uint8_t id; - uint8_t len; - std::vector data; - }; std::vector extensions_; // Payload diff --git a/src/rtp/rtp_packet/rtp_packet_to_send.cpp b/src/rtp/rtp_packet/rtp_packet_to_send.cpp index 03f25a2..86bdce6 100644 --- a/src/rtp/rtp_packet/rtp_packet_to_send.cpp +++ b/src/rtp/rtp_packet/rtp_packet_to_send.cpp @@ -34,4 +34,97 @@ void RtpPacketToSend::set_packet_type(RtpPacketMediaType type) { packet_type_ = type; } +void AddAbsSendTimeExtension(std::vector& 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::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 csrcs = Csrcs(); + + uint32_t timestamp = std::chrono::duration_cast( + 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 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 diff --git a/src/rtp/rtp_packet/rtp_packet_to_send.h b/src/rtp/rtp_packet/rtp_packet_to_send.h index a4528b0..754a988 100644 --- a/src/rtp/rtp_packet/rtp_packet_to_send.h +++ b/src/rtp/rtp_packet/rtp_packet_to_send.h @@ -44,6 +44,8 @@ class RtpPacketToSend : public ::RtpPacket { ~RtpPacketToSend(); + bool BuildRtxPacket(); + // Time in local time base as close as it can to frame capture time. webrtc::Timestamp capture_time() const { return capture_time_; } void set_capture_time(webrtc::Timestamp time) { capture_time_ = time; } @@ -169,6 +171,9 @@ class RtpPacketToSend : public ::RtpPacket { bool is_red_ = false; bool send_as_ect1_ = false; std::optional time_in_send_queue_; + + private: + std::vector rtp_packet_frame_; }; } // namespace webrtc diff --git a/src/rtp/rtp_packet/rtx_packet.h b/src/rtp/rtp_packet/rtx_packet.h new file mode 100644 index 0000000..690d385 --- /dev/null +++ b/src/rtp/rtp_packet/rtx_packet.h @@ -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 \ No newline at end of file diff --git a/src/transport/channel/rtp_video_receiver.cpp b/src/transport/channel/rtp_video_receiver.cpp index 0b89662..fe6a470 100644 --- a/src/transport/channel/rtp_video_receiver.cpp +++ b/src/transport/channel/rtp_video_receiver.cpp @@ -217,9 +217,16 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) { rtp_packet_h264->Build(rtp_packet.Buffer().data(), rtp_packet.Size())) { 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( 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); } else { nack_->OnReceivedPacket(rtp_packet.SequenceNumber(), false); diff --git a/src/transport/channel/video_channel_send.cpp b/src/transport/channel/video_channel_send.cpp index ce7507d..5463e20 100644 --- a/src/transport/channel/video_channel_send.cpp +++ b/src/transport/channel/video_channel_send.cpp @@ -49,6 +49,9 @@ void VideoChannelSend::OnSentRtpPacket( if (packet->retransmitted_sequence_number()) { rtp_packet_history_.MarkPacketAsSent( *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) { rtp_packet_history_.PutRtpPacket(std::move(packet), clock_->CurrentTime()); } @@ -124,11 +127,17 @@ int32_t VideoChannelSend::ReSendPacket(uint16_t packet_id) { retransmit_packet = std::make_unique(stored_packet); - if (retransmit_packet) { - retransmit_packet->set_retransmitted_sequence_number( - stored_packet.SequenceNumber()); - retransmit_packet->set_original_ssrc(stored_packet.Ssrc()); - } + retransmit_packet->SetSsrc(rtx_ssrc_); + retransmit_packet->SetPayloadType(rtp::PAYLOAD_TYPE::RTX); + + 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; }); if (packet_size == 0) { @@ -142,8 +151,6 @@ int32_t VideoChannelSend::ReSendPacket(uint16_t packet_id) { return -1; } - packet->SetSsrc(rtx_ssrc_); - packet->SetPayloadType(rtp::PAYLOAD_TYPE::RTX); packet->set_packet_type(webrtc::RtpPacketMediaType::kRetransmission); packet->set_fec_protect_packet(false); diff --git a/src/transport/packet_sender/packet_sender_imp.h b/src/transport/packet_sender/packet_sender_imp.h index 867007e..cb1e97b 100644 --- a/src/transport/packet_sender/packet_sender_imp.h +++ b/src/transport/packet_sender/packet_sender_imp.h @@ -68,10 +68,7 @@ class PacketSenderImp : public PacketSender, ssrc_seq_[packet->Ssrc()] = 1; } - if (packet->packet_type().value() != - webrtc::RtpPacketMediaType::kRetransmission) { - packet->UpdateSequenceNumber(ssrc_seq_[packet->Ssrc()]++); - } + packet->UpdateSequenceNumber(ssrc_seq_[packet->Ssrc()]++); on_sent_packet_func_(std::move(packet)); }