From 31e4e806b18b88055c9342625c988939b4ff79a3 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Wed, 3 Aug 2016 18:27:40 +0200 Subject: [PATCH] RtpPacketHistory rewritten to use RtpPacket class. RtpSender updated to use new version of RtpPacketHistory. BUG=webrtc:5261 R=asapersson@webrtc.org Review URL: https://codereview.webrtc.org/1945773002 . Cr-Commit-Position: refs/heads/master@{#13626} --- .../rtp_rtcp/source/rtp_header_extensions.cc | 10 +- .../rtp_rtcp/source/rtp_header_extensions.h | 4 +- webrtc/modules/rtp_rtcp/source/rtp_packet.cc | 29 +- webrtc/modules/rtp_rtcp/source/rtp_packet.h | 15 +- .../rtp_rtcp/source/rtp_packet_history.cc | 214 +++---- .../rtp_rtcp/source/rtp_packet_history.h | 99 ++-- .../source/rtp_packet_history_unittest.cc | 280 ++++----- .../rtp_rtcp/source/rtp_packet_to_send.h | 2 + .../rtp_rtcp/source/rtp_packet_unittest.cc | 4 +- webrtc/modules/rtp_rtcp/source/rtp_sender.cc | 539 +++++++----------- webrtc/modules/rtp_rtcp/source/rtp_sender.h | 46 +- .../rtp_rtcp/source/rtp_sender_unittest.cc | 1 + 12 files changed, 469 insertions(+), 774 deletions(-) diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc index a551b15617..441c548906 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc @@ -124,14 +124,14 @@ bool TransmissionOffset::IsSupportedFor(MediaType type) { return false; } -bool TransmissionOffset::Parse(const uint8_t* data, int32_t* value) { - *value = ByteReader::ReadBigEndian(data); +bool TransmissionOffset::Parse(const uint8_t* data, int32_t* rtp_time) { + *rtp_time = ByteReader::ReadBigEndian(data); return true; } -bool TransmissionOffset::Write(uint8_t* data, int64_t value) { - RTC_CHECK_LE(value, 0x00ffffff); - ByteWriter::WriteBigEndian(data, value); +bool TransmissionOffset::Write(uint8_t* data, int32_t rtp_time) { + RTC_DCHECK_LE(rtp_time, 0x00ffffff); + ByteWriter::WriteBigEndian(data, rtp_time); return true; } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h index cdbf806170..116aaa6b93 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -45,8 +45,8 @@ class TransmissionOffset { static constexpr uint8_t kValueSizeBytes = 3; static const char* kName; static bool IsSupportedFor(MediaType type); - static bool Parse(const uint8_t* data, int32_t* time_ms); - static bool Write(uint8_t* data, int64_t time_ms); + static bool Parse(const uint8_t* data, int32_t* rtp_time); + static bool Write(uint8_t* data, int32_t rtp_time); }; class TransportSequenceNumber { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet.cc index 07aeb7130d..8c8fa0e79a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet.cc @@ -78,18 +78,19 @@ bool Packet::Parse(const uint8_t* buffer, size_t buffer_size) { Clear(); return false; } - RTC_DCHECK_EQ(size(), buffer_size); buffer_.SetData(buffer, buffer_size); + RTC_DCHECK_EQ(size(), buffer_size); return true; } -bool Packet::Parse(rtc::Buffer buffer) { - if (!ParseBuffer(buffer.data(), buffer.size())) { +bool Packet::Parse(rtc::CopyOnWriteBuffer buffer) { + if (!ParseBuffer(buffer.cdata(), buffer.size())) { Clear(); return false; } - RTC_DCHECK_EQ(size(), buffer.size()); + size_t buffer_size = buffer.size(); buffer_ = std::move(buffer); + RTC_DCHECK_EQ(size(), buffer_size); return true; } @@ -174,16 +175,22 @@ const uint8_t* Packet::payload() const { return data() + payload_offset_; } +rtc::CopyOnWriteBuffer Packet::Buffer() const { + return buffer_; +} + size_t Packet::capacity() const { - return buffer_.size(); + return buffer_.capacity(); } size_t Packet::size() const { - return payload_offset_ + payload_size_ + padding_size_; + size_t ret = payload_offset_ + payload_size_ + padding_size_; + RTC_DCHECK_EQ(buffer_.size(), ret); + return ret; } const uint8_t* Packet::data() const { - return buffer_.data(); + return buffer_.cdata(); } size_t Packet::FreeCapacity() const { @@ -194,7 +201,7 @@ size_t Packet::MaxPayloadSize() const { return capacity() - payload_offset_; } -void Packet::CopyHeader(const Packet& packet) { +void Packet::CopyHeaderFrom(const Packet& packet) { RTC_DCHECK_GE(capacity(), packet.headers_size()); marker_ = packet.marker_; @@ -257,6 +264,7 @@ void Packet::SetCsrcs(const std::vector& csrcs) { ByteWriter::WriteBigEndian(WriteAt(offset), csrc); offset += 4; } + buffer_.SetSize(payload_offset_); } uint8_t* Packet::AllocatePayload(size_t size_bytes) { @@ -266,6 +274,7 @@ uint8_t* Packet::AllocatePayload(size_t size_bytes) { return nullptr; } payload_size_ = size_bytes; + buffer_.SetSize(payload_offset_ + payload_size_); return WriteAt(payload_offset_); } @@ -273,6 +282,7 @@ void Packet::SetPayloadSize(size_t size_bytes) { RTC_DCHECK_EQ(padding_size_, 0u); RTC_DCHECK_LE(size_bytes, payload_size_); payload_size_ = size_bytes; + buffer_.SetSize(payload_offset_ + payload_size_); } bool Packet::SetPadding(uint8_t size_bytes, Random* random) { @@ -284,6 +294,7 @@ bool Packet::SetPadding(uint8_t size_bytes, Random* random) { return false; } padding_size_ = size_bytes; + buffer_.SetSize(payload_offset_ + payload_size_ + padding_size_); if (padding_size_ > 0) { size_t padding_offset = payload_offset_ + payload_size_; size_t padding_end = padding_offset + padding_size_; @@ -311,6 +322,7 @@ void Packet::Clear() { extensions_size_ = 0; memset(WriteAt(0), 0, kFixedHeaderSize); + buffer_.SetSize(kFixedHeaderSize); WriteAt(0, kRtpVersion << 6); } @@ -497,6 +509,7 @@ bool Packet::AllocateExtension(ExtensionType type, memset(WriteAt(extensions_offset + extensions_size_), 0, extension_padding_size); payload_offset_ = extensions_offset + 4 * extensions_words; + buffer_.SetSize(payload_offset_); return true; } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet.h b/webrtc/modules/rtp_rtcp/source/rtp_packet.h index b2687ca9ba..f1e3dd40f9 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet.h @@ -13,8 +13,7 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/buffer.h" -#include "webrtc/base/constructormagic.h" +#include "webrtc/base/copyonwritebuffer.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { @@ -33,7 +32,7 @@ class Packet { bool Parse(const uint8_t* buffer, size_t size); // Parse and move given buffer into Packet. - bool Parse(rtc::Buffer packet); + bool Parse(rtc::CopyOnWriteBuffer packet); // Maps parsed extensions to their types to allow use of GetExtension. // Used after parsing when |extensions| can't be provided until base rtp @@ -60,6 +59,7 @@ class Packet { const uint8_t* payload() const; // Buffer. + rtc::CopyOnWriteBuffer Buffer() const; size_t capacity() const; size_t size() const; const uint8_t* data() const; @@ -70,7 +70,7 @@ class Packet { void Clear(); // Header setters. - void CopyHeader(const Packet& packet); + void CopyHeaderFrom(const Packet& packet); void SetMarker(bool marker_bit); void SetPayloadType(uint8_t payload_type); void SetSequenceNumber(uint16_t seq_no); @@ -103,9 +103,12 @@ class Packet { // Adding and getting extensions will fail until |extensions| is // provided via constructor or IdentifyExtensions function. explicit Packet(const ExtensionManager* extensions); + Packet(const Packet&) = default; Packet(const ExtensionManager* extensions, size_t capacity); virtual ~Packet(); + Packet& operator=(const Packet&) = default; + private: struct ExtensionInfo { ExtensionType type; @@ -152,9 +155,9 @@ class Packet { uint8_t num_extensions_ = 0; ExtensionInfo extension_entries_[kMaxExtensionHeaders]; uint16_t extensions_size_ = 0; // Unaligned. - rtc::Buffer buffer_; + rtc::CopyOnWriteBuffer buffer_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Packet); + Packet() = delete; }; template diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc index 713fba8770..0a15209271 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc @@ -10,31 +10,26 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" -#include -#include -#include // memset - #include #include -#include #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" +#include "webrtc/system_wrappers/include/clock.h" namespace webrtc { +namespace { +constexpr size_t kMinPacketRequestBytes = 50; +} // namespace +constexpr size_t RtpPacketHistory::kMaxCapacity; -static const int kMinPacketRequestBytes = 50; +RtpPacketHistory::RtpPacketHistory(Clock* clock) + : clock_(clock), store_(false), prev_index_(0) {} -RTPPacketHistory::RTPPacketHistory(Clock* clock) - : clock_(clock), - store_(false), - prev_index_(0) {} +RtpPacketHistory::~RtpPacketHistory() {} -RTPPacketHistory::~RTPPacketHistory() { -} - -void RTPPacketHistory::SetStorePacketsStatus(bool enable, +void RtpPacketHistory::SetStorePacketsStatus(bool enable, uint16_t number_to_store) { rtc::CritScope cs(&critsect_); if (enable) { @@ -42,21 +37,21 @@ void RTPPacketHistory::SetStorePacketsStatus(bool enable, LOG(LS_WARNING) << "Purging packet history in order to re-set status."; Free(); } - assert(!store_); + RTC_DCHECK(!store_); Allocate(number_to_store); } else { Free(); } } -void RTPPacketHistory::Allocate(size_t number_to_store) { - assert(number_to_store > 0); - assert(number_to_store <= kMaxHistoryCapacity); +void RtpPacketHistory::Allocate(size_t number_to_store) { + RTC_DCHECK_GT(number_to_store, 0u); + RTC_DCHECK_LE(number_to_store, kMaxCapacity); store_ = true; stored_packets_.resize(number_to_store); } -void RTPPacketHistory::Free() { +void RtpPacketHistory::Free() { if (!store_) { return; } @@ -67,40 +62,29 @@ void RTPPacketHistory::Free() { prev_index_ = 0; } -bool RTPPacketHistory::StorePackets() const { +bool RtpPacketHistory::StorePackets() const { rtc::CritScope cs(&critsect_); return store_; } -int32_t RTPPacketHistory::PutRTPPacket(const uint8_t* packet, - size_t packet_length, - int64_t capture_time_ms, - StorageType type) { +void RtpPacketHistory::PutRtpPacket(std::unique_ptr packet, + StorageType type, + bool sent) { + RTC_DCHECK(packet); rtc::CritScope cs(&critsect_); if (!store_) { - return 0; + return; } - assert(packet); - assert(packet_length > 3); - - if (packet_length > IP_PACKET_SIZE) { - LOG(LS_WARNING) << "Failed to store RTP packet with length: " - << packet_length; - return -1; - } - - const uint16_t seq_num = (packet[2] << 8) + packet[3]; - // If index we're about to overwrite contains a packet that has not // yet been sent (probably pending in paced sender), we need to expand // the buffer. - if (stored_packets_[prev_index_].length > 0 && + if (stored_packets_[prev_index_].packet && stored_packets_[prev_index_].send_time == 0) { size_t current_size = static_cast(stored_packets_.size()); - if (current_size < kMaxHistoryCapacity) { + if (current_size < kMaxCapacity) { size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1); - expanded_size = std::min(expanded_size, kMaxHistoryCapacity); + expanded_size = std::min(expanded_size, kMaxCapacity); Allocate(expanded_size); // Causes discontinuity, but that's OK-ish. FindSeqNum() will still work, // but may be slower - at least until buffer has wrapped around once. @@ -108,91 +92,48 @@ int32_t RTPPacketHistory::PutRTPPacket(const uint8_t* packet, } } - // Store packet - // TODO(sprang): Overhaul this class and get rid of this copy step. - // (Finally introduce the RtpPacket class?) - memcpy(stored_packets_[prev_index_].data, packet, packet_length); - stored_packets_[prev_index_].length = packet_length; - - stored_packets_[prev_index_].sequence_number = seq_num; - stored_packets_[prev_index_].time_ms = - (capture_time_ms > 0) ? capture_time_ms : clock_->TimeInMilliseconds(); - stored_packets_[prev_index_].send_time = 0; // Packet not sent. + // Store packet. + if (packet->capture_time_ms() <= 0) + packet->set_capture_time_ms(clock_->TimeInMilliseconds()); + stored_packets_[prev_index_].sequence_number = packet->SequenceNumber(); + stored_packets_[prev_index_].send_time = + (sent ? clock_->TimeInMilliseconds() : 0); stored_packets_[prev_index_].storage_type = type; stored_packets_[prev_index_].has_been_retransmitted = false; + stored_packets_[prev_index_].packet = std::move(packet); ++prev_index_; if (prev_index_ >= stored_packets_.size()) { prev_index_ = 0; } - return 0; } -bool RTPPacketHistory::HasRTPPacket(uint16_t sequence_number) const { +bool RtpPacketHistory::HasRtpPacket(uint16_t sequence_number) const { rtc::CritScope cs(&critsect_); if (!store_) { return false; } - int32_t index = 0; - bool found = FindSeqNum(sequence_number, &index); - if (!found) { - return false; - } - - if (stored_packets_[index].length == 0) { - // Invalid length. - return false; - } - return true; + int unused_index = 0; + return FindSeqNum(sequence_number, &unused_index); } -bool RTPPacketHistory::SetSent(uint16_t sequence_number) { +std::unique_ptr RtpPacketHistory::GetPacketAndSetSendTime( + uint16_t sequence_number, + int64_t min_elapsed_time_ms, + bool retransmit) { rtc::CritScope cs(&critsect_); if (!store_) { - return false; + return nullptr; } - int32_t index = 0; - bool found = FindSeqNum(sequence_number, &index); - if (!found) { - return false; - } - - // Send time already set. - if (stored_packets_[index].send_time != 0) { - return false; - } - - stored_packets_[index].send_time = clock_->TimeInMilliseconds(); - return true; -} - -bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number, - int64_t min_elapsed_time_ms, - bool retransmit, - uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms) { - rtc::CritScope cs(&critsect_); - RTC_CHECK_GE(*packet_length, static_cast(IP_PACKET_SIZE)); - if (!store_) - return false; - - int32_t index = 0; - bool found = FindSeqNum(sequence_number, &index); - if (!found) { + int index = 0; + if (!FindSeqNum(sequence_number, &index)) { LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number; - return false; - } - - size_t length = stored_packets_[index].length; - assert(length <= IP_PACKET_SIZE); - if (length == 0) { - LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number - << ", len " << length; - return false; + return nullptr; } + RTC_DCHECK_EQ(sequence_number, + stored_packets_[index].packet->SequenceNumber()); // Verify elapsed time since last retrieve, but only for retransmissions and // always send packet upon first retransmission request. @@ -200,59 +141,45 @@ bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number, if (min_elapsed_time_ms > 0 && retransmit && stored_packets_[index].has_been_retransmitted && ((now - stored_packets_[index].send_time) < min_elapsed_time_ms)) { - return false; + return nullptr; } if (retransmit) { if (stored_packets_[index].storage_type == kDontRetransmit) { - // No bytes copied since this packet shouldn't be retransmitted or is - // of zero size. - return false; + // No bytes copied since this packet shouldn't be retransmitted. + return nullptr; } stored_packets_[index].has_been_retransmitted = true; } stored_packets_[index].send_time = clock_->TimeInMilliseconds(); - GetPacket(index, packet, packet_length, stored_time_ms); - return true; + return GetPacket(index); } -void RTPPacketHistory::GetPacket(int index, - uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms) const { - // Get packet. - size_t length = stored_packets_[index].length; - memcpy(packet, stored_packets_[index].data, length); - *packet_length = length; - *stored_time_ms = stored_packets_[index].time_ms; +std::unique_ptr RtpPacketHistory::GetPacket(int index) const { + const RtpPacketToSend& stored = *stored_packets_[index].packet; + return std::unique_ptr(new RtpPacketToSend(stored)); } -bool RTPPacketHistory::GetBestFittingPacket(uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms) { +std::unique_ptr RtpPacketHistory::GetBestFittingPacket( + size_t packet_length) const { rtc::CritScope cs(&critsect_); if (!store_) - return false; - int index = FindBestFittingPacket(*packet_length); + return nullptr; + int index = FindBestFittingPacket(packet_length); if (index < 0) - return false; - GetPacket(index, packet, packet_length, stored_time_ms); - return true; + return nullptr; + return GetPacket(index); } -// private, lock should already be taken -bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number, - int32_t* index) const { - uint16_t temp_sequence_number = 0; +bool RtpPacketHistory::FindSeqNum(uint16_t sequence_number, int* index) const { if (prev_index_ > 0) { *index = prev_index_ - 1; - temp_sequence_number = stored_packets_[*index].sequence_number; } else { - *index = stored_packets_.size() - 1; - temp_sequence_number = stored_packets_[*index].sequence_number; // wrap + *index = stored_packets_.size() - 1; // Wrap. } + uint16_t temp_sequence_number = stored_packets_[*index].sequence_number; - int32_t idx = (prev_index_ - 1) - (temp_sequence_number - sequence_number); + int idx = *index - (temp_sequence_number - sequence_number); if (idx >= 0 && idx < static_cast(stored_packets_.size())) { *index = idx; temp_sequence_number = stored_packets_[*index].sequence_number; @@ -268,24 +195,21 @@ bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number, } } } - if (temp_sequence_number == sequence_number) { - // We found a match. - return true; - } - return false; + return temp_sequence_number == sequence_number && + stored_packets_[*index].packet; } -int RTPPacketHistory::FindBestFittingPacket(size_t size) const { +int RtpPacketHistory::FindBestFittingPacket(size_t size) const { if (size < kMinPacketRequestBytes || stored_packets_.empty()) return -1; size_t min_diff = std::numeric_limits::max(); int best_index = -1; // Returned unchanged if we don't find anything. for (size_t i = 0; i < stored_packets_.size(); ++i) { - if (stored_packets_[i].length == 0) + if (!stored_packets_[i].packet) continue; - size_t diff = (stored_packets_[i].length > size) - ? (stored_packets_[i].length - size) - : (size - stored_packets_[i].length); + size_t stored_size = stored_packets_[i].packet->size(); + size_t diff = + (stored_size > size) ? (stored_size - size) : (size - stored_size); if (diff < min_diff) { min_diff = diff; best_index = static_cast(i); @@ -294,6 +218,4 @@ int RTPPacketHistory::FindBestFittingPacket(size_t size) const { return best_index; } -RTPPacketHistory::StoredPacket::StoredPacket() {} - } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h index b4d48aa2ce..dc2b35a375 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h @@ -6,99 +6,80 @@ * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. - * - * Class for storing RTP packets. */ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ +#include #include +#include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_annotations.h" -#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { class Clock; +class RtpPacketToSend; -static const size_t kMaxHistoryCapacity = 9600; - -class RTPPacketHistory { +class RtpPacketHistory { public: - explicit RTPPacketHistory(Clock* clock); - ~RTPPacketHistory(); + static constexpr size_t kMaxCapacity = 9600; + explicit RtpPacketHistory(Clock* clock); + ~RtpPacketHistory(); void SetStorePacketsStatus(bool enable, uint16_t number_to_store); - bool StorePackets() const; - // Stores RTP packet. - int32_t PutRTPPacket(const uint8_t* packet, - size_t packet_length, - int64_t capture_time_ms, - StorageType type); + void PutRtpPacket(std::unique_ptr packet, + StorageType type, + bool sent); - // Gets stored RTP packet corresponding to the input sequence number. - // The packet is copied to the buffer pointed to by ptr_rtp_packet. - // The rtp_packet_length should show the available buffer size. - // Returns true if packet is found. - // packet_length: returns the copied packet length on success. - // min_elapsed_time_ms: the minimum time that must have elapsed since the last - // time the packet was resent (parameter is ignored if set to zero). - // If the packet is found but the minimum time has not elapsed, no bytes are - // copied. - // stored_time_ms: returns the time when the packet was stored. - bool GetPacketAndSetSendTime(uint16_t sequence_number, - int64_t min_elapsed_time_ms, - bool retransmit, - uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms); + // Gets stored RTP packet corresponding to the input |sequence number|. + // Returns nullptr if packet is not found. + // |min_elapsed_time_ms| is the minimum time that must have elapsed since + // the last time the packet was resent (parameter is ignored if set to zero). + // If the packet is found but the minimum time has not elapsed, returns + // nullptr. + std::unique_ptr GetPacketAndSetSendTime( + uint16_t sequence_number, + int64_t min_elapsed_time_ms, + bool retransmit); - bool GetBestFittingPacket(uint8_t* packet, size_t* packet_length, - int64_t* stored_time_ms); + std::unique_ptr GetBestFittingPacket( + size_t packet_size) const; - bool HasRTPPacket(uint16_t sequence_number) const; - - bool SetSent(uint16_t sequence_number); + bool HasRtpPacket(uint16_t sequence_number) const; private: - void GetPacket(int index, - uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms) const - EXCLUSIVE_LOCKS_REQUIRED(critsect_); - void Allocate(size_t number_to_store) EXCLUSIVE_LOCKS_REQUIRED(critsect_); - void Free() EXCLUSIVE_LOCKS_REQUIRED(critsect_); - void VerifyAndAllocatePacketLength(size_t packet_length, uint32_t start_index) - EXCLUSIVE_LOCKS_REQUIRED(critsect_); - bool FindSeqNum(uint16_t sequence_number, int32_t* index) const - EXCLUSIVE_LOCKS_REQUIRED(critsect_); - int FindBestFittingPacket(size_t size) const - EXCLUSIVE_LOCKS_REQUIRED(critsect_); - - private: - Clock* clock_; - rtc::CriticalSection critsect_; - bool store_ GUARDED_BY(critsect_); - uint32_t prev_index_ GUARDED_BY(critsect_); - struct StoredPacket { - StoredPacket(); uint16_t sequence_number = 0; - int64_t time_ms = 0; int64_t send_time = 0; StorageType storage_type = kDontRetransmit; bool has_been_retransmitted = false; - uint8_t data[IP_PACKET_SIZE]; - size_t length = 0; + std::unique_ptr packet; }; + + std::unique_ptr GetPacket(int index) const + EXCLUSIVE_LOCKS_REQUIRED(critsect_); + void Allocate(size_t number_to_store) EXCLUSIVE_LOCKS_REQUIRED(critsect_); + void Free() EXCLUSIVE_LOCKS_REQUIRED(critsect_); + bool FindSeqNum(uint16_t sequence_number, int* index) const + EXCLUSIVE_LOCKS_REQUIRED(critsect_); + int FindBestFittingPacket(size_t size) const + EXCLUSIVE_LOCKS_REQUIRED(critsect_); + + Clock* clock_; + rtc::CriticalSection critsect_; + bool store_ GUARDED_BY(critsect_); + uint32_t prev_index_ GUARDED_BY(critsect_); std::vector stored_packets_ GUARDED_BY(critsect_); + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtpPacketHistory); }; } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc index 7580a80923..05b2311035 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc @@ -8,10 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "testing/gtest/include/gtest/gtest.h" - -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/typedefs.h" @@ -19,271 +22,200 @@ namespace webrtc { class RtpPacketHistoryTest : public ::testing::Test { protected: - RtpPacketHistoryTest() - : fake_clock_(123456), - hist_(new RTPPacketHistory(&fake_clock_)) { - } - ~RtpPacketHistoryTest() { - delete hist_; - } + static constexpr uint16_t kSeqNum = 88; + + RtpPacketHistoryTest() : fake_clock_(123456), hist_(&fake_clock_) {} SimulatedClock fake_clock_; - RTPPacketHistory* hist_; - enum {kPayload = 127}; - enum {kSsrc = 12345678}; - enum {kSeqNum = 88}; - enum {kTimestamp = 127}; - enum {kMaxPacketLength = 1500}; - uint8_t packet_[kMaxPacketLength]; - uint8_t packet_out_[kMaxPacketLength]; + RtpPacketHistory hist_; - void CreateRtpPacket(uint16_t seq_num, uint32_t ssrc, uint8_t payload, - uint32_t timestamp, uint8_t* array, size_t* cur_pos) { - array[(*cur_pos)++] = 0x80; - array[(*cur_pos)++] = payload; - array[(*cur_pos)++] = seq_num >> 8; - array[(*cur_pos)++] = seq_num; - array[(*cur_pos)++] = timestamp >> 24; - array[(*cur_pos)++] = timestamp >> 16; - array[(*cur_pos)++] = timestamp >> 8; - array[(*cur_pos)++] = timestamp; - array[(*cur_pos)++] = ssrc >> 24; - array[(*cur_pos)++] = ssrc >> 16; - array[(*cur_pos)++] = ssrc >> 8; - array[(*cur_pos)++] = ssrc; + std::unique_ptr CreateRtpPacket(uint16_t seq_num) { + // Payload, ssrc, timestamp and extensions are irrelevant for this tests. + std::unique_ptr packet(new RtpPacketToSend(nullptr)); + packet->SetSequenceNumber(seq_num); + packet->set_capture_time_ms(fake_clock_.TimeInMilliseconds()); + return packet; } }; TEST_F(RtpPacketHistoryTest, SetStoreStatus) { - EXPECT_FALSE(hist_->StorePackets()); - hist_->SetStorePacketsStatus(true, 10); - EXPECT_TRUE(hist_->StorePackets()); - hist_->SetStorePacketsStatus(false, 0); - EXPECT_FALSE(hist_->StorePackets()); + EXPECT_FALSE(hist_.StorePackets()); + hist_.SetStorePacketsStatus(true, 10); + EXPECT_TRUE(hist_.StorePackets()); + hist_.SetStorePacketsStatus(false, 0); + EXPECT_FALSE(hist_.StorePackets()); } TEST_F(RtpPacketHistoryTest, NoStoreStatus) { - EXPECT_FALSE(hist_->StorePackets()); - size_t len = 0; - int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + EXPECT_FALSE(hist_.StorePackets()); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); // Packet should not be stored. - len = kMaxPacketLength; - int64_t time; - EXPECT_FALSE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_, &len, - &time)); -} - -TEST_F(RtpPacketHistoryTest, PutRtpPacket_TooLargePacketLength) { - hist_->SetStorePacketsStatus(true, 10); - int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - EXPECT_EQ(-1, hist_->PutRTPPacket(packet_, kMaxPacketLength + 1, - capture_time_ms, kAllowRetransmission)); + EXPECT_FALSE(hist_.GetPacketAndSetSendTime(kSeqNum, 0, false)); } TEST_F(RtpPacketHistoryTest, GetRtpPacket_NotStored) { - hist_->SetStorePacketsStatus(true, 10); - size_t len = kMaxPacketLength; - int64_t time; - EXPECT_FALSE(hist_->GetPacketAndSetSendTime(0, 0, false, packet_, &len, - &time)); + hist_.SetStorePacketsStatus(true, 10); + EXPECT_FALSE(hist_.GetPacketAndSetSendTime(0, 0, false)); } TEST_F(RtpPacketHistoryTest, PutRtpPacket) { - hist_->SetStorePacketsStatus(true, 10); - size_t len = 0; - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); + hist_.SetStorePacketsStatus(true, 10); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); - EXPECT_FALSE(hist_->HasRTPPacket(kSeqNum)); - int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); - EXPECT_TRUE(hist_->HasRTPPacket(kSeqNum)); + EXPECT_FALSE(hist_.HasRtpPacket(kSeqNum)); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); + EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum)); } TEST_F(RtpPacketHistoryTest, GetRtpPacket) { - hist_->SetStorePacketsStatus(true, 10); - size_t len = 0; + hist_.SetStorePacketsStatus(true, 10); int64_t capture_time_ms = 1; - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); + packet->set_capture_time_ms(capture_time_ms); + rtc::CopyOnWriteBuffer buffer = packet->Buffer(); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); - size_t len_out = kMaxPacketLength; - int64_t time; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_out_, - &len_out, &time)); - EXPECT_EQ(len, len_out); - EXPECT_EQ(capture_time_ms, time); - for (size_t i = 0; i < len; i++) { - EXPECT_EQ(packet_[i], packet_out_[i]); - } + std::unique_ptr packet_out = + hist_.GetPacketAndSetSendTime(kSeqNum, 0, false); + EXPECT_TRUE(packet_out); + EXPECT_EQ(buffer, packet_out->Buffer()); + EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms()); } TEST_F(RtpPacketHistoryTest, NoCaptureTime) { - hist_->SetStorePacketsStatus(true, 10); - size_t len = 0; + hist_.SetStorePacketsStatus(true, 10); fake_clock_.AdvanceTimeMilliseconds(1); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, -1, kAllowRetransmission)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); + packet->set_capture_time_ms(-1); + rtc::CopyOnWriteBuffer buffer = packet->Buffer(); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); - size_t len_out = kMaxPacketLength; - int64_t time; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_out_, - &len_out, &time)); - EXPECT_EQ(len, len_out); - EXPECT_EQ(capture_time_ms, time); - for (size_t i = 0; i < len; i++) { - EXPECT_EQ(packet_[i], packet_out_[i]); - } + std::unique_ptr packet_out = + hist_.GetPacketAndSetSendTime(kSeqNum, 0, false); + EXPECT_TRUE(packet_out); + EXPECT_EQ(buffer, packet_out->Buffer()); + EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms()); } TEST_F(RtpPacketHistoryTest, DontRetransmit) { - hist_->SetStorePacketsStatus(true, 10); - size_t len = 0; + hist_.SetStorePacketsStatus(true, 10); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ( - 0, hist_->PutRTPPacket(packet_, len, capture_time_ms, kDontRetransmit)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); + rtc::CopyOnWriteBuffer buffer = packet->Buffer(); + hist_.PutRtpPacket(std::move(packet), kDontRetransmit, false); - size_t len_out = kMaxPacketLength; - int64_t time; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_out_, - &len_out, &time)); - EXPECT_EQ(len, len_out); - EXPECT_EQ(capture_time_ms, time); + std::unique_ptr packet_out; + packet_out = hist_.GetPacketAndSetSendTime(kSeqNum, 0, true); + EXPECT_FALSE(packet_out); + + packet_out = hist_.GetPacketAndSetSendTime(kSeqNum, 0, false); + EXPECT_TRUE(packet_out); + + EXPECT_EQ(buffer.size(), packet_out->size()); + EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms()); } TEST_F(RtpPacketHistoryTest, MinResendTime) { static const int64_t kMinRetransmitIntervalMs = 100; - hist_->SetStorePacketsStatus(true, 10); - size_t len = 0; + hist_.SetStorePacketsStatus(true, 10); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); + size_t len = packet->size(); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); // First transmission: TimeToSendPacket() call from pacer. - int64_t time; - len = kMaxPacketLength; - EXPECT_TRUE( - hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_, &len, &time)); + EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum, 0, false)); fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs); // Time has elapsed. - len = kMaxPacketLength; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, - true, packet_, &len, &time)); - EXPECT_GT(len, 0u); - EXPECT_EQ(capture_time_ms, time); + std::unique_ptr packet_out = + hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true); + EXPECT_TRUE(packet_out); + EXPECT_EQ(len, packet_out->size()); + EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms()); fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1); // Time has not elapsed. Packet should be found, but no bytes copied. - len = kMaxPacketLength; - EXPECT_FALSE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, - true, packet_, &len, &time)); + EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum)); + EXPECT_FALSE( + hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true)); } TEST_F(RtpPacketHistoryTest, EarlyFirstResend) { static const int64_t kMinRetransmitIntervalMs = 100; - hist_->SetStorePacketsStatus(true, 10); - size_t len = 0; + hist_.SetStorePacketsStatus(true, 10); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum); + rtc::CopyOnWriteBuffer buffer = packet->Buffer(); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); // First transmission: TimeToSendPacket() call from pacer. - int64_t time; - len = kMaxPacketLength; - EXPECT_TRUE( - hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_, &len, &time)); + EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum, 0, false)); fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1); // Time has not elapsed, but this is the first retransmission request so // allow anyway. - len = kMaxPacketLength; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, - true, packet_, &len, &time)); - EXPECT_GT(len, 0u); - EXPECT_EQ(capture_time_ms, time); + std::unique_ptr packet_out = + hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true); + EXPECT_TRUE(packet_out); + EXPECT_EQ(buffer, packet_out->Buffer()); + EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms()); fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1); // Time has not elapsed. Packet should be found, but no bytes copied. - len = kMaxPacketLength; - EXPECT_FALSE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, - true, packet_, &len, &time)); + EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum)); + EXPECT_FALSE( + hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true)); } TEST_F(RtpPacketHistoryTest, DynamicExpansion) { - hist_->SetStorePacketsStatus(true, 10); - size_t len; - int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - int64_t time; + hist_.SetStorePacketsStatus(true, 10); // Add 4 packets, and then send them. for (int i = 0; i < 4; ++i) { - len = 0; - CreateRtpPacket(kSeqNum + i, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum + i); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); } for (int i = 0; i < 4; ++i) { - len = kMaxPacketLength; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_, - &len, &time)); + EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false)); } - capture_time_ms += 33; + fake_clock_.AdvanceTimeMilliseconds(33); // Add 16 packets, and then send them. History should expand to make this // work. for (int i = 4; i < 20; ++i) { - len = 0; - CreateRtpPacket(kSeqNum + i, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + std::unique_ptr packet = CreateRtpPacket(kSeqNum + i); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); } for (int i = 4; i < 20; ++i) { - len = kMaxPacketLength; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_, - &len, &time)); + EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false)); } fake_clock_.AdvanceTimeMilliseconds(100); // Retransmit last 16 packets. for (int i = 4; i < 20; ++i) { - len = kMaxPacketLength; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_, - &len, &time)); + EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false)); } } TEST_F(RtpPacketHistoryTest, FullExpansion) { static const int kSendSidePacketHistorySize = 600; - hist_->SetStorePacketsStatus(true, kSendSidePacketHistorySize); - size_t len; - int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); - int64_t time; - for (size_t i = 0; i < kMaxHistoryCapacity + 1; ++i) { - len = 0; - CreateRtpPacket(kSeqNum + i, kSsrc, kPayload, kTimestamp, packet_, &len); - EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms, - kAllowRetransmission)); + hist_.SetStorePacketsStatus(true, kSendSidePacketHistorySize); + for (size_t i = 0; i < RtpPacketHistory::kMaxCapacity + 1; ++i) { + std::unique_ptr packet = CreateRtpPacket(kSeqNum + i); + hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); } fake_clock_.AdvanceTimeMilliseconds(100); // Retransmit all packets currently in buffer. - for (size_t i = 1; i < kMaxHistoryCapacity + 1; ++i) { - len = kMaxPacketLength; - EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_, - &len, &time)); + for (size_t i = 1; i < RtpPacketHistory::kMaxCapacity + 1; ++i) { + EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false)); } } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h b/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h index ad749ffb61..f2ddc8a52e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h @@ -18,9 +18,11 @@ class RtpPacketToSend : public rtp::Packet { public: explicit RtpPacketToSend(const ExtensionManager* extensions) : Packet(extensions) {} + RtpPacketToSend(const RtpPacketToSend& packet) = default; RtpPacketToSend(const ExtensionManager* extensions, size_t capacity) : Packet(extensions, capacity) {} + RtpPacketToSend& operator=(const RtpPacketToSend& packet) = default; // Time in local time base as close as it can to frame capture time. int64_t capture_time_ms() const { return capture_time_ms_; } void set_capture_time_ms(int64_t time) { capture_time_ms_ = time; } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc index c9342221df..63a171dfb3 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc @@ -174,12 +174,12 @@ TEST(RtpPacketTest, ParseMinimum) { } TEST(RtpPacketTest, ParseBuffer) { - rtc::Buffer unparsed(kMinimumPacket); + rtc::CopyOnWriteBuffer unparsed(kMinimumPacket); const uint8_t* raw = unparsed.data(); RtpPacketReceived packet; EXPECT_TRUE(packet.Parse(std::move(unparsed))); - EXPECT_EQ(raw, packet.data()); // Expect packet took over the buffer. + EXPECT_EQ(raw, packet.data()); // Expect packet take the buffer without copy. EXPECT_EQ(kSeqNum, packet.SequenceNumber()); EXPECT_EQ(kTimestamp, packet.Timestamp()); EXPECT_EQ(kSsrc, packet.Ssrc()); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 58dbc3ebff..b918a908a7 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -10,7 +10,6 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" -#include // srand #include #include @@ -24,22 +23,22 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" #include "webrtc/modules/rtp_rtcp/source/time_util.h" namespace webrtc { -// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP. -static const size_t kMaxPaddingLength = 224; -static const int kSendSideDelayWindowMs = 1000; -static const uint32_t kAbsSendTimeFraction = 18; -static const int kBitrateStatisticsWindowMs = 1000; - namespace { - -const size_t kRtpHeaderLength = 12; -const uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1. +// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP. +constexpr size_t kMaxPaddingLength = 224; +constexpr int kSendSideDelayWindowMs = 1000; +constexpr size_t kRtpHeaderLength = 12; +constexpr uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1. +constexpr uint32_t kTimestampTicksPerMs = 90; +constexpr int kBitrateStatisticsWindowMs = 1000; const char* FrameTypeToString(FrameType frame_type) { switch (frame_type) { @@ -53,16 +52,13 @@ const char* FrameTypeToString(FrameType frame_type) { return ""; } -// TODO(holmer): Merge this with the implementation in -// remote_bitrate_estimator_abs_send_time.cc. -uint32_t ConvertMsTo24Bits(int64_t time_ms) { - uint32_t time_24_bits = - static_cast( - ((static_cast(time_ms) << kAbsSendTimeFraction) + 500) / - 1000) & - 0x00FFFFFF; - return time_24_bits; +void CountPacket(RtpPacketCounter* counter, const RtpPacketToSend& packet) { + ++counter->packets; + counter->header_bytes += packet.headers_size(); + counter->padding_bytes += packet.padding_size(); + counter->payload_bytes += packet.payload_size(); } + } // namespace RTPSender::RTPSender( @@ -127,10 +123,6 @@ RTPSender::RTPSender( csrcs_(), rtx_(kRtxOff), retransmission_rate_limiter_(retransmission_rate_limiter) { - // We need to seed the random generator for BuildPaddingPacket() below. - // TODO(holmer,tommi): Note that TimeInMilliseconds might return 0 on Mac - // early on in the process. - srand(static_cast(clock_->TimeInMilliseconds())); ssrc_ = ssrc_db_->CreateSSRC(); RTC_DCHECK(ssrc_ != 0); ssrc_rtx_ = ssrc_db_->CreateSSRC(); @@ -346,17 +338,12 @@ void RTPSender::SetMaxPayloadLength(size_t max_payload_length) { } size_t RTPSender::MaxDataPayloadLength() const { - int rtx; - { - rtc::CritScope lock(&send_critsect_); - rtx = rtx_; - } if (audio_configured_) { return max_payload_length_ - RtpHeaderLength(); } else { return max_payload_length_ - RtpHeaderLength() // RTP overhead. - video_->FECPacketOverhead() // FEC/ULP/RED overhead. - - ((rtx) ? 2 : 0); // RTX overhead. + - (RtxStatus() ? kRtxHeaderSize : 0); // RTX overhead. } } @@ -543,41 +530,20 @@ size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send, return 0; } - uint8_t buffer[IP_PACKET_SIZE]; int bytes_left = static_cast(bytes_to_send); while (bytes_left > 0) { - size_t length = bytes_left; - int64_t capture_time_ms; - if (!packet_history_.GetBestFittingPacket(buffer, &length, - &capture_time_ms)) { + std::unique_ptr packet = + packet_history_.GetBestFittingPacket(bytes_left); + if (!packet) break; - } - if (!PrepareAndSendPacket(buffer, length, capture_time_ms, true, false, - probe_cluster_id)) + size_t payload_size = packet->payload_size(); + if (!PrepareAndSendPacket(std::move(packet), true, false, probe_cluster_id)) break; - RtpUtility::RtpHeaderParser rtp_parser(buffer, length); - RTPHeader rtp_header; - rtp_parser.Parse(&rtp_header); - bytes_left -= static_cast(length - rtp_header.headerLength); + bytes_left -= payload_size; } return bytes_to_send - bytes_left; } -void RTPSender::BuildPaddingPacket(uint8_t* packet, - size_t header_length, - size_t padding_length) { - packet[0] |= 0x20; // Set padding bit. - int32_t* data = reinterpret_cast(&(packet[header_length])); - - // Fill data buffer with random data. - for (size_t j = 0; j < (padding_length >> 2); ++j) { - data[j] = rand(); // NOLINT - } - // Set number of padding bytes in the last byte of the packet. - packet[header_length + padding_length - 1] = - static_cast(padding_length); -} - size_t RTPSender::SendPadData(size_t bytes, bool timestamp_provided, uint32_t timestamp, @@ -653,42 +619,36 @@ size_t RTPSender::SendPadData(size_t bytes, } } - uint8_t padding_packet[IP_PACKET_SIZE]; - size_t header_length = 0; - { - rtc::CritScope lock(&send_critsect_); - header_length = - CreateRtpHeader(padding_packet, payload_type, ssrc, false, timestamp, - sequence_number, std::vector()); - } - BuildPaddingPacket(padding_packet, header_length, padding_bytes_in_packet); - size_t length = padding_bytes_in_packet + header_length; + RtpPacketToSend padding_packet(&rtp_header_extension_map_, IP_PACKET_SIZE); + padding_packet.SetPayloadType(payload_type); + padding_packet.SetMarker(false); + padding_packet.SetSequenceNumber(sequence_number); + padding_packet.SetTimestamp(timestamp); + padding_packet.SetSsrc(ssrc); + int64_t now_ms = clock_->TimeInMilliseconds(); - RtpUtility::RtpHeaderParser rtp_parser(padding_packet, length); - RTPHeader rtp_header; - rtp_parser.Parse(&rtp_header); - if (capture_time_ms > 0) { - UpdateTransmissionTimeOffset( - padding_packet, length, rtp_header, now_ms - capture_time_ms); + padding_packet.SetExtension( + kTimestampTicksPerMs * (now_ms - capture_time_ms)); } - - UpdateAbsoluteSendTime(padding_packet, length, rtp_header, now_ms); + padding_packet.SetExtension(now_ms); PacketOptions options; - if (UpdateTransportSequenceNumber(padding_packet, length, rtp_header, - &options.packet_id)) { - if (transport_feedback_observer_) - transport_feedback_observer_->AddPacket(options.packet_id, length, - probe_cluster_id); - } + bool has_transport_seq_no = + UpdateTransportSequenceNumber(&padding_packet, &options.packet_id); - if (!SendPacketToNetwork(padding_packet, length, options)) + padding_packet.SetPadding(padding_bytes_in_packet, &random_); + + if (has_transport_seq_no && transport_feedback_observer_) + transport_feedback_observer_->AddPacket( + options.packet_id, padding_packet.size(), probe_cluster_id); + + if (!SendPacketToNetwork(padding_packet, options)) break; bytes_sent += padding_bytes_in_packet; - UpdateRtpStats(padding_packet, length, rtp_header, over_rtx, false); + UpdateRtpStats(padding_packet, over_rtx, false); } return bytes_sent; @@ -703,13 +663,9 @@ bool RTPSender::StorePackets() const { } int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { - size_t length = IP_PACKET_SIZE; - uint8_t data_buffer[IP_PACKET_SIZE]; - int64_t capture_time_ms; - - if (!packet_history_.GetPacketAndSetSendTime(packet_id, min_resend_time, true, - data_buffer, &length, - &capture_time_ms)) { + std::unique_ptr packet = + packet_history_.GetPacketAndSetSendTime(packet_id, min_resend_time, true); + if (!packet) { // Packet not found. return 0; } @@ -717,53 +673,44 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { // Check if we're overusing retransmission bitrate. // TODO(sprang): Add histograms for nack success or failure reasons. RTC_DCHECK(retransmission_rate_limiter_); - if (!retransmission_rate_limiter_->TryUseRate(length)) + if (!retransmission_rate_limiter_->TryUseRate(packet->size())) return -1; if (paced_sender_) { - RtpUtility::RtpHeaderParser rtp_parser(data_buffer, length); - RTPHeader header; - if (!rtp_parser.Parse(&header)) { - assert(false); - return -1; - } // Convert from TickTime to Clock since capture_time_ms is based on // TickTime. - int64_t corrected_capture_tims_ms = capture_time_ms + clock_delta_ms_; - paced_sender_->InsertPacket( - RtpPacketSender::kNormalPriority, header.ssrc, header.sequenceNumber, - corrected_capture_tims_ms, length - header.headerLength, true); + int64_t corrected_capture_tims_ms = + packet->capture_time_ms() + clock_delta_ms_; + paced_sender_->InsertPacket(RtpPacketSender::kNormalPriority, + packet->Ssrc(), packet->SequenceNumber(), + corrected_capture_tims_ms, + packet->payload_size(), true); - return length; + return packet->size(); } - int rtx = kRtxOff; - { - rtc::CritScope lock(&send_critsect_); - rtx = rtx_; - } - if (!PrepareAndSendPacket(data_buffer, length, capture_time_ms, - (rtx & kRtxRetransmitted) > 0, true, - PacketInfo::kNotAProbe)) { + bool rtx = (RtxStatus() & kRtxRetransmitted) > 0; + int32_t packet_size = static_cast(packet->size()); + if (!PrepareAndSendPacket(std::move(packet), rtx, true, + PacketInfo::kNotAProbe)) return -1; - } - return static_cast(length); + return packet_size; } -bool RTPSender::SendPacketToNetwork(const uint8_t* packet, - size_t size, +bool RTPSender::SendPacketToNetwork(const RtpPacketToSend& packet, const PacketOptions& options) { int bytes_sent = -1; if (transport_) { - bytes_sent = transport_->SendRtp(packet, size, options) - ? static_cast(size) + bytes_sent = transport_->SendRtp(packet.data(), packet.size(), options) + ? static_cast(packet.size()) : -1; if (event_log_ && bytes_sent > 0) { - event_log_->LogRtpHeader(kOutgoingPacket, MediaType::ANY, packet, size); + event_log_->LogRtpHeader(kOutgoingPacket, MediaType::ANY, packet.data(), + packet.size()); } } TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), - "RTPSender::SendPacketToNetwork", "size", size, "sent", - bytes_sent); + "RTPSender::SendPacketToNetwork", "size", packet.size(), + "sent", bytes_sent); // TODO(pwestin): Add a separate bitrate for sent bitrate after pacer. if (bytes_sent <= 0) { LOG(LS_WARNING) << "Transport failed to send packet"; @@ -811,89 +758,75 @@ bool RTPSender::TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms, bool retransmission, int probe_cluster_id) { - size_t length = IP_PACKET_SIZE; - uint8_t data_buffer[IP_PACKET_SIZE]; - int64_t stored_time_ms; - - if (!packet_history_.GetPacketAndSetSendTime(sequence_number, - 0, - retransmission, - data_buffer, - &length, - &stored_time_ms)) { + std::unique_ptr packet = + packet_history_.GetPacketAndSetSendTime(sequence_number, 0, + retransmission); + if (!packet) // Packet cannot be found. Allow sending to continue. return true; - } - int rtx; - { - rtc::CritScope lock(&send_critsect_); - rtx = rtx_; - } - return PrepareAndSendPacket(data_buffer, length, capture_time_ms, - retransmission && (rtx & kRtxRetransmitted) > 0, - retransmission, probe_cluster_id); + return PrepareAndSendPacket( + std::move(packet), + retransmission && (RtxStatus() & kRtxRetransmitted) > 0, retransmission, + probe_cluster_id); } -bool RTPSender::PrepareAndSendPacket(uint8_t* buffer, - size_t length, - int64_t capture_time_ms, +bool RTPSender::PrepareAndSendPacket(std::unique_ptr packet, bool send_over_rtx, bool is_retransmit, int probe_cluster_id) { - uint8_t* buffer_to_send_ptr = buffer; + RTC_DCHECK(packet); + int64_t capture_time_ms = packet->capture_time_ms(); + RtpPacketToSend* packet_to_send = packet.get(); - RtpUtility::RtpHeaderParser rtp_parser(buffer, length); - RTPHeader rtp_header; - rtp_parser.Parse(&rtp_header); - if (!is_retransmit && rtp_header.markerBit) { + if (!is_retransmit && packet->Marker()) { TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PacedSend", capture_time_ms); } - TRACE_EVENT_INSTANT2( - TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PrepareAndSendPacket", - "timestamp", rtp_header.timestamp, "seqnum", rtp_header.sequenceNumber); + TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), + "PrepareAndSendPacket", "timestamp", packet->Timestamp(), + "seqnum", packet->SequenceNumber()); - uint8_t data_buffer_rtx[IP_PACKET_SIZE]; + std::unique_ptr packet_rtx; if (send_over_rtx) { - if (!BuildRtxPacket(buffer, &length, data_buffer_rtx)) + packet_rtx = BuildRtxPacket(*packet); + if (!packet_rtx) return false; - buffer_to_send_ptr = data_buffer_rtx; + packet_to_send = packet_rtx.get(); } int64_t now_ms = clock_->TimeInMilliseconds(); int64_t diff_ms = now_ms - capture_time_ms; - UpdateTransmissionTimeOffset(buffer_to_send_ptr, length, rtp_header, - diff_ms); - UpdateAbsoluteSendTime(buffer_to_send_ptr, length, rtp_header, now_ms); + packet_to_send->SetExtension(kTimestampTicksPerMs * + diff_ms); + packet_to_send->SetExtension(now_ms); PacketOptions options; - if (UpdateTransportSequenceNumber(buffer_to_send_ptr, length, rtp_header, - &options.packet_id)) { - if (transport_feedback_observer_) - transport_feedback_observer_->AddPacket(options.packet_id, length, - probe_cluster_id); + if (UpdateTransportSequenceNumber(packet_to_send, &options.packet_id) && + transport_feedback_observer_) { + transport_feedback_observer_->AddPacket( + options.packet_id, packet_to_send->size(), probe_cluster_id); } if (!is_retransmit && !send_over_rtx) { - UpdateDelayStatistics(capture_time_ms, now_ms); - UpdateOnSendPacket(options.packet_id, capture_time_ms, rtp_header.ssrc); + UpdateDelayStatistics(packet->capture_time_ms(), now_ms); + UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(), + packet->Ssrc()); } - bool ret = SendPacketToNetwork(buffer_to_send_ptr, length, options); - if (ret) { + if (!SendPacketToNetwork(*packet_to_send, options)) + return false; + + { rtc::CritScope lock(&send_critsect_); media_has_been_sent_ = true; } - UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx, - is_retransmit); - return ret; + UpdateRtpStats(*packet_to_send, send_over_rtx, is_retransmit); + return true; } -void RTPSender::UpdateRtpStats(const uint8_t* buffer, - size_t packet_length, - const RTPHeader& header, +void RTPSender::UpdateRtpStats(const RtpPacketToSend& packet, bool is_rtx, bool is_retransmit) { StreamDataCounters* counters; @@ -908,27 +841,26 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer, counters = &rtp_stats_; } - total_bitrate_sent_.Update(packet_length, now_ms); + total_bitrate_sent_.Update(packet.size(), now_ms); - if (counters->first_packet_time_ms == -1) + if (counters->first_packet_time_ms == -1) { counters->first_packet_time_ms = clock_->TimeInMilliseconds(); - - if (IsFecPacket(buffer, header)) - counters->fec.AddPacket(packet_length, header); - - if (is_retransmit) { - counters->retransmitted.AddPacket(packet_length, header); - nack_bitrate_sent_.Update(packet_length, now_ms); } + if (IsFecPacket(packet)) { + CountPacket(&counters->fec, packet); + } + if (is_retransmit) { + CountPacket(&counters->retransmitted, packet); + nack_bitrate_sent_.Update(packet.size(), now_ms); + } + CountPacket(&counters->transmitted, packet); - counters->transmitted.AddPacket(packet_length, header); - - if (rtp_stats_callback_) + if (rtp_stats_callback_) { rtp_stats_callback_->DataCountersUpdated(*counters, ssrc); + } } -bool RTPSender::IsFecPacket(const uint8_t* buffer, - const RTPHeader& header) const { +bool RTPSender::IsFecPacket(const RtpPacketToSend& packet) const { if (!video_) { return false; } @@ -936,9 +868,8 @@ bool RTPSender::IsFecPacket(const uint8_t* buffer, uint8_t pt_red; uint8_t pt_fec; video_->GenericFECStatus(&fec_enabled, &pt_red, &pt_fec); - return fec_enabled && - header.payloadType == pt_red && - buffer[header.headerLength] == pt_fec; + return fec_enabled && packet.PayloadType() == pt_red && + packet.payload()[0] == pt_fec; } size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { @@ -951,7 +882,6 @@ size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { return bytes_sent; } -// TODO(pwestin): send in the RtpHeaderParser to avoid parsing it again. bool RTPSender::SendToNetwork(uint8_t* buffer, size_t payload_length, size_t rtp_header_length, @@ -959,35 +889,38 @@ bool RTPSender::SendToNetwork(uint8_t* buffer, StorageType storage, RtpPacketSender::Priority priority) { size_t length = payload_length + rtp_header_length; - RtpUtility::RtpHeaderParser rtp_parser(buffer, length); - - RTPHeader rtp_header; - rtp_parser.Parse(&rtp_header); + std::unique_ptr packet( + new RtpPacketToSend(&rtp_header_extension_map_, length)); + RTC_CHECK(packet->Parse(buffer, length)); + packet->set_capture_time_ms(capture_time_ms); + return SendToNetwork(std::move(packet), storage, priority); +} +bool RTPSender::SendToNetwork(std::unique_ptr packet, + StorageType storage, + RtpPacketSender::Priority priority) { + RTC_DCHECK(packet); int64_t now_ms = clock_->TimeInMilliseconds(); // |capture_time_ms| <= 0 is considered invalid. // TODO(holmer): This should be changed all over Video Engine so that negative // time is consider invalid, while 0 is considered a valid time. - if (capture_time_ms > 0) { - UpdateTransmissionTimeOffset(buffer, length, rtp_header, - now_ms - capture_time_ms); - } - - UpdateAbsoluteSendTime(buffer, length, rtp_header, now_ms); - - // Used for NACK and to spread out the transmission of packets. - if (packet_history_.PutRTPPacket(buffer, length, capture_time_ms, storage) != - 0) { - return false; + if (packet->capture_time_ms() > 0) { + packet->SetExtension( + kTimestampTicksPerMs * (now_ms - packet->capture_time_ms())); } + packet->SetExtension(now_ms); if (paced_sender_) { + uint16_t seq_no = packet->SequenceNumber(); + uint32_t ssrc = packet->Ssrc(); // Correct offset between implementations of millisecond time stamps in // TickTime and Clock. - int64_t corrected_time_ms = capture_time_ms + clock_delta_ms_; - paced_sender_->InsertPacket(priority, rtp_header.ssrc, - rtp_header.sequenceNumber, corrected_time_ms, + int64_t corrected_time_ms = packet->capture_time_ms() + clock_delta_ms_; + size_t payload_length = packet->payload_size(); + packet_history_.PutRtpPacket(std::move(packet), storage, false); + + paced_sender_->InsertPacket(priority, ssrc, seq_no, corrected_time_ms, payload_length, false); if (last_capture_time_ms_sent_ == 0 || corrected_time_ms > last_capture_time_ms_sent_) { @@ -1000,31 +933,32 @@ bool RTPSender::SendToNetwork(uint8_t* buffer, } PacketOptions options; - if (UpdateTransportSequenceNumber(buffer, length, rtp_header, - &options.packet_id)) { - if (transport_feedback_observer_) - transport_feedback_observer_->AddPacket(options.packet_id, length, - PacketInfo::kNotAProbe); + if (UpdateTransportSequenceNumber(packet.get(), &options.packet_id) && + transport_feedback_observer_) { + transport_feedback_observer_->AddPacket(options.packet_id, packet->size(), + PacketInfo::kNotAProbe); } - UpdateDelayStatistics(capture_time_ms, now_ms); - UpdateOnSendPacket(options.packet_id, capture_time_ms, rtp_header.ssrc); - bool sent = SendPacketToNetwork(buffer, length, options); + UpdateDelayStatistics(packet->capture_time_ms(), now_ms); + UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(), + packet->Ssrc()); + + bool sent = SendPacketToNetwork(*packet, options); + + if (sent) { + { + rtc::CritScope lock(&send_critsect_); + media_has_been_sent_ = true; + } + UpdateRtpStats(*packet, false, false); + } // Mark the packet as sent in the history even if send failed. Dropping a // packet here should be treated as any other packet drop so we should be // ready for a retransmission. - packet_history_.SetSent(rtp_header.sequenceNumber); + packet_history_.PutRtpPacket(std::move(packet), storage, true); - if (!sent) - return false; - - { - rtc::CritScope lock(&send_critsect_); - media_has_been_sent_ = true; - } - UpdateRtpStats(buffer, length, rtp_header, false, false); - return true; + return sent; } void RTPSender::UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms) { @@ -1494,31 +1428,6 @@ RTPSender::ExtensionStatus RTPSender::VerifyExtension( return ExtensionStatus::kOk; } -void RTPSender::UpdateTransmissionTimeOffset(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int64_t time_diff_ms) const { - size_t offset; - rtc::CritScope lock(&send_critsect_); - switch (VerifyExtension(kRtpExtensionTransmissionTimeOffset, rtp_packet, - rtp_packet_length, rtp_header, - kTransmissionTimeOffsetLength, &offset)) { - case ExtensionStatus::kNotRegistered: - return; - case ExtensionStatus::kError: - LOG(LS_WARNING) << "Failed to update transmission time offset."; - return; - case ExtensionStatus::kOk: - break; - default: - RTC_NOTREACHED(); - } - - // Update transmission offset field (converting to a 90 kHz timestamp). - ByteWriter::WriteBigEndian(rtp_packet + offset + 1, - time_diff_ms * 90); // RTP timestamp. -} - bool RTPSender::UpdateAudioLevel(uint8_t* rtp_packet, size_t rtp_packet_length, const RTPHeader& rtp_header, @@ -1570,67 +1479,22 @@ bool RTPSender::UpdateVideoRotation(uint8_t* rtp_packet, return true; } -void RTPSender::UpdateAbsoluteSendTime(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int64_t now_ms) const { - size_t offset; +bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet, + int* packet_id) const { + RTC_DCHECK(packet); + RTC_DCHECK(packet_id); rtc::CritScope lock(&send_critsect_); - - switch (VerifyExtension(kRtpExtensionAbsoluteSendTime, rtp_packet, - rtp_packet_length, rtp_header, - kAbsoluteSendTimeLength, &offset)) { - case ExtensionStatus::kNotRegistered: - return; - case ExtensionStatus::kError: - LOG(LS_WARNING) << "Failed to update absolute send time"; - return; - case ExtensionStatus::kOk: - break; - default: - RTC_NOTREACHED(); - } - - // Update absolute send time field (convert ms to 24-bit unsigned with 18 bit - // fractional part). - ByteWriter::WriteBigEndian(rtp_packet + offset + 1, - ConvertMsTo24Bits(now_ms)); -} - -bool RTPSender::UpdateTransportSequenceNumber(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int* sequence_number) const { - RTC_DCHECK(sequence_number); - size_t offset; - rtc::CritScope lock(&send_critsect_); - - switch (VerifyExtension(kRtpExtensionTransportSequenceNumber, rtp_packet, - rtp_packet_length, rtp_header, - kTransportSequenceNumberLength, &offset)) { - case ExtensionStatus::kNotRegistered: - return false; - case ExtensionStatus::kError: - LOG(LS_WARNING) << "Failed to update transport sequence number"; - return false; - case ExtensionStatus::kOk: - break; - default: - RTC_NOTREACHED(); - } - - if (!AllocateTransportSequenceNumber(sequence_number)) + if (!rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) return false; - BuildTransportSequenceNumberExtension(rtp_packet + offset, *sequence_number); - return true; -} - -bool RTPSender::AllocateTransportSequenceNumber(int* packet_id) const { if (!transport_sequence_number_allocator_) return false; *packet_id = transport_sequence_number_allocator_->AllocateSequenceNumber(); + + if (!packet->SetExtension(*packet_id)) + return false; + return true; } @@ -1803,53 +1667,46 @@ int32_t RTPSender::SetFecParameters( return 0; } -bool RTPSender::BuildRtxPacket(uint8_t* buffer, - size_t* length, - uint8_t* buffer_rtx) { - rtc::CritScope lock(&send_critsect_); - if (!sending_media_) - return false; - uint8_t* data_buffer_rtx = buffer_rtx; - // Add RTX header. - RtpUtility::RtpHeaderParser rtp_parser( - reinterpret_cast(buffer), *length); - - RTPHeader rtp_header; - rtp_parser.Parse(&rtp_header); - +std::unique_ptr RTPSender::BuildRtxPacket( + const RtpPacketToSend& packet) { + // TODO(danilchap): Create rtx packet with extra capacity for SRTP + // when transport interface would be updated to take buffer class. + std::unique_ptr rtx_packet(new RtpPacketToSend( + &rtp_header_extension_map_, packet.size() + kRtxHeaderSize)); // Add original RTP header. - memcpy(data_buffer_rtx, buffer, rtp_header.headerLength); + rtx_packet->CopyHeaderFrom(packet); + { + rtc::CritScope lock(&send_critsect_); + if (!sending_media_) + return nullptr; + // Replace payload type, if a specific type is set for RTX. + auto kv = rtx_payload_type_map_.find(packet.PayloadType()); - // Replace payload type, if a specific type is set for RTX. - auto kv = rtx_payload_type_map_.find(rtp_header.payloadType); - // Use rtx mapping associated with media codec if we can't find one, assuming - // it's red. - // TODO(holmer): Remove once old Chrome versions don't rely on this. - if (kv == rtx_payload_type_map_.end()) - kv = rtx_payload_type_map_.find(payload_type_); - if (kv != rtx_payload_type_map_.end()) - data_buffer_rtx[1] = kv->second; - if (rtp_header.markerBit) - data_buffer_rtx[1] |= kRtpMarkerBitMask; + // Use rtx mapping associated with media codec if we can't find one, + // assume it's red. + // TODO(holmer): Remove once old Chrome versions don't rely on this. + if (kv == rtx_payload_type_map_.end()) + kv = rtx_payload_type_map_.find(payload_type_); + if (kv != rtx_payload_type_map_.end()) + rtx_packet->SetPayloadType(kv->second); - // Replace sequence number. - uint8_t* ptr = data_buffer_rtx + 2; - ByteWriter::WriteBigEndian(ptr, sequence_number_rtx_++); + // Replace sequence number. + rtx_packet->SetSequenceNumber(sequence_number_rtx_++); - // Replace SSRC. - ptr += 6; - ByteWriter::WriteBigEndian(ptr, ssrc_rtx_); + // Replace SSRC. + rtx_packet->SetSsrc(ssrc_rtx_); + } + uint8_t* rtx_payload = + rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize); + RTC_DCHECK(rtx_payload); // Add OSN (original sequence number). - ptr = data_buffer_rtx + rtp_header.headerLength; - ByteWriter::WriteBigEndian(ptr, rtp_header.sequenceNumber); - ptr += 2; + ByteWriter::WriteBigEndian(rtx_payload, packet.SequenceNumber()); // Add original payload data. - memcpy(ptr, buffer + rtp_header.headerLength, - *length - rtp_header.headerLength); - *length += 2; - return true; + memcpy(rtx_payload + kRtxHeaderSize, packet.payload(), packet.payload_size()); + + return rtx_packet; } void RTPSender::RegisterRtpStatisticsCallback( diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h index f068ae3570..14ec3c1f68 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h @@ -35,9 +35,10 @@ namespace webrtc { class RateLimiter; +class RtcEventLog; +class RtpPacketToSend; class RTPSenderAudio; class RTPSenderVideo; -class RtcEventLog; class RTPSenderInterface { public: @@ -277,12 +278,16 @@ class RTPSender : public RTPSenderInterface { uint32_t Timestamp() const override; uint32_t SSRC() const override; + // Deprecated. Create RtpPacketToSend instead and use next function. bool SendToNetwork(uint8_t* data_buffer, size_t payload_length, size_t rtp_header_length, int64_t capture_time_ms, StorageType storage, RtpPacketSender::Priority priority) override; + bool SendToNetwork(std::unique_ptr packet, + StorageType storage, + RtpPacketSender::Priority priority); // Audio. @@ -359,9 +364,7 @@ class RTPSender : public RTPSenderInterface { const std::vector& csrcs) const EXCLUSIVE_LOCKS_REQUIRED(send_critsect_); - bool PrepareAndSendPacket(uint8_t* buffer, - size_t length, - int64_t capture_time_ms, + bool PrepareAndSendPacket(std::unique_ptr packet, bool send_over_rtx, bool is_retransmit, int probe_cluster_id); @@ -370,14 +373,10 @@ class RTPSender : public RTPSenderInterface { // return a larger value that their argument. size_t TrySendRedundantPayloads(size_t bytes, int probe_cluster_id); - void BuildPaddingPacket(uint8_t* packet, - size_t header_length, - size_t padding_length); + std::unique_ptr BuildRtxPacket( + const RtpPacketToSend& packet); - bool BuildRtxPacket(uint8_t* buffer, size_t* length, uint8_t* buffer_rtx); - - bool SendPacketToNetwork(const uint8_t* packet, - size_t size, + bool SendPacketToNetwork(const RtpPacketToSend& packet, const PacketOptions& options); void UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms); @@ -394,19 +393,8 @@ class RTPSender : public RTPSenderInterface { size_t* position) const EXCLUSIVE_LOCKS_REQUIRED(send_critsect_); - void UpdateTransmissionTimeOffset(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int64_t time_diff_ms) const; - void UpdateAbsoluteSendTime(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int64_t now_ms) const; - - bool UpdateTransportSequenceNumber(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int* sequence_number) const; + bool UpdateTransportSequenceNumber(RtpPacketToSend* packet, + int* packet_id) const; void UpdatePlayoutDelayLimits(uint8_t* rtp_packet, size_t rtp_packet_length, @@ -414,14 +402,10 @@ class RTPSender : public RTPSenderInterface { uint16_t min_playout_delay, uint16_t max_playout_delay) const; - bool AllocateTransportSequenceNumber(int* packet_id) const; - - void UpdateRtpStats(const uint8_t* buffer, - size_t packet_length, - const RTPHeader& header, + void UpdateRtpStats(const RtpPacketToSend& packet, bool is_rtx, bool is_retransmit); - bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const; + bool IsFecPacket(const RtpPacketToSend& packet) const; Clock* const clock_; const int64_t clock_delta_ms_; @@ -458,7 +442,7 @@ class RTPSender : public RTPSenderInterface { PlayoutDelayOracle playout_delay_oracle_; bool playout_delay_active_ GUARDED_BY(send_critsect_); - RTPPacketHistory packet_history_; + RtpPacketHistory packet_history_; // Statistics rtc::CriticalSection statistics_crit_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc index ce032eca17..cabd411abf 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -149,6 +149,7 @@ class RtpSenderTest : public ::testing::Test { &mock_rtc_event_log_, &send_packet_observer_, &retransmission_rate_limiter_)); rtp_sender_->SetSequenceNumber(kSeqNum); + rtp_sender_->SetSendPayloadType(kPayload); } SimulatedClock fake_clock_;