From 5e57b17283f78dbc0f72815746bdda6d9a92b8f2 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Fri, 2 Sep 2016 19:15:59 +0200 Subject: [PATCH] Introduce helpers to RtpSender to propagate RtpPacketToSend. The helpers intended to replace and deprecate BuildRtpHeader when RtpSenderAudio/RtpSenderVideo will be updated to pass RtpPacket class instead of raw buffer for sending. BUG=webrtc:5261 R=sprang@webrtc.org Review URL: https://codereview.webrtc.org/2303283002 . Cr-Commit-Position: refs/heads/master@{#14051} --- webrtc/modules/rtp_rtcp/source/rtp_packet.h | 9 ++ webrtc/modules/rtp_rtcp/source/rtp_sender.cc | 30 ++++++ webrtc/modules/rtp_rtcp/source/rtp_sender.h | 8 ++ .../rtp_rtcp/source/rtp_sender_unittest.cc | 100 +++++++++++++++++- 4 files changed, 146 insertions(+), 1 deletion(-) diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet.h b/webrtc/modules/rtp_rtcp/source/rtp_packet.h index f1e3dd40f9..6981eabc25 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet.h @@ -83,6 +83,9 @@ class Packet { void SetCsrcs(const std::vector& csrcs); // Header extensions. + template + bool HasExtension() const; + template bool GetExtension(Values...) const; @@ -160,6 +163,12 @@ class Packet { Packet() = delete; }; +template +bool Packet::HasExtension() const { + uint16_t offset = 0; + return FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset); +} + template bool Packet::GetExtension(Values... values) const { uint16_t offset = 0; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 5a0dc13a6d..fc677d7760 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -1072,6 +1072,36 @@ size_t RTPSender::CreateRtpHeader(uint8_t* header, return rtp_header_length; } +std::unique_ptr RTPSender::AllocatePacket() const { + rtc::CritScope lock(&send_critsect_); + std::unique_ptr packet( + new RtpPacketToSend(&rtp_header_extension_map_, max_payload_length_)); + packet->SetSsrc(ssrc_); + packet->SetCsrcs(csrcs_); + // Reserve extensions, if registered, RtpSender set in SendToNetwork. + packet->ReserveExtension(); + packet->ReserveExtension(); + packet->ReserveExtension(); + return packet; +} + +bool RTPSender::AssignSequenceNumber(RtpPacketToSend* packet) { + rtc::CritScope lock(&send_critsect_); + if (!sending_media_) + return false; + RTC_DCHECK_EQ(packet->Ssrc(), ssrc_); + packet->SetSequenceNumber(sequence_number_++); + + // Remember marker bit to determine if padding can be inserted with + // sequence number following |packet|. + last_packet_marker_bit_ = packet->Marker(); + // Save timestamps to generate timestamp field and extensions for the padding. + last_rtp_timestamp_ = packet->Timestamp(); + last_timestamp_time_ms_ = clock_->TimeInMilliseconds(); + capture_time_ms_ = packet->capture_time_ms(); + return true; +} + int32_t RTPSender::BuildRTPheader(uint8_t* data_buffer, int8_t payload_type, bool marker_bit, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h index 7a6677b408..6c9928c793 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h @@ -203,6 +203,14 @@ class RTPSender { void SetRtxPayloadType(int payload_type, int associated_payload_type); + // Create empty packet, fills ssrc, csrcs and reserve place for header + // extensions RtpSender updates before sending. + std::unique_ptr AllocatePacket() const; + // Allocate sequence number for provided packet. + // Save packet's fields to generate padding that doesn't break media stream. + // Return false if sending was turned off. + bool AssignSequenceNumber(RtpPacketToSend* packet); + // Functions wrapping RTPSenderInterface. int32_t BuildRTPheader(uint8_t* data_buffer, int8_t payload_type, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc index e11bf1ee5a..de5aaf3bad 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -22,6 +22,8 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.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.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" @@ -53,7 +55,8 @@ const VideoRotation kRotation = kVideoRotation_270; const size_t kGenericHeaderLength = 1; const uint8_t kPayloadData[] = {47, 11, 32, 93, 89}; -using testing::_; +using ::testing::_; +using ::testing::ElementsAreArray; const uint8_t* GetPayloadData(const RTPHeader& rtp_header, const uint8_t* packet) { @@ -372,6 +375,101 @@ TEST_F(RtpSenderTestWithoutPacer, RegisterRtpVideoRotationHeaderExtension) { EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionLength()); } +TEST_F(RtpSenderTestWithoutPacer, AllocatePacketSetCsrc) { + // Configure rtp_sender with csrc. + std::vector csrcs; + csrcs.push_back(0x23456789); + rtp_sender_->SetCsrcs(csrcs); + + auto packet = rtp_sender_->AllocatePacket(); + + ASSERT_TRUE(packet); + EXPECT_EQ(rtp_sender_->SSRC(), packet->Ssrc()); + EXPECT_EQ(csrcs, packet->Csrcs()); +} + +TEST_F(RtpSenderTestWithoutPacer, AllocatePacketReserveExtensions) { + // Configure rtp_sender with extensions. + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); + ASSERT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, + kAudioLevelExtensionId)); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionTransportSequenceNumber, + kTransportSequenceNumberExtensionId)); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionVideoRotation, kVideoRotationExtensionId)); + + auto packet = rtp_sender_->AllocatePacket(); + + ASSERT_TRUE(packet); + // Preallocate BWE extensions RtpSender set itself. + EXPECT_TRUE(packet->HasExtension()); + EXPECT_TRUE(packet->HasExtension()); + EXPECT_TRUE(packet->HasExtension()); + // Do not allocate media specific extensions. + EXPECT_FALSE(packet->HasExtension()); + EXPECT_FALSE(packet->HasExtension()); +} + +TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberAdvanceSequenceNumber) { + auto packet = rtp_sender_->AllocatePacket(); + ASSERT_TRUE(packet); + const uint16_t sequence_number = rtp_sender_->SequenceNumber(); + + EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get())); + + EXPECT_EQ(sequence_number, packet->SequenceNumber()); + EXPECT_EQ(sequence_number + 1, rtp_sender_->SequenceNumber()); +} + +TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberFailsOnNotSending) { + auto packet = rtp_sender_->AllocatePacket(); + ASSERT_TRUE(packet); + + rtp_sender_->SetSendingMediaStatus(false); + EXPECT_FALSE(rtp_sender_->AssignSequenceNumber(packet.get())); +} + +TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberMayAllowPadding) { + constexpr size_t kPaddingSize = 100; + auto packet = rtp_sender_->AllocatePacket(); + ASSERT_TRUE(packet); + + ASSERT_FALSE(rtp_sender_->SendPadData(kPaddingSize, false, 0, 0, -1)); + packet->SetMarker(false); + ASSERT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get())); + // Packet without marker bit doesn't allow padding. + EXPECT_FALSE(rtp_sender_->SendPadData(kPaddingSize, false, 0, 0, -1)); + + packet->SetMarker(true); + ASSERT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get())); + // Packet with marker bit allows send padding. + EXPECT_TRUE(rtp_sender_->SendPadData(kPaddingSize, false, 0, 0, -1)); +} + +TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberSetPaddingTimestamps) { + constexpr size_t kPaddingSize = 100; + auto packet = rtp_sender_->AllocatePacket(); + ASSERT_TRUE(packet); + packet->SetMarker(true); + packet->SetTimestamp(kTimestamp); + + ASSERT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get())); + ASSERT_TRUE(rtp_sender_->SendPadData(kPaddingSize, false, 0, 0, -1)); + + ASSERT_EQ(1u, transport_.sent_packets_.size()); + // Parse the padding packet and verify its timestamp. + RtpPacketToSend padding_packet(nullptr); + ASSERT_TRUE(padding_packet.Parse(transport_.sent_packets_[0]->data(), + transport_.sent_packets_[0]->size())); + EXPECT_EQ(kTimestamp, padding_packet.Timestamp()); +} + TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacket) { size_t length = static_cast(rtp_sender_->BuildRtpHeader( packet_, kPayload, kMarkerBit, kTimestamp, 0));