From 34ed2b95a59a3935d0a013cbc6d389b1608bf7eb Mon Sep 17 00:00:00 2001 From: danilchap Date: Mon, 18 Jan 2016 02:43:32 -0800 Subject: [PATCH] [rtp_rtcp] rtcp::SenderReport moved into own file and got Parse function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG=webrtc:5260 R=åsapersson Review URL: https://codereview.webrtc.org/1544983002 Cr-Commit-Position: refs/heads/master@{#11288} --- webrtc/call/rtc_event_log_unittest.cc | 5 +- webrtc/modules/modules.gyp | 1 + webrtc/modules/rtp_rtcp/BUILD.gn | 2 + webrtc/modules/rtp_rtcp/rtp_rtcp.gypi | 2 + webrtc/modules/rtp_rtcp/source/rtcp_packet.cc | 97 ------------- webrtc/modules/rtp_rtcp/source/rtcp_packet.h | 76 ----------- .../rtcp_packet/compound_packet_unittest.cc | 1 + .../source/rtcp_packet/sender_report.cc | 118 ++++++++++++++++ .../source/rtcp_packet/sender_report.h | 86 ++++++++++++ .../rtcp_packet/sender_report_unittest.cc | 117 ++++++++++++++++ .../rtp_rtcp/source/rtcp_packet_unittest.cc | 128 ------------------ .../rtp_rtcp/source/rtcp_receiver_unittest.cc | 1 + webrtc/modules/rtp_rtcp/source/rtcp_sender.cc | 4 +- webrtc/modules/rtp_rtcp/source/rtcp_sender.h | 1 + 14 files changed, 334 insertions(+), 305 deletions(-) create mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.cc create mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h create mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report_unittest.cc diff --git a/webrtc/call/rtc_event_log_unittest.cc b/webrtc/call/rtc_event_log_unittest.cc index f590f669a2..0998071827 100644 --- a/webrtc/call/rtc_event_log_unittest.cc +++ b/webrtc/call/rtc_event_log_unittest.cc @@ -23,6 +23,7 @@ #include "webrtc/call.h" #include "webrtc/call/rtc_event_log.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/test/test_suite.h" @@ -355,8 +356,8 @@ rtc::scoped_ptr GenerateRtcpPacket(Random* prng) { rtcp::SenderReport sender_report; sender_report.From(prng->Rand()); // Sender SSRC. - sender_report.WithNtpSec(prng->Rand()); - sender_report.WithNtpFrac(prng->Rand()); + sender_report.WithNtp( + NtpTime(prng->Rand(), prng->Rand())); sender_report.WithPacketCount(prng->Rand()); sender_report.WithReportBlock(report_block); diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index 37d43042a2..9c50d267e9 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -320,6 +320,7 @@ 'rtp_rtcp/source/rtcp_packet/rpsi_unittest.cc', 'rtp_rtcp/source/rtcp_packet/rrtr_unittest.cc', 'rtp_rtcp/source/rtcp_packet/sdes_unittest.cc', + 'rtp_rtcp/source/rtcp_packet/sender_report_unittest.cc', 'rtp_rtcp/source/rtcp_packet/sli_unittest.cc', 'rtp_rtcp/source/rtcp_packet/tmmbn_unittest.cc', 'rtp_rtcp/source/rtcp_packet/tmmbr_unittest.cc', diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn index 42de871f4a..f423d08f91 100644 --- a/webrtc/modules/rtp_rtcp/BUILD.gn +++ b/webrtc/modules/rtp_rtcp/BUILD.gn @@ -80,6 +80,8 @@ source_set("rtp_rtcp") { "source/rtcp_packet/rtpfb.h", "source/rtcp_packet/sdes.cc", "source/rtcp_packet/sdes.h", + "source/rtcp_packet/sender_report.cc", + "source/rtcp_packet/sender_report.h", "source/rtcp_packet/sli.cc", "source/rtcp_packet/sli.h", "source/rtcp_packet/tmmbn.cc", diff --git a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi index 1db044143f..a927e4ea64 100644 --- a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi +++ b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi @@ -75,6 +75,8 @@ 'source/rtcp_packet/rtpfb.h', 'source/rtcp_packet/sdes.cc', 'source/rtcp_packet/sdes.h', + 'source/rtcp_packet/sender_report.cc', + 'source/rtcp_packet/sender_report.h', 'source/rtcp_packet/sli.cc', 'source/rtcp_packet/sli.h', 'source/rtcp_packet/tmmbn.cc', diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc index ec87ed6bdb..eaaa78c2f0 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc @@ -10,23 +10,10 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" -#include - #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" -using webrtc::RTCPUtility::PT_APP; -using webrtc::RTCPUtility::PT_IJ; -using webrtc::RTCPUtility::PT_RTPFB; -using webrtc::RTCPUtility::PT_SR; - -using webrtc::RTCPUtility::RTCPPacketAPP; -using webrtc::RTCPUtility::RTCPPacketReportBlockItem; -using webrtc::RTCPUtility::RTCPPacketRTPFBNACK; -using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem; -using webrtc::RTCPUtility::RTCPPacketSR; - namespace webrtc { namespace rtcp { namespace { @@ -37,66 +24,6 @@ void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) { ByteWriter::WriteBigEndian(buffer + *offset, value); *offset += 2; } -void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { - ByteWriter::WriteBigEndian(buffer + *offset, value); - *offset += 4; -} - -// Sender report (SR) (RFC 3550). -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| RC | PT=SR=200 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of sender | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | NTP timestamp, most significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NTP timestamp, least significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | RTP timestamp | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | sender's packet count | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | sender's octet count | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - -void CreateSenderReport(const RTCPPacketSR& sr, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, sr.SenderSSRC); - AssignUWord32(buffer, pos, sr.NTPMostSignificant); - AssignUWord32(buffer, pos, sr.NTPLeastSignificant); - AssignUWord32(buffer, pos, sr.RTPTimestamp); - AssignUWord32(buffer, pos, sr.SenderPacketCount); - AssignUWord32(buffer, pos, sr.SenderOctetCount); -} - -// Report block (RFC 3550). -// -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_1 (SSRC of first source) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | fraction lost | cumulative number of packets lost | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | extended highest sequence number received | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | interarrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | last SR (LSR) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | delay since last SR (DLSR) | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - -void CreateReportBlocks(const std::vector& blocks, - uint8_t* buffer, - size_t* pos) { - for (const ReportBlock& block : blocks) { - block.Create(buffer + *pos); - *pos += ReportBlock::kLength; - } -} } // namespace void RtcpPacket::Append(RtcpPacket* packet) { @@ -195,30 +122,6 @@ void RtcpPacket::CreateHeader( AssignUWord16(buffer, pos, length); } -bool SenderReport::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - CreateHeader(sr_.NumberOfReportBlocks, PT_SR, HeaderLength(), packet, index); - CreateSenderReport(sr_, packet, index); - CreateReportBlocks(report_blocks_, packet, index); - return true; -} - -bool SenderReport::WithReportBlock(const ReportBlock& block) { - if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { - LOG(LS_WARNING) << "Max report blocks reached."; - return false; - } - report_blocks_.push_back(block); - sr_.NumberOfReportBlocks = report_blocks_.size(); - return true; -} - RawPacket::RawPacket(size_t buffer_length) : buffer_length_(buffer_length), length_(0) { buffer_.reset(new uint8_t[buffer_length]); diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h index 2cf90055e8..965a667304 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h @@ -15,8 +15,6 @@ #include #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/typedefs.h" @@ -24,7 +22,6 @@ namespace webrtc { namespace rtcp { static const int kCommonFbFmtLength = 12; -static const int kReportBlockLength = 24; class RawPacket; @@ -120,79 +117,6 @@ class RtcpPacket { PacketReadyCallback* callback) const; }; -// TODO(sprang): Move RtcpPacket subclasses out to separate files. - -// RTCP sender report (RFC 3550). -// -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| RC | PT=SR=200 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of sender | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | NTP timestamp, most significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NTP timestamp, least significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | RTP timestamp | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | sender's packet count | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | sender's octet count | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | report block(s) | -// | .... | - -class SenderReport : public RtcpPacket { - public: - SenderReport() : RtcpPacket() { - memset(&sr_, 0, sizeof(sr_)); - } - - virtual ~SenderReport() {} - - void From(uint32_t ssrc) { - sr_.SenderSSRC = ssrc; - } - void WithNtpSec(uint32_t sec) { - sr_.NTPMostSignificant = sec; - } - void WithNtpFrac(uint32_t frac) { - sr_.NTPLeastSignificant = frac; - } - void WithRtpTimestamp(uint32_t rtp_timestamp) { - sr_.RTPTimestamp = rtp_timestamp; - } - void WithPacketCount(uint32_t packet_count) { - sr_.SenderPacketCount = packet_count; - } - void WithOctetCount(uint32_t octet_count) { - sr_.SenderOctetCount = octet_count; - } - bool WithReportBlock(const ReportBlock& block); - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - static const int kMaxNumberOfReportBlocks = 0x1f; - - size_t BlockLength() const { - const size_t kSrHeaderLength = 8; - const size_t kSenderInfoLength = 20; - return kSrHeaderLength + kSenderInfoLength + - report_blocks_.size() * kReportBlockLength; - } - - RTCPUtility::RTCPPacketSR sr_; - std::vector report_blocks_; - - RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport); -}; - // Class holding a RTCP packet. // // Takes a built rtcp packet. diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc index b38b69c638..0378566977 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc @@ -15,6 +15,7 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" #include "webrtc/test/rtcp_packet_parser.h" using webrtc::rtcp::Bye; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.cc new file mode 100644 index 0000000000..ab1863ed46 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.cc @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { +// Sender report (SR) (RFC 3550). +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| RC | PT=SR=200 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 | SSRC of sender | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// 4 | NTP timestamp, most significant word | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | NTP timestamp, least significant word | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 12 | RTP timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 16 | sender's packet count | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 20 | sender's octet count | +// 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + +SenderReport::SenderReport() + : sender_ssrc_(0), + rtp_timestamp_(0), + sender_packet_count_(0), + sender_octet_count_(0) {} + +bool SenderReport::Parse(const RtcpCommonHeader& header, + const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + + const uint8_t report_block_count = header.count_or_format; + if (header.payload_size_bytes < + kSenderBaseLength + report_block_count * ReportBlock::kLength) { + LOG(LS_WARNING) << "Packet is too small to contain all the data."; + return false; + } + // Read SenderReport header. + sender_ssrc_ = ByteReader::ReadBigEndian(&payload[0]); + uint32_t secs = ByteReader::ReadBigEndian(&payload[4]); + uint32_t frac = ByteReader::ReadBigEndian(&payload[8]); + ntp_.Set(secs, frac); + rtp_timestamp_ = ByteReader::ReadBigEndian(&payload[12]); + sender_packet_count_ = ByteReader::ReadBigEndian(&payload[16]); + sender_octet_count_ = ByteReader::ReadBigEndian(&payload[20]); + report_blocks_.resize(report_block_count); + const uint8_t* next_block = payload + kSenderBaseLength; + for (ReportBlock& block : report_blocks_) { + bool block_parsed = block.Parse(next_block, ReportBlock::kLength); + RTC_DCHECK(block_parsed); + next_block += ReportBlock::kLength; + } + // Double check we didn't read beyond provided buffer. + RTC_DCHECK_LE(next_block, payload + header.payload_size_bytes); + return true; +} + +bool SenderReport::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + const size_t index_end = *index + BlockLength(); + + CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet, + index); + // Write SenderReport header. + ByteWriter::WriteBigEndian(&packet[*index + 0], sender_ssrc_); + ByteWriter::WriteBigEndian(&packet[*index + 4], ntp_.seconds()); + ByteWriter::WriteBigEndian(&packet[*index + 8], ntp_.fractions()); + ByteWriter::WriteBigEndian(&packet[*index + 12], rtp_timestamp_); + ByteWriter::WriteBigEndian(&packet[*index + 16], + sender_packet_count_); + ByteWriter::WriteBigEndian(&packet[*index + 20], + sender_octet_count_); + *index += kSenderBaseLength; + // Write report blocks. + for (const ReportBlock& block : report_blocks_) { + block.Create(packet + *index); + *index += ReportBlock::kLength; + } + // Ensure bytes written match expected. + RTC_DCHECK_EQ(*index, index_end); + return true; +} + +bool SenderReport::WithReportBlock(const ReportBlock& block) { + if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { + LOG(LS_WARNING) << "Max report blocks reached."; + return false; + } + report_blocks_.push_back(block); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h new file mode 100644 index 0000000000..e26911abc3 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * 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. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SENDER_REPORT_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SENDER_REPORT_H_ + +#include + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" +#include "webrtc/system_wrappers/include/ntp_time.h" + +namespace webrtc { +namespace rtcp { + +class SenderReport : public RtcpPacket { + public: + static const uint8_t kPacketType = 200; + + SenderReport(); + virtual ~SenderReport() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void WithNtp(NtpTime ntp) { ntp_ = ntp; } + void WithRtpTimestamp(uint32_t rtp_timestamp) { + rtp_timestamp_ = rtp_timestamp; + } + void WithPacketCount(uint32_t packet_count) { + sender_packet_count_ = packet_count; + } + void WithOctetCount(uint32_t octet_count) { + sender_octet_count_ = octet_count; + } + bool WithReportBlock(const ReportBlock& block); + void ClearReportBlocks() { report_blocks_.clear(); } + + uint32_t sender_ssrc() const { return sender_ssrc_; } + NtpTime ntp() const { return ntp_; } + uint32_t rtp_timestamp() const { return rtp_timestamp_; } + uint32_t sender_packet_count() const { return sender_packet_count_; } + uint32_t sender_octet_count() const { return sender_octet_count_; } + + const std::vector& report_blocks() const { + return report_blocks_; + } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + static const size_t kMaxNumberOfReportBlocks = 0x1f; + const size_t kSenderBaseLength = 24; + + size_t BlockLength() const override { + return kHeaderLength + kSenderBaseLength + + report_blocks_.size() * ReportBlock::kLength; + } + + uint32_t sender_ssrc_; + NtpTime ntp_; + uint32_t rtp_timestamp_; + uint32_t sender_packet_count_; + uint32_t sender_octet_count_; + std::vector report_blocks_; + + RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SENDER_REPORT_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report_unittest.cc new file mode 100644 index 0000000000..548c130224 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report_unittest.cc @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::ReportBlock; +using webrtc::rtcp::SenderReport; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { + +class RtcpPacketSenderReportTest : public ::testing::Test { + protected: + const uint32_t kSenderSsrc = 0x12345678; + const uint32_t kRemoteSsrc = 0x23456789; + + void ParsePacket(const RawPacket& packet) { + RtcpCommonHeader header; + EXPECT_TRUE( + RtcpParseCommonHeader(packet.Buffer(), packet.Length(), &header)); + EXPECT_EQ(packet.Length(), header.BlockSize()); + EXPECT_TRUE(parsed_.Parse( + header, packet.Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); + } + + // Only ParsePacket can change parsed, tests should use it in readonly mode. + const SenderReport& parsed() { return parsed_; } + + private: + SenderReport parsed_; +}; + +TEST_F(RtcpPacketSenderReportTest, WithoutReportBlocks) { + const NtpTime kNtp(0x11121418, 0x22242628); + const uint32_t kRtpTimestamp = 0x33343536; + const uint32_t kPacketCount = 0x44454647; + const uint32_t kOctetCount = 0x55565758; + + SenderReport sr; + sr.From(kSenderSsrc); + sr.WithNtp(kNtp); + sr.WithRtpTimestamp(kRtpTimestamp); + sr.WithPacketCount(kPacketCount); + sr.WithOctetCount(kOctetCount); + + rtc::scoped_ptr packet = sr.Build(); + ParsePacket(*packet); + + EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc()); + EXPECT_EQ(kNtp, parsed().ntp()); + EXPECT_EQ(kRtpTimestamp, parsed().rtp_timestamp()); + EXPECT_EQ(kPacketCount, parsed().sender_packet_count()); + EXPECT_EQ(kOctetCount, parsed().sender_octet_count()); + EXPECT_TRUE(parsed().report_blocks().empty()); +} + +TEST_F(RtcpPacketSenderReportTest, WithOneReportBlock) { + ReportBlock rb; + rb.To(kRemoteSsrc); + + SenderReport sr; + sr.From(kSenderSsrc); + EXPECT_TRUE(sr.WithReportBlock(rb)); + + rtc::scoped_ptr packet = sr.Build(); + ParsePacket(*packet); + + EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc()); + EXPECT_EQ(1u, parsed().report_blocks().size()); + EXPECT_EQ(kRemoteSsrc, parsed().report_blocks()[0].source_ssrc()); +} + +TEST_F(RtcpPacketSenderReportTest, WithTwoReportBlocks) { + ReportBlock rb1; + rb1.To(kRemoteSsrc); + ReportBlock rb2; + rb2.To(kRemoteSsrc + 1); + + SenderReport sr; + sr.From(kSenderSsrc); + EXPECT_TRUE(sr.WithReportBlock(rb1)); + EXPECT_TRUE(sr.WithReportBlock(rb2)); + + rtc::scoped_ptr packet = sr.Build(); + ParsePacket(*packet); + + EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc()); + EXPECT_EQ(2u, parsed().report_blocks().size()); + EXPECT_EQ(kRemoteSsrc, parsed().report_blocks()[0].source_ssrc()); + EXPECT_EQ(kRemoteSsrc + 1, parsed().report_blocks()[1].source_ssrc()); +} + +TEST_F(RtcpPacketSenderReportTest, WithTooManyReportBlocks) { + SenderReport sr; + sr.From(kSenderSsrc); + const size_t kMaxReportBlocks = (1 << 5) - 1; + ReportBlock rb; + for (size_t i = 0; i < kMaxReportBlocks; ++i) { + rb.To(kRemoteSsrc + i); + EXPECT_TRUE(sr.WithReportBlock(rb)); + } + rb.To(kRemoteSsrc + kMaxReportBlocks); + EXPECT_FALSE(sr.WithReportBlock(rb)); +} + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc index 6b4ef902a1..1b5d4f32a6 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc @@ -14,142 +14,14 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" -#include "webrtc/test/rtcp_packet_parser.h" -using ::testing::ElementsAre; - -using webrtc::rtcp::App; -using webrtc::rtcp::Bye; -using webrtc::rtcp::RawPacket; using webrtc::rtcp::ReceiverReport; using webrtc::rtcp::ReportBlock; -using webrtc::rtcp::SenderReport; -using webrtc::test::RtcpPacketParser; namespace webrtc { const uint32_t kSenderSsrc = 0x12345678; -const uint32_t kRemoteSsrc = 0x23456789; - -TEST(RtcpPacketTest, Sr) { - SenderReport sr; - sr.From(kSenderSsrc); - sr.WithNtpSec(0x11111111); - sr.WithNtpFrac(0x22222222); - sr.WithRtpTimestamp(0x33333333); - sr.WithPacketCount(0x44444444); - sr.WithOctetCount(0x55555555); - - rtc::scoped_ptr packet(sr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - - EXPECT_EQ(1, parser.sender_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.sender_report()->Ssrc()); - EXPECT_EQ(0x11111111U, parser.sender_report()->NtpSec()); - EXPECT_EQ(0x22222222U, parser.sender_report()->NtpFrac()); - EXPECT_EQ(0x33333333U, parser.sender_report()->RtpTimestamp()); - EXPECT_EQ(0x44444444U, parser.sender_report()->PacketCount()); - EXPECT_EQ(0x55555555U, parser.sender_report()->OctetCount()); - EXPECT_EQ(0, parser.report_block()->num_packets()); -} - -TEST(RtcpPacketTest, SrWithOneReportBlock) { - ReportBlock rb; - rb.To(kRemoteSsrc); - - SenderReport sr; - sr.From(kSenderSsrc); - EXPECT_TRUE(sr.WithReportBlock(rb)); - - rtc::scoped_ptr packet(sr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.sender_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.sender_report()->Ssrc()); - EXPECT_EQ(1, parser.report_block()->num_packets()); - EXPECT_EQ(kRemoteSsrc, parser.report_block()->Ssrc()); -} - -TEST(RtcpPacketTest, SrWithTwoReportBlocks) { - ReportBlock rb1; - rb1.To(kRemoteSsrc); - ReportBlock rb2; - rb2.To(kRemoteSsrc + 1); - - SenderReport sr; - sr.From(kSenderSsrc); - EXPECT_TRUE(sr.WithReportBlock(rb1)); - EXPECT_TRUE(sr.WithReportBlock(rb2)); - - rtc::scoped_ptr packet(sr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.sender_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.sender_report()->Ssrc()); - EXPECT_EQ(2, parser.report_block()->num_packets()); - EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc)); - EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc + 1)); -} - -TEST(RtcpPacketTest, SrWithTooManyReportBlocks) { - SenderReport sr; - sr.From(kSenderSsrc); - const int kMaxReportBlocks = (1 << 5) - 1; - ReportBlock rb; - for (int i = 0; i < kMaxReportBlocks; ++i) { - rb.To(kRemoteSsrc + i); - EXPECT_TRUE(sr.WithReportBlock(rb)); - } - rb.To(kRemoteSsrc + kMaxReportBlocks); - EXPECT_FALSE(sr.WithReportBlock(rb)); -} - -TEST(RtcpPacketTest, AppWithNoData) { - App app; - app.WithSubType(30); - uint32_t name = 'n' << 24; - name += 'a' << 16; - name += 'm' << 8; - name += 'e'; - app.WithName(name); - - rtc::scoped_ptr packet(app.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.app()->num_packets()); - EXPECT_EQ(30U, parser.app()->SubType()); - EXPECT_EQ(name, parser.app()->Name()); - EXPECT_EQ(0, parser.app_item()->num_packets()); -} - -TEST(RtcpPacketTest, App) { - App app; - app.From(kSenderSsrc); - app.WithSubType(30); - uint32_t name = 'n' << 24; - name += 'a' << 16; - name += 'm' << 8; - name += 'e'; - app.WithName(name); - const char kData[] = {'t', 'e', 's', 't', 'd', 'a', 't', 'a'}; - const size_t kDataLength = sizeof(kData) / sizeof(kData[0]); - app.WithData((const uint8_t*)kData, kDataLength); - - rtc::scoped_ptr packet(app.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.app()->num_packets()); - EXPECT_EQ(30U, parser.app()->SubType()); - EXPECT_EQ(name, parser.app()->Name()); - EXPECT_EQ(1, parser.app_item()->num_packets()); - EXPECT_EQ(kDataLength, parser.app_item()->DataLength()); - EXPECT_EQ(0, strncmp(kData, (const char*)parser.app_item()->Data(), - parser.app_item()->DataLength())); -} TEST(RtcpPacketTest, BuildWithTooSmallBuffer) { ReportBlock rb; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc index f36c04eb08..d239d85d6c 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc @@ -29,6 +29,7 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc index 64331a5e52..4b0914d47d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc @@ -33,6 +33,7 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" @@ -483,8 +484,7 @@ rtc::scoped_ptr RTCPSender::BuildSR(const RtcpContext& ctx) { rtcp::SenderReport* report = new rtcp::SenderReport(); report->From(ssrc_); - report->WithNtpSec(ctx.ntp_sec_); - report->WithNtpFrac(ctx.ntp_frac_); + report->WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_)); report->WithRtpTimestamp(rtp_timestamp); report->WithPacketCount(ctx.feedback_state_.packets_sent); report->WithOctetCount(ctx.feedback_state_.media_bytes_sent); diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h index dd3aec4c9f..3cc8f4a14d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h @@ -25,6 +25,7 @@ #include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"