diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc index 399c133cd1..8443894066 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc @@ -19,6 +19,7 @@ #include "webrtc/common_types.h" #include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h" @@ -28,197 +29,6 @@ namespace webrtc { namespace { // Anonymous namespace; hide utility functions and classes. -// A very simple packet builder class for building RTCP packets. -class PacketBuilder { - public: - static const int kMaxPacketSize = 1024; - - struct ReportBlock { - ReportBlock(uint32_t ssrc, uint32_t extended_max, uint8_t fraction_loss, - uint32_t cumulative_loss, uint32_t jitter) - : ssrc(ssrc), - extended_max(extended_max), - fraction_loss(fraction_loss), - cumulative_loss(cumulative_loss), - jitter(jitter) {} - - uint32_t ssrc; - uint32_t extended_max; - uint8_t fraction_loss; - uint32_t cumulative_loss; - uint32_t jitter; - }; - - PacketBuilder() - : pos_(0), - pos_of_len_(0) { - } - - - void Add8(uint8_t byte) { - EXPECT_LT(pos_, kMaxPacketSize - 1); - buffer_[pos_] = byte; - ++pos_; - } - - void Add16(uint16_t word) { - Add8(word >> 8); - Add8(word & 0xFF); - } - - void Add32(uint32_t word) { - Add8(word >> 24); - Add8((word >> 16) & 0xFF); - Add8((word >> 8) & 0xFF); - Add8(word & 0xFF); - } - - void Add64(uint32_t upper_half, uint32_t lower_half) { - Add32(upper_half); - Add32(lower_half); - } - - // Set the 5-bit value in the 1st byte of the header - // and the payload type. Set aside room for the length field, - // and make provision for backpatching it. - // Note: No way to set the padding bit. - void AddRtcpHeader(int payload, int format_or_count) { - PatchLengthField(); - Add8(0x80 | (format_or_count & 0x1F)); - Add8(payload); - pos_of_len_ = pos_; - Add16(0xDEAD); // Initialize length to "clearly illegal". - } - - void AddTmmbrBandwidth(int mantissa, int exponent, int overhead) { - // 6 bits exponent, 17 bits mantissa, 9 bits overhead. - uint32_t word = 0; - word |= (exponent << 26); - word |= ((mantissa & 0x1FFFF) << 9); - word |= (overhead & 0x1FF); - Add32(word); - } - - void AddSrPacket(uint32_t sender_ssrc) { - AddRtcpHeader(200, 0); - Add32(sender_ssrc); - Add64(0x10203, 0x4050607); // NTP timestamp - Add32(0x10203); // RTP timestamp - Add32(0); // Sender's packet count - Add32(0); // Sender's octet count - } - - void AddRrPacket(uint32_t sender_ssrc, uint32_t rtp_ssrc, - uint32_t extended_max, uint8_t fraction_loss, - uint32_t cumulative_loss, uint32_t jitter) { - ReportBlock report_block(rtp_ssrc, extended_max, fraction_loss, - cumulative_loss, jitter); - std::list report_block_vector(&report_block, - &report_block + 1); - AddRrPacketMultipleReportBlocks(sender_ssrc, report_block_vector); - } - - void AddRrPacketMultipleReportBlocks( - uint32_t sender_ssrc, const std::list& report_blocks) { - AddRtcpHeader(201, report_blocks.size()); - Add32(sender_ssrc); - for (std::list::const_iterator it = report_blocks.begin(); - it != report_blocks.end(); ++it) { - AddReportBlock(it->ssrc, it->extended_max, it->fraction_loss, - it->cumulative_loss, it->jitter); - } - } - - void AddReportBlock(uint32_t rtp_ssrc, uint32_t extended_max, - uint8_t fraction_loss, uint32_t cumulative_loss, - uint32_t jitter) { - Add32(rtp_ssrc); - Add32((fraction_loss << 24) + cumulative_loss); - Add32(extended_max); - Add32(jitter); - Add32(0); // Last SR. - Add32(0); // Delay since last SR. - } - - void AddXrHeader(uint32_t sender_ssrc) { - AddRtcpHeader(207, 0); - Add32(sender_ssrc); - } - - void AddXrReceiverReferenceTimeBlock(uint32_t ntp_sec, uint32_t ntp_frac) { - Add8(4); // Block type. - Add8(0); // Reserved. - Add16(2); // Length. - Add64(ntp_sec, ntp_frac); // NTP timestamp. - } - - void AddXrDlrrBlock(std::vector& remote_ssrc) { - ASSERT_LT(pos_ + 4 + static_cast(remote_ssrc.size())*4, - kMaxPacketSize-1) << "Max buffer size reached."; - Add8(5); // Block type. - Add8(0); // Reserved. - Add16(remote_ssrc.size() * 3); // Length. - for (size_t i = 0; i < remote_ssrc.size(); ++i) { - Add32(remote_ssrc.at(i)); // Receiver SSRC. - Add32(0x10203); // Last RR. - Add32(0x40506); // Delay since last RR. - } - } - - void AddXrUnknownBlock() { - Add8(6); // Block type. - Add8(0); // Reserved. - Add16(9); // Length. - Add32(0); // Receiver SSRC. - Add64(0, 0); // Remaining fields (RFC 3611) are set to zero. - Add64(0, 0); - Add64(0, 0); - Add64(0, 0); - } - - void AddXrVoipBlock(uint32_t remote_ssrc, uint8_t loss) { - Add8(7); // Block type. - Add8(0); // Reserved. - Add16(8); // Length. - Add32(remote_ssrc); // Receiver SSRC. - Add8(loss); // Loss rate. - Add8(0); // Remaining statistics (RFC 3611) are set to zero. - Add16(0); - Add64(0, 0); - Add64(0, 0); - Add64(0, 0); - } - - const uint8_t* packet() { - PatchLengthField(); - return buffer_; - } - - unsigned int length() { - return pos_; - } - private: - void PatchLengthField() { - if (pos_of_len_ > 0) { - // Backpatch the packet length. The client must have taken - // care of proper padding to 32-bit words. - int this_packet_length = (pos_ - pos_of_len_ - 2); - ASSERT_EQ(0, this_packet_length % 4) - << "Packets must be a multiple of 32 bits long" - << " pos " << pos_ << " pos_of_len " << pos_of_len_; - buffer_[pos_of_len_] = this_packet_length >> 10; - buffer_[pos_of_len_+1] = (this_packet_length >> 2) & 0xFF; - pos_of_len_ = 0; - } - } - - int pos_; - // Where the length field of the current packet is. - // Note that 0 is not a legal value, so is used for "uninitialized". - int pos_of_len_; - uint8_t buffer_[kMaxPacketSize]; -}; - // This test transport verifies that no functions get called. class TestTransport : public Transport, public NullRtpData { @@ -338,9 +148,10 @@ TEST_F(RtcpReceiverTest, BrokenPacketIsIgnored) { TEST_F(RtcpReceiverTest, InjectSrPacket) { const uint32_t kSenderSsrc = 0x10203; - PacketBuilder p; - p.AddSrPacket(kSenderSsrc); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::SenderReport sr; + sr.From(kSenderSsrc); + rtcp::RawPacket p = sr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); // The parser will note the remote SSRC on a SR from other than his // expected peer, but will not flag that he's gotten a packet. EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC); @@ -349,9 +160,10 @@ TEST_F(RtcpReceiverTest, InjectSrPacket) { } TEST_F(RtcpReceiverTest, XrPacketWithZeroReportBlocksIgnored) { - PacketBuilder p; - p.AddXrHeader(0x2345); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::Xr xr; + xr.From(0x2345); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(0U, rtcp_packet_info_.rtcpPacketTypeFlags); } @@ -362,37 +174,47 @@ TEST_F(RtcpReceiverTest, InjectXrVoipPacket) { rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); const uint8_t kLossRate = 123; - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrVoipBlock(kSourceSsrc, kLossRate); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::VoipMetric voip_metric; + voip_metric.To(kSourceSsrc); + voip_metric.LossRate(kLossRate); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithVoipMetric(&voip_metric); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); ASSERT_TRUE(rtcp_packet_info_.VoIPMetric != NULL); EXPECT_EQ(kLossRate, rtcp_packet_info_.VoIPMetric->lossRate); EXPECT_EQ(kRtcpXrVoipMetric, rtcp_packet_info_.rtcpPacketTypeFlags); } -TEST_F(RtcpReceiverTest, InjectXrReceiverReferenceTimePacket) { - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrReceiverReferenceTimeBlock(0x10203, 0x40506); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); - EXPECT_EQ(kRtcpXrReceiverReferenceTime, - rtcp_packet_info_.rtcpPacketTypeFlags); -} - -TEST_F(RtcpReceiverTest, InjectXrDlrrPacketWithNoSubBlock) { +TEST_F(RtcpReceiverTest, XrVoipPacketNotToUsIgnored) { const uint32_t kSourceSsrc = 0x123456; std::set ssrcs; ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - std::vector remote_ssrcs; - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrDlrrBlock(remote_ssrcs); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::VoipMetric voip_metric; + voip_metric.To(kSourceSsrc + 1); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithVoipMetric(&voip_metric); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(0U, rtcp_packet_info_.rtcpPacketTypeFlags); - EXPECT_FALSE(rtcp_packet_info_.xr_dlrr_item); +} + +TEST_F(RtcpReceiverTest, InjectXrReceiverReferenceTimePacket) { + rtcp::Rrtr rrtr; + rrtr.WithNtpSec(0x10203); + rrtr.WithNtpFrac(0x40506); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithRrtr(&rrtr); + + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); + EXPECT_EQ(kRtcpXrReceiverReferenceTime, + rtcp_packet_info_.rtcpPacketTypeFlags); } TEST_F(RtcpReceiverTest, XrDlrrPacketNotToUsIgnored) { @@ -400,13 +222,14 @@ TEST_F(RtcpReceiverTest, XrDlrrPacketNotToUsIgnored) { std::set ssrcs; ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - std::vector remote_ssrcs; - remote_ssrcs.push_back(kSourceSsrc+1); - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrDlrrBlock(remote_ssrcs); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::Dlrr dlrr; + dlrr.WithDlrrItem(kSourceSsrc + 1, 0x12345, 0x67890); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithDlrr(&dlrr); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(0U, rtcp_packet_info_.rtcpPacketTypeFlags); EXPECT_FALSE(rtcp_packet_info_.xr_dlrr_item); } @@ -416,13 +239,14 @@ TEST_F(RtcpReceiverTest, InjectXrDlrrPacketWithSubBlock) { std::set ssrcs; ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - std::vector remote_ssrcs; - remote_ssrcs.push_back(kSourceSsrc); - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrDlrrBlock(remote_ssrcs); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::Dlrr dlrr; + dlrr.WithDlrrItem(kSourceSsrc, 0x12345, 0x67890); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithDlrr(&dlrr); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); // The parser should note the DLRR report block item, but not flag the packet // since the RTT is not estimated. EXPECT_TRUE(rtcp_packet_info_.xr_dlrr_item); @@ -433,36 +257,39 @@ TEST_F(RtcpReceiverTest, InjectXrDlrrPacketWithMultipleSubBlocks) { std::set ssrcs; ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - std::vector remote_ssrcs; - remote_ssrcs.push_back(kSourceSsrc+2); - remote_ssrcs.push_back(kSourceSsrc+1); - remote_ssrcs.push_back(kSourceSsrc); - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrDlrrBlock(remote_ssrcs); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::Dlrr dlrr; + dlrr.WithDlrrItem(kSourceSsrc + 1, 0x12345, 0x67890); + dlrr.WithDlrrItem(kSourceSsrc + 2, 0x12345, 0x67890); + dlrr.WithDlrrItem(kSourceSsrc, 0x12345, 0x67890); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithDlrr(&dlrr); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); // The parser should note the DLRR report block item, but not flag the packet // since the RTT is not estimated. EXPECT_TRUE(rtcp_packet_info_.xr_dlrr_item); } TEST_F(RtcpReceiverTest, InjectXrPacketWithMultipleReportBlocks) { - const uint8_t kLossRate = 123; const uint32_t kSourceSsrc = 0x123456; std::set ssrcs; ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - std::vector remote_ssrcs; - remote_ssrcs.push_back(kSourceSsrc); - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrDlrrBlock(remote_ssrcs); - p.AddXrVoipBlock(kSourceSsrc, kLossRate); - p.AddXrReceiverReferenceTimeBlock(0x10203, 0x40506); - - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::Rrtr rrtr; + rtcp::Dlrr dlrr; + dlrr.WithDlrrItem(kSourceSsrc, 0x12345, 0x67890); + rtcp::VoipMetric metric; + metric.To(kSourceSsrc); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithRrtr(&rrtr); + xr.WithDlrr(&dlrr); + xr.WithVoipMetric(&metric); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(static_cast(kRtcpXrReceiverReferenceTime + kRtcpXrVoipMetric), rtcp_packet_info_.rtcpPacketTypeFlags); @@ -472,7 +299,6 @@ TEST_F(RtcpReceiverTest, InjectXrPacketWithMultipleReportBlocks) { } TEST_F(RtcpReceiverTest, InjectXrPacketWithUnknownReportBlock) { - const uint8_t kLossRate = 123; const uint32_t kSourceSsrc = 0x123456; std::set ssrcs; ssrcs.insert(kSourceSsrc); @@ -480,16 +306,27 @@ TEST_F(RtcpReceiverTest, InjectXrPacketWithUnknownReportBlock) { std::vector remote_ssrcs; remote_ssrcs.push_back(kSourceSsrc); - PacketBuilder p; - p.AddXrHeader(0x2345); - p.AddXrVoipBlock(kSourceSsrc, kLossRate); - p.AddXrUnknownBlock(); - p.AddXrReceiverReferenceTimeBlock(0x10203, 0x40506); + rtcp::Rrtr rrtr; + rtcp::Dlrr dlrr; + dlrr.WithDlrrItem(kSourceSsrc, 0x12345, 0x67890); + rtcp::VoipMetric metric; + metric.To(kSourceSsrc); + rtcp::Xr xr; + xr.From(0x2345); + xr.WithRrtr(&rrtr); + xr.WithDlrr(&dlrr); + xr.WithVoipMetric(&metric); + rtcp::RawPacket p = xr.Build(); + // Modify the DLRR block to have an unsupported block type, from 5 to 6. + uint8_t* buffer = const_cast(p.buffer()); + EXPECT_EQ(5, buffer[20]); + buffer[20] = 6; - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(static_cast(kRtcpXrReceiverReferenceTime + kRtcpXrVoipMetric), rtcp_packet_info_.rtcpPacketTypeFlags); + EXPECT_FALSE(rtcp_packet_info_.xr_dlrr_item); } TEST(RtcpUtilityTest, MidNtp) { @@ -515,10 +352,14 @@ TEST_F(RtcpReceiverTest, GetLastReceivedXrReferenceTimeInfo) { const uint32_t kNtpFrac = 0x40506; const uint32_t kNtpMid = RTCPUtility::MidNtp(kNtpSec, kNtpFrac); - PacketBuilder p; - p.AddXrHeader(kSenderSsrc); - p.AddXrReceiverReferenceTimeBlock(kNtpSec, kNtpFrac); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::Rrtr rrtr; + rrtr.WithNtpSec(kNtpSec); + rrtr.WithNtpFrac(kNtpFrac); + rtcp::Xr xr; + xr.From(kSenderSsrc); + xr.WithRrtr(&rrtr); + rtcp::RawPacket p = xr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(kRtcpXrReceiverReferenceTime, rtcp_packet_info_.rtcpPacketTypeFlags); @@ -542,7 +383,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - uint32_t sequence_number = 1234; + const uint16_t kSequenceNumber = 1234; system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs); // No RR received, shouldn't trigger a timeout. @@ -550,18 +391,21 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); // Add a RR and advance the clock just enough to not trigger a timeout. - PacketBuilder p1; - p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0, 0); - EXPECT_EQ(0, InjectRtcpPacket(p1.packet(), p1.length())); + rtcp::ReportBlock rb1; + rb1.To(kSourceSsrc); + rb1.WithExtHighestSeqNum(kSequenceNumber); + rtcp::ReceiverReport rr1; + rr1.From(kSenderSsrc); + rr1.WithReportBlock(&rb1); + rtcp::RawPacket p1 = rr1.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p1.buffer(), p1.buffer_length())); system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1); EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); // Add a RR with the same extended max as the previous RR to trigger a // sequence number timeout, but not a RR timeout. - PacketBuilder p2; - p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0, 0); - EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length())); + EXPECT_EQ(0, InjectRtcpPacket(p1.buffer(), p1.buffer_length())); system_clock_.AdvanceTimeMilliseconds(2); EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); EXPECT_TRUE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); @@ -576,18 +420,20 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) { EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); // Add a new RR with increase sequence number to reset timers. - PacketBuilder p3; - sequence_number++; - p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0, 0); - EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length())); + rtcp::ReportBlock rb2; + rb2.To(kSourceSsrc); + rb2.WithExtHighestSeqNum(kSequenceNumber + 1); + rtcp::ReceiverReport rr2; + rr2.From(kSenderSsrc); + rr2.WithReportBlock(&rb2); + rtcp::RawPacket p2 = rr2.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p2.buffer(), p2.buffer_length())); EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); EXPECT_FALSE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); // Verify we can get a timeout again once we've received new RR. system_clock_.AdvanceTimeMilliseconds(2 * kRtcpIntervalMs); - PacketBuilder p4; - p4.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, 0, 0, 0); - EXPECT_EQ(0, InjectRtcpPacket(p4.packet(), p4.length())); + EXPECT_EQ(0, InjectRtcpPacket(p2.buffer(), p2.buffer_length())); system_clock_.AdvanceTimeMilliseconds(kRtcpIntervalMs + 1); EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs)); EXPECT_TRUE(rtcp_receiver_->RtcpRrSequenceNumberTimeout(kRtcpIntervalMs)); @@ -602,33 +448,51 @@ TEST_F(RtcpReceiverTest, TmmbrReceivedWithNoIncomingPacket) { TEST_F(RtcpReceiverTest, TwoReportBlocks) { const uint32_t kSenderSsrc = 0x10203; - const int kNumSsrcs = 2; - const uint32_t kSourceSsrcs[kNumSsrcs] = {0x40506, 0x50607}; - uint32_t sequence_numbers[kNumSsrcs] = {10, 12423}; + const uint32_t kSourceSsrcs[] = {0x40506, 0x50607}; + const uint16_t kSequenceNumbers[] = {10, 12423}; + const int kNumSsrcs = sizeof(kSourceSsrcs) / sizeof(kSourceSsrcs[0]); std::set ssrcs(kSourceSsrcs, kSourceSsrcs + kNumSsrcs); rtcp_receiver_->SetSsrcs(kSourceSsrcs[0], ssrcs); - PacketBuilder packet; - std::list report_blocks; - report_blocks.push_back(PacketBuilder::ReportBlock( - kSourceSsrcs[0], sequence_numbers[0], 10, 5, 0)); - report_blocks.push_back(PacketBuilder::ReportBlock( - kSourceSsrcs[1], sequence_numbers[1], 0, 0, 0)); - packet.AddRrPacketMultipleReportBlocks(kSenderSsrc, report_blocks); - EXPECT_EQ(0, InjectRtcpPacket(packet.packet(), packet.length())); + rtcp::ReportBlock rb1; + rb1.To(kSourceSsrcs[0]); + rb1.WithExtHighestSeqNum(kSequenceNumbers[0]); + rb1.WithFractionLost(10); + rb1.WithCumulativeLost(5); + + rtcp::ReportBlock rb2; + rb2.To(kSourceSsrcs[1]); + rb2.WithExtHighestSeqNum(kSequenceNumbers[1]); + + rtcp::ReceiverReport rr1; + rr1.From(kSenderSsrc); + rr1.WithReportBlock(&rb1); + rr1.WithReportBlock(&rb2); + + rtcp::RawPacket p1 = rr1.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p1.buffer(), p1.buffer_length())); ASSERT_EQ(2u, rtcp_packet_info_.report_blocks.size()); EXPECT_EQ(10, rtcp_packet_info_.report_blocks.front().fractionLost); EXPECT_EQ(0, rtcp_packet_info_.report_blocks.back().fractionLost); - PacketBuilder packet2; - report_blocks.clear(); - report_blocks.push_back(PacketBuilder::ReportBlock( - kSourceSsrcs[0], sequence_numbers[0], 0, 0, 0)); - report_blocks.push_back(PacketBuilder::ReportBlock( - kSourceSsrcs[1], sequence_numbers[1], 20, 10, 0)); - packet2.AddRrPacketMultipleReportBlocks(kSenderSsrc, report_blocks); - EXPECT_EQ(0, InjectRtcpPacket(packet2.packet(), packet2.length())); + rtcp::ReportBlock rb3; + rb3.To(kSourceSsrcs[0]); + rb3.WithExtHighestSeqNum(kSequenceNumbers[0]); + + rtcp::ReportBlock rb4; + rb4.To(kSourceSsrcs[1]); + rb4.WithExtHighestSeqNum(kSequenceNumbers[1]); + rb4.WithFractionLost(20); + rb4.WithCumulativeLost(10); + + rtcp::ReceiverReport rr2; + rr2.From(kSenderSsrc); + rr2.WithReportBlock(&rb3); + rr2.WithReportBlock(&rb4); + + rtcp::RawPacket p2 = rr2.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p2.buffer(), p2.buffer_length())); ASSERT_EQ(2u, rtcp_packet_info_.report_blocks.size()); EXPECT_EQ(0, rtcp_packet_info_.report_blocks.front().fractionLost); EXPECT_EQ(20, rtcp_packet_info_.report_blocks.back().fractionLost); @@ -637,98 +501,95 @@ TEST_F(RtcpReceiverTest, TwoReportBlocks) { TEST_F(RtcpReceiverTest, TmmbrPacketAccepted) { const uint32_t kMediaFlowSsrc = 0x2040608; const uint32_t kSenderSsrc = 0x10203; - const uint32_t kMediaRecipientSsrc = 0x101; std::set ssrcs; ssrcs.insert(kMediaFlowSsrc); // Matches "media source" above. rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); - PacketBuilder p; - p.AddSrPacket(kSenderSsrc); - // TMMBR packet. - p.AddRtcpHeader(205, 3); - p.Add32(kSenderSsrc); - p.Add32(kMediaRecipientSsrc); - p.Add32(kMediaFlowSsrc); - p.AddTmmbrBandwidth(30000, 0, 0); // 30 Kbits/sec bandwidth, no overhead. + rtcp::Tmmbr tmmbr; + tmmbr.From(kSenderSsrc); + tmmbr.To(kMediaFlowSsrc); + tmmbr.WithBitrateKbps(30); + + rtcp::SenderReport sr; + sr.From(kSenderSsrc); + sr.Append(&tmmbr); + rtcp::RawPacket p = sr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); TMMBRSet candidate_set; candidate_set.VerifyAndAllocateSet(1); EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(1, 0, &candidate_set)); EXPECT_LT(0U, candidate_set.Tmmbr(0)); - EXPECT_EQ(kMediaRecipientSsrc, candidate_set.Ssrc(0)); + EXPECT_EQ(kSenderSsrc, candidate_set.Ssrc(0)); } TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) { const uint32_t kMediaFlowSsrc = 0x2040608; const uint32_t kSenderSsrc = 0x10203; - const uint32_t kMediaRecipientSsrc = 0x101; - const uint32_t kOtherMediaFlowSsrc = 0x9999; - PacketBuilder p; - p.AddSrPacket(kSenderSsrc); - // TMMBR packet. - p.AddRtcpHeader(205, 3); - p.Add32(kSenderSsrc); - p.Add32(kMediaRecipientSsrc); - p.Add32(kOtherMediaFlowSsrc); // This SSRC is not what we're sending. - p.AddTmmbrBandwidth(30000, 0, 0); + rtcp::Tmmbr tmmbr; + tmmbr.From(kSenderSsrc); + tmmbr.To(kMediaFlowSsrc + 1); // This SSRC is not what we are sending. + tmmbr.WithBitrateKbps(30); + + rtcp::SenderReport sr; + sr.From(kSenderSsrc); + sr.Append(&tmmbr); + rtcp::RawPacket p = sr.Build(); std::set ssrcs; ssrcs.insert(kMediaFlowSsrc); rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(0, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); } TEST_F(RtcpReceiverTest, TmmbrPacketZeroRateIgnored) { const uint32_t kMediaFlowSsrc = 0x2040608; const uint32_t kSenderSsrc = 0x10203; - const uint32_t kMediaRecipientSsrc = 0x101; std::set ssrcs; ssrcs.insert(kMediaFlowSsrc); // Matches "media source" above. rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); - PacketBuilder p; - p.AddSrPacket(kSenderSsrc); - // TMMBR packet. - p.AddRtcpHeader(205, 3); - p.Add32(kSenderSsrc); - p.Add32(kMediaRecipientSsrc); - p.Add32(kMediaFlowSsrc); - p.AddTmmbrBandwidth(0, 0, 0); // Rate zero. + rtcp::Tmmbr tmmbr; + tmmbr.From(kSenderSsrc); + tmmbr.To(kMediaFlowSsrc); + tmmbr.WithBitrateKbps(0); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::SenderReport sr; + sr.From(kSenderSsrc); + sr.Append(&tmmbr); + rtcp::RawPacket p = sr.Build(); + + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); EXPECT_EQ(0, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); } TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) { const uint32_t kMediaFlowSsrc = 0x2040608; const uint32_t kSenderSsrc = 0x10203; - const uint32_t kMediaRecipientSsrc = 0x101; std::set ssrcs; ssrcs.insert(kMediaFlowSsrc); // Matches "media source" above. rtcp_receiver_->SetSsrcs(kMediaFlowSsrc, ssrcs); - // Inject 3 packets "from" kMediaRecipientSsrc, Ssrc+1, Ssrc+2. + // Inject 3 packets "from" kSenderSsrc, kSenderSsrc+1, kSenderSsrc+2. // The times of arrival are starttime + 0, starttime + 5 and starttime + 10. - for (uint32_t ssrc = kMediaRecipientSsrc; - ssrc < kMediaRecipientSsrc+3; ++ssrc) { - PacketBuilder p; - p.AddSrPacket(kSenderSsrc); - // TMMBR packet. - p.AddRtcpHeader(205, 3); - p.Add32(kSenderSsrc); - p.Add32(ssrc); - p.Add32(kMediaFlowSsrc); - p.AddTmmbrBandwidth(30000, 0, 0); // 30 Kbits/sec bandwidth, no overhead. + for (uint32_t ssrc = kSenderSsrc; ssrc < kSenderSsrc + 3; ++ssrc) { + rtcp::Tmmbr tmmbr; + tmmbr.From(ssrc); + tmmbr.To(kMediaFlowSsrc); + tmmbr.WithBitrateKbps(30); - EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length())); + rtcp::SenderReport sr; + sr.From(ssrc); + sr.Append(&tmmbr); + rtcp::RawPacket p = sr.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p.buffer(), p.buffer_length())); // 5 seconds between each packet. system_clock_.AdvanceTimeMilliseconds(5000); } - // It is now starttime+15. + // It is now starttime + 15. EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); TMMBRSet candidate_set; candidate_set.VerifyAndAllocateSet(3); @@ -739,9 +600,8 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) { system_clock_.AdvanceTimeMilliseconds(12000); // Odd behaviour: Just counting them does not trigger the timeout. EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); - // Odd behaviour: There's only one left after timeout, not 2. - EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(3, 0, &candidate_set)); - EXPECT_EQ(kMediaRecipientSsrc + 2, candidate_set.Ssrc(0)); + EXPECT_EQ(2, rtcp_receiver_->TMMBRReceived(3, 0, &candidate_set)); + EXPECT_EQ(kSenderSsrc + 1, candidate_set.Ssrc(0)); } TEST_F(RtcpReceiverTest, Callbacks) { @@ -773,31 +633,48 @@ TEST_F(RtcpReceiverTest, Callbacks) { const uint32_t kSenderSsrc = 0x10203; const uint32_t kSourceSsrc = 0x123456; - const uint8_t fraction_loss = 3; - const uint32_t cumulative_loss = 7; - const uint32_t jitter = 9; - uint32_t sequence_number = 1234; + const uint8_t kFractionLoss = 3; + const uint32_t kCumulativeLoss = 7; + const uint32_t kJitter = 9; + const uint16_t kSequenceNumber = 1234; std::set ssrcs; ssrcs.insert(kSourceSsrc); rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs); - // First packet, all numbers should just propagate - PacketBuilder p1; - p1.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number, - fraction_loss, cumulative_loss, jitter); - EXPECT_EQ(0, InjectRtcpPacket(p1.packet(), p1.length())); - EXPECT_TRUE(callback.Matches(kSourceSsrc, sequence_number, fraction_loss, - cumulative_loss, jitter)); + // First packet, all numbers should just propagate. + rtcp::ReportBlock rb1; + rb1.To(kSourceSsrc); + rb1.WithExtHighestSeqNum(kSequenceNumber); + rb1.WithFractionLost(kFractionLoss); + rb1.WithCumulativeLost(kCumulativeLoss); + rb1.WithJitter(kJitter); + + rtcp::ReceiverReport rr1; + rr1.From(kSenderSsrc); + rr1.WithReportBlock(&rb1); + rtcp::RawPacket p1 = rr1.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p1.buffer(), p1.buffer_length())); + EXPECT_TRUE(callback.Matches(kSourceSsrc, kSequenceNumber, kFractionLoss, + kCumulativeLoss, kJitter)); rtcp_receiver_->RegisterRtcpStatisticsCallback(NULL); - // Add arbitrary numbers, callback should not be called (retain old values) - PacketBuilder p2; - p2.AddRrPacket(kSenderSsrc, kSourceSsrc, sequence_number + 1, 42, 137, 4711); - EXPECT_EQ(0, InjectRtcpPacket(p2.packet(), p2.length())); - EXPECT_TRUE(callback.Matches(kSourceSsrc, sequence_number, fraction_loss, - cumulative_loss, jitter)); + // Add arbitrary numbers, callback should not be called (retain old values). + rtcp::ReportBlock rb2; + rb2.To(kSourceSsrc); + rb2.WithExtHighestSeqNum(kSequenceNumber + 1); + rb2.WithFractionLost(42); + rb2.WithCumulativeLost(137); + rb2.WithJitter(4711); + + rtcp::ReceiverReport rr2; + rr2.From(kSenderSsrc); + rr2.WithReportBlock(&rb2); + rtcp::RawPacket p2 = rr2.Build(); + EXPECT_EQ(0, InjectRtcpPacket(p2.buffer(), p2.buffer_length())); + EXPECT_TRUE(callback.Matches(kSourceSsrc, kSequenceNumber, kFractionLoss, + kCumulativeLoss, kJitter)); } } // Anonymous namespace