From 8443238e268dfb708fd1115ef485f7e17515f449 Mon Sep 17 00:00:00 2001 From: danilchap Date: Thu, 9 Feb 2017 05:21:42 -0800 Subject: [PATCH] Remove rtcp_utility as mostly unused. Since the only used class is RTCPUtilitiy::NackStats, rename it to RtcpNackStats and move it into dedicated file. BUG=webrtc:5565 Review-Url: https://codereview.webrtc.org/2680183004 Cr-Commit-Position: refs/heads/master@{#16515} --- webrtc/modules/rtp_rtcp/BUILD.gn | 6 +- webrtc/modules/rtp_rtcp/source/CPPLINT.cfg | 3 - .../rtp_rtcp/source/rtcp_nack_stats.cc | 31 + .../modules/rtp_rtcp/source/rtcp_nack_stats.h | 40 + .../source/rtcp_nack_stats_unittest.cc | 64 + .../modules/rtp_rtcp/source/rtcp_receiver.cc | 1 + .../modules/rtp_rtcp/source/rtcp_receiver.h | 4 +- webrtc/modules/rtp_rtcp/source/rtcp_sender.h | 4 +- .../modules/rtp_rtcp/source/rtcp_utility.cc | 1752 ----------------- webrtc/modules/rtp_rtcp/source/rtcp_utility.h | 490 ----- .../rtp_rtcp/source/rtcp_utility_unittest.cc | 160 -- 11 files changed, 143 insertions(+), 2412 deletions(-) delete mode 100644 webrtc/modules/rtp_rtcp/source/CPPLINT.cfg create mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.cc create mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h create mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_nack_stats_unittest.cc delete mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_utility.cc delete mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_utility.h delete mode 100644 webrtc/modules/rtp_rtcp/source/rtcp_utility_unittest.cc diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn index b7166ef459..da742c5480 100644 --- a/webrtc/modules/rtp_rtcp/BUILD.gn +++ b/webrtc/modules/rtp_rtcp/BUILD.gn @@ -40,6 +40,8 @@ rtc_static_library("rtp_rtcp") { "source/receive_statistics_impl.cc", "source/receive_statistics_impl.h", "source/remote_ntp_time_estimator.cc", + "source/rtcp_nack_stats.cc", + "source/rtcp_nack_stats.h", "source/rtcp_packet.cc", "source/rtcp_packet.h", "source/rtcp_packet/app.cc", @@ -100,8 +102,6 @@ rtc_static_library("rtp_rtcp") { "source/rtcp_receiver.h", "source/rtcp_sender.cc", "source/rtcp_sender.h", - "source/rtcp_utility.cc", - "source/rtcp_utility.h", "source/rtp_format.cc", "source/rtp_format.h", "source/rtp_format_h264.cc", @@ -242,6 +242,7 @@ if (rtc_include_tests) { "source/playout_delay_oracle_unittest.cc", "source/receive_statistics_unittest.cc", "source/remote_ntp_time_estimator_unittest.cc", + "source/rtcp_nack_stats_unittest.cc", "source/rtcp_packet/app_unittest.cc", "source/rtcp_packet/bye_unittest.cc", "source/rtcp_packet/common_header_unittest.cc", @@ -269,7 +270,6 @@ if (rtc_include_tests) { "source/rtcp_packet_unittest.cc", "source/rtcp_receiver_unittest.cc", "source/rtcp_sender_unittest.cc", - "source/rtcp_utility_unittest.cc", "source/rtp_fec_unittest.cc", "source/rtp_format_h264_unittest.cc", "source/rtp_format_vp8_test_helper.cc", diff --git a/webrtc/modules/rtp_rtcp/source/CPPLINT.cfg b/webrtc/modules/rtp_rtcp/source/CPPLINT.cfg deleted file mode 100644 index ec15757363..0000000000 --- a/webrtc/modules/rtp_rtcp/source/CPPLINT.cfg +++ /dev/null @@ -1,3 +0,0 @@ -#rtcp_utility planned to be removed when webrtc:5260 will be finished. -exclude_files=rtcp_utility.* - diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.cc b/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.cc new file mode 100644 index 0000000000..91fdc6e607 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.cc @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 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_nack_stats.h" + +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { + +RtcpNackStats::RtcpNackStats() + : max_sequence_number_(0), + requests_(0), + unique_requests_(0) {} + +void RtcpNackStats::ReportRequest(uint16_t sequence_number) { + if (requests_ == 0 || + IsNewerSequenceNumber(sequence_number, max_sequence_number_)) { + max_sequence_number_ = sequence_number; + ++unique_requests_; + } + ++requests_; +} + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h b/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h new file mode 100644 index 0000000000..72fad6c73f --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2017 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_NACK_STATS_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_NACK_STATS_H_ + +#include + +namespace webrtc { + +class RtcpNackStats { + public: + RtcpNackStats(); + + // Updates stats with requested sequence number. + // This function should be called for each NACK request to calculate the + // number of unique NACKed RTP packets. + void ReportRequest(uint16_t sequence_number); + + // Gets the number of NACKed RTP packets. + uint32_t requests() const { return requests_; } + + // Gets the number of unique NACKed RTP packets. + uint32_t unique_requests() const { return unique_requests_; } + + private: + uint16_t max_sequence_number_; + uint32_t requests_; + uint32_t unique_requests_; +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_NACK_STATS_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats_unittest.cc new file mode 100644 index 0000000000..6583f79b38 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats_unittest.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 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_nack_stats.h" +#include "webrtc/test/gtest.h" + +namespace webrtc { + +TEST(RtcpNackStatsTest, Requests) { + RtcpNackStats stats; + EXPECT_EQ(0U, stats.unique_requests()); + EXPECT_EQ(0U, stats.requests()); + stats.ReportRequest(10); + EXPECT_EQ(1U, stats.unique_requests()); + EXPECT_EQ(1U, stats.requests()); + + stats.ReportRequest(10); + EXPECT_EQ(1U, stats.unique_requests()); + stats.ReportRequest(11); + EXPECT_EQ(2U, stats.unique_requests()); + + stats.ReportRequest(11); + EXPECT_EQ(2U, stats.unique_requests()); + stats.ReportRequest(13); + EXPECT_EQ(3U, stats.unique_requests()); + + stats.ReportRequest(11); + EXPECT_EQ(3U, stats.unique_requests()); + EXPECT_EQ(6U, stats.requests()); +} + +TEST(RtcpNackStatsTest, RequestsWithWrap) { + RtcpNackStats stats; + stats.ReportRequest(65534); + EXPECT_EQ(1U, stats.unique_requests()); + + stats.ReportRequest(65534); + EXPECT_EQ(1U, stats.unique_requests()); + stats.ReportRequest(65535); + EXPECT_EQ(2U, stats.unique_requests()); + + stats.ReportRequest(65535); + EXPECT_EQ(2U, stats.unique_requests()); + stats.ReportRequest(0); + EXPECT_EQ(3U, stats.unique_requests()); + + stats.ReportRequest(65535); + EXPECT_EQ(3U, stats.unique_requests()); + stats.ReportRequest(0); + EXPECT_EQ(3U, stats.unique_requests()); + stats.ReportRequest(1); + EXPECT_EQ(4U, stats.unique_requests()); + EXPECT_EQ(8U, stats.requests()); +} + +} // namespace webrtc + diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc index 59049be01f..e8d2ff2913 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc @@ -40,6 +40,7 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/modules/rtp_rtcp/source/time_util.h" #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" #include "webrtc/system_wrappers/include/ntp_time.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h index 1e4d88bb22..b86b03060c 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h @@ -19,8 +19,8 @@ #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/system_wrappers/include/ntp_time.h" #include "webrtc/typedefs.h" @@ -260,7 +260,7 @@ class RTCPReceiver { RtcpPacketTypeCounterObserver* const packet_type_counter_observer_; RtcpPacketTypeCounter packet_type_counter_; - RTCPUtility::NackStats nack_stats_; + RtcpNackStats nack_stats_; size_t num_skipped_packets_; int64_t last_skipped_packets_warning_ms_; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h index 82b6adbd68..ccfbd48124 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h @@ -28,11 +28,11 @@ #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #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_nack_stats.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -259,7 +259,7 @@ class RTCPSender { RtcpPacketTypeCounter packet_type_counter_ GUARDED_BY(critical_section_rtcp_sender_); - RTCPUtility::NackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_); + RtcpNackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_); rtc::Optional video_bitrate_allocation_ GUARDED_BY(critical_section_rtcp_sender_); diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc deleted file mode 100644 index 2c26fa79db..0000000000 --- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc +++ /dev/null @@ -1,1752 +0,0 @@ -/* - * Copyright (c) 2012 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_utility.h" - -#include -#include // ceil -#include // memcpy - -#include - -#include "webrtc/base/checks.h" -#include "webrtc/base/logging.h" -#include "webrtc/modules/rtp_rtcp/source/byte_io.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" - -namespace webrtc { -namespace { -constexpr uint64_t kMaxBitrateBps = std::numeric_limits::max(); -} // namespace - -namespace RTCPUtility { - -NackStats::NackStats() - : max_sequence_number_(0), - requests_(0), - unique_requests_(0) {} - -NackStats::~NackStats() {} - -void NackStats::ReportRequest(uint16_t sequence_number) { - if (requests_ == 0 || - webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) { - max_sequence_number_ = sequence_number; - ++unique_requests_; - } - ++requests_; -} - -uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) { - return (ntp_sec << 16) + (ntp_frac >> 16); -} -} // namespace RTCPUtility - -// RTCPParserV2 : currently read only -RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData, - size_t rtcpDataLength, - bool rtcpReducedSizeEnable) - : _ptrRTCPDataBegin(rtcpData), - _RTCPReducedSizeEnable(rtcpReducedSizeEnable), - _ptrRTCPDataEnd(rtcpData + rtcpDataLength), - _validPacket(false), - _ptrRTCPData(rtcpData), - _ptrRTCPBlockEnd(NULL), - _state(ParseState::State_TopLevel), - _numberOfBlocks(0), - num_skipped_blocks_(0), - _packetType(RTCPPacketTypes::kInvalid) { - Validate(); -} - -RTCPUtility::RTCPParserV2::~RTCPParserV2() { -} - -ptrdiff_t -RTCPUtility::RTCPParserV2::LengthLeft() const -{ - return (_ptrRTCPDataEnd- _ptrRTCPData); -} - -RTCPUtility::RTCPPacketTypes -RTCPUtility::RTCPParserV2::PacketType() const -{ - return _packetType; -} - -const RTCPUtility::RTCPPacket& -RTCPUtility::RTCPParserV2::Packet() const -{ - return _packet; -} - -rtcp::RtcpPacket* RTCPUtility::RTCPParserV2::ReleaseRtcpPacket() { - return rtcp_packet_.release(); -} -RTCPUtility::RTCPPacketTypes -RTCPUtility::RTCPParserV2::Begin() -{ - _ptrRTCPData = _ptrRTCPDataBegin; - - return Iterate(); -} - -RTCPUtility::RTCPPacketTypes -RTCPUtility::RTCPParserV2::Iterate() -{ - // Reset packet type - _packetType = RTCPPacketTypes::kInvalid; - - if (IsValid()) - { - switch (_state) - { - case ParseState::State_TopLevel: - IterateTopLevel(); - break; - case ParseState::State_ReportBlockItem: - IterateReportBlockItem(); - break; - case ParseState::State_SDESChunk: - IterateSDESChunk(); - break; - case ParseState::State_BYEItem: - IterateBYEItem(); - break; - case ParseState::State_ExtendedJitterItem: - IterateExtendedJitterItem(); - break; - case ParseState::State_RTPFB_NACKItem: - IterateNACKItem(); - break; - case ParseState::State_RTPFB_TMMBRItem: - IterateTMMBRItem(); - break; - case ParseState::State_RTPFB_TMMBNItem: - IterateTMMBNItem(); - break; - case ParseState::State_PSFB_SLIItem: - IterateSLIItem(); - break; - case ParseState::State_PSFB_RPSIItem: - IterateRPSIItem(); - break; - case ParseState::State_PSFB_FIRItem: - IterateFIRItem(); - break; - case ParseState::State_PSFB_AppItem: - IteratePsfbAppItem(); - break; - case ParseState::State_PSFB_REMBItem: - IteratePsfbREMBItem(); - break; - case ParseState::State_XRItem: - IterateXrItem(); - break; - case ParseState::State_XR_DLLRItem: - IterateXrDlrrItem(); - break; - case ParseState::State_AppItem: - IterateAppItem(); - break; - default: - RTC_NOTREACHED() << "Invalid state!"; - break; - } - } - return _packetType; -} - -void -RTCPUtility::RTCPParserV2::IterateTopLevel() -{ - for (;;) - { - RtcpCommonHeader header; - if (_ptrRTCPDataEnd <= _ptrRTCPData) - return; - - if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData, - &header)) { - return; - } - _ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize(); - if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd) - { - ++num_skipped_blocks_; - return; - } - - switch (header.packet_type) { - case PT_SR: - { - // number of Report blocks - _numberOfBlocks = header.count_or_format; - ParseSR(); - return; - } - case PT_RR: - { - // number of Report blocks - _numberOfBlocks = header.count_or_format; - ParseRR(); - return; - } - case PT_SDES: - { - // number of SDES blocks - _numberOfBlocks = header.count_or_format; - const bool ok = ParseSDES(); - if (!ok) - { - // Nothing supported found, continue to next block! - break; - } - return; - } - case PT_BYE: - { - _numberOfBlocks = header.count_or_format; - const bool ok = ParseBYE(); - if (!ok) - { - // Nothing supported found, continue to next block! - break; - } - return; - } - case PT_IJ: - { - // number of Report blocks - _numberOfBlocks = header.count_or_format; - ParseIJ(); - return; - } - case PT_RTPFB: - FALLTHROUGH(); - case PT_PSFB: - { - if (!ParseFBCommon(header)) { - // Nothing supported found, continue to next block! - EndCurrentBlock(); - break; - } - return; - } - case PT_APP: - { - const bool ok = ParseAPP(header); - if (!ok) - { - // Nothing supported found, continue to next block! - break; - } - return; - } - case PT_XR: - { - const bool ok = ParseXr(); - if (!ok) - { - // Nothing supported found, continue to next block! - break; - } - return; - } - default: - // Not supported! Skip! - ++num_skipped_blocks_; - EndCurrentBlock(); - break; - } - } -} - -void -RTCPUtility::RTCPParserV2::IterateXrItem() -{ - const bool success = ParseXrItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateXrDlrrItem() -{ - const bool success = ParseXrDlrrItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateReportBlockItem() -{ - const bool success = ParseReportBlockItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateSDESChunk() -{ - const bool success = ParseSDESChunk(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateBYEItem() -{ - const bool success = ParseBYEItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateExtendedJitterItem() -{ - const bool success = ParseIJItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateNACKItem() -{ - const bool success = ParseNACKItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateTMMBRItem() -{ - const bool success = ParseTMMBRItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateTMMBNItem() -{ - const bool success = ParseTMMBNItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateSLIItem() -{ - const bool success = ParseSLIItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateRPSIItem() -{ - const bool success = ParseRPSIItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateFIRItem() -{ - const bool success = ParseFIRItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IteratePsfbAppItem() -{ - const bool success = ParsePsfbAppItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IteratePsfbREMBItem() -{ - const bool success = ParsePsfbREMBItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::IterateAppItem() -{ - const bool success = ParseAPPItem(); - if (!success) - { - Iterate(); - } -} - -void -RTCPUtility::RTCPParserV2::Validate() -{ - if (_ptrRTCPData == nullptr) - return; // NOT VALID - - RtcpCommonHeader header; - if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin) - return; // NOT VALID - - if (!RtcpParseCommonHeader(_ptrRTCPDataBegin, - _ptrRTCPDataEnd - _ptrRTCPDataBegin, &header)) - return; // NOT VALID! - - // * if (!reducedSize) : first packet must be RR or SR. - // - // * The padding bit (P) should be zero for the first packet of a - // compound RTCP packet because padding should only be applied, - // if it is needed, to the last packet. (NOT CHECKED!) - // - // * The length fields of the individual RTCP packets must add up - // to the overall length of the compound RTCP packet as - // received. This is a fairly strong check. (NOT CHECKED!) - - if (!_RTCPReducedSizeEnable) { - if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) - return; // NOT VALID - } - - _validPacket = true; -} - -bool -RTCPUtility::RTCPParserV2::IsValid() const -{ - return _validPacket; -} - -void -RTCPUtility::RTCPParserV2::EndCurrentBlock() -{ - _ptrRTCPData = _ptrRTCPBlockEnd; -} - -// 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| IC | PT | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// Common header for all RTCP packets, 4 octets. - -bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet, - size_t size_bytes, - RtcpCommonHeader* parsed_header) { - RTC_DCHECK(parsed_header != nullptr); - if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) { - LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte" - << (size_bytes != 1 ? "s" : "") - << ") remaining in buffer to parse RTCP header (4 bytes)."; - return false; - } - - const uint8_t kRtcpVersion = 2; - uint8_t version = packet[0] >> 6; - if (version != kRtcpVersion) { - LOG(LS_WARNING) << "Invalid RTCP header: Version must be " - << static_cast(kRtcpVersion) << " but was " - << static_cast(version); - return false; - } - - bool has_padding = (packet[0] & 0x20) != 0; - uint8_t format = packet[0] & 0x1F; - uint8_t packet_type = packet[1]; - size_t packet_size_words = - ByteReader::ReadBigEndian(&packet[2]) + 1; - - if (size_bytes < packet_size_words * 4) { - LOG(LS_WARNING) << "Buffer too small (" << size_bytes - << " bytes) to fit an RtcpPacket of " << packet_size_words - << " 32bit words."; - return false; - } - - size_t payload_size = packet_size_words * 4; - size_t padding_bytes = 0; - if (has_padding) { - if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) { - LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload " - "size specified."; - return false; - } - - padding_bytes = packet[payload_size - 1]; - if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) { - LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes (" - << padding_bytes << ") for a packet size of " - << payload_size << "bytes."; - return false; - } - payload_size -= padding_bytes; - } - payload_size -= RtcpCommonHeader::kHeaderSizeBytes; - - parsed_header->version = kRtcpVersion; - parsed_header->count_or_format = format; - parsed_header->packet_type = packet_type; - parsed_header->payload_size_bytes = payload_size; - parsed_header->padding_bytes = padding_bytes; - - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseRR() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 8) - { - return false; - } - - - _ptrRTCPData += 4; // Skip header - - _packetType = RTCPPacketTypes::kRr; - - _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24; - _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16; - _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8; - _packet.RR.SenderSSRC += *_ptrRTCPData++; - - _packet.RR.NumberOfReportBlocks = _numberOfBlocks; - - // State transition - _state = ParseState::State_ReportBlockItem; - - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseSR() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 28) - { - EndCurrentBlock(); - return false; - } - - _ptrRTCPData += 4; // Skip header - - _packetType = RTCPPacketTypes::kSr; - - _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24; - _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16; - _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8; - _packet.SR.SenderSSRC += *_ptrRTCPData++; - - _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24; - _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16; - _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8; - _packet.SR.NTPMostSignificant += *_ptrRTCPData++; - - _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24; - _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16; - _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8; - _packet.SR.NTPLeastSignificant += *_ptrRTCPData++; - - _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24; - _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16; - _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8; - _packet.SR.RTPTimestamp += *_ptrRTCPData++; - - _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24; - _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16; - _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8; - _packet.SR.SenderPacketCount += *_ptrRTCPData++; - - _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24; - _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16; - _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8; - _packet.SR.SenderOctetCount += *_ptrRTCPData++; - - _packet.SR.NumberOfReportBlocks = _numberOfBlocks; - - // State transition - if(_numberOfBlocks != 0) - { - _state = ParseState::State_ReportBlockItem; - }else - { - // don't go to state report block item if 0 report blocks - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - } - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseReportBlockItem() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 24 || _numberOfBlocks <= 0) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24; - _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16; - _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8; - _packet.ReportBlockItem.SSRC += *_ptrRTCPData++; - - _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++; - - _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16; - _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8; - _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++; - - _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24; - _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16; - _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8; - _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++; - - _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24; - _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16; - _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8; - _packet.ReportBlockItem.Jitter += *_ptrRTCPData++; - - _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24; - _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16; - _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8; - _packet.ReportBlockItem.LastSR += *_ptrRTCPData++; - - _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24; - _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16; - _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8; - _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++; - - _numberOfBlocks--; - _packetType = RTCPPacketTypes::kReportBlockItem; - return true; -} - -/* From RFC 5450: Transmission Time Offsets in RTP Streams. - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - hdr |V=2|P| RC | PT=IJ=195 | length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | inter-arrival jitter | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - . . - . . - . . - | inter-arrival jitter | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -bool -RTCPUtility::RTCPParserV2::ParseIJ() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4) - { - return false; - } - - _ptrRTCPData += 4; // Skip header - - _packetType = RTCPPacketTypes::kExtendedIj; - - // State transition - _state = ParseState::State_ExtendedJitterItem; - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseIJItem() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4 || _numberOfBlocks <= 0) - { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24; - _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16; - _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8; - _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++; - - _numberOfBlocks--; - _packetType = RTCPPacketTypes::kExtendedIjItem; - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseSDES() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 8) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _ptrRTCPData += 4; // Skip header - - _state = ParseState::State_SDESChunk; - _packetType = RTCPPacketTypes::kSdes; - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseSDESChunk() -{ - if(_numberOfBlocks <= 0) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _numberOfBlocks--; - - // Find CName item in a SDES chunk. - while (_ptrRTCPData < _ptrRTCPBlockEnd) - { - const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData; - if (dataLen < 4) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - uint32_t SSRC = *_ptrRTCPData++ << 24; - SSRC += *_ptrRTCPData++ << 16; - SSRC += *_ptrRTCPData++ << 8; - SSRC += *_ptrRTCPData++; - - const bool foundCname = ParseSDESItem(); - if (foundCname) - { - _packet.CName.SenderSSRC = SSRC; // Add SSRC - return true; - } - } - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; -} - -bool -RTCPUtility::RTCPParserV2::ParseSDESItem() -{ - // Find CName - // Only the CNAME item is mandatory. RFC 3550 page 46 - bool foundCName = false; - - size_t itemOctetsRead = 0; - while (_ptrRTCPData < _ptrRTCPBlockEnd) - { - const uint8_t tag = *_ptrRTCPData++; - ++itemOctetsRead; - - if (tag == 0) - { - // End tag! 4 oct aligned - while ((itemOctetsRead++ % 4) != 0) - { - ++_ptrRTCPData; - } - return foundCName; - } - - if (_ptrRTCPData < _ptrRTCPBlockEnd) - { - const uint8_t len = *_ptrRTCPData++; - ++itemOctetsRead; - - if (tag == 1) - { - // CNAME - - // Sanity - if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - uint8_t i = 0; - for (; i < len; ++i) - { - const uint8_t c = _ptrRTCPData[i]; - if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) - { - // Illegal char - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _packet.CName.CName[i] = c; - } - // Make sure we are null terminated. - _packet.CName.CName[i] = 0; - _packetType = RTCPPacketTypes::kSdesChunk; - - foundCName = true; - } - _ptrRTCPData += len; - itemOctetsRead += len; - } - } - - // No end tag found! - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; -} - -bool -RTCPUtility::RTCPParserV2::ParseBYE() -{ - _ptrRTCPData += 4; // Skip header - - _state = ParseState::State_BYEItem; - - return ParseBYEItem(); -} - -bool -RTCPUtility::RTCPParserV2::ParseBYEItem() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length < 4 || _numberOfBlocks == 0) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kBye; - - _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24; - _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16; - _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8; - _packet.BYE.SenderSSRC += *_ptrRTCPData++; - - // we can have several CSRCs attached - - // sanity - if(length >= 4*_numberOfBlocks) - { - _ptrRTCPData += (_numberOfBlocks -1)*4; - } - _numberOfBlocks = 0; - - return true; -} -/* - 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|reserved | PT=XR=207 | length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SSRC | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : report blocks : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ -bool RTCPUtility::RTCPParserV2::ParseXr() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length < 8) - { - EndCurrentBlock(); - return false; - } - - _ptrRTCPData += 4; // Skip header - - _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24; - _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16; - _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8; - _packet.XR.OriginatorSSRC += *_ptrRTCPData++; - - _packetType = RTCPPacketTypes::kXrHeader; - _state = ParseState::State_XRItem; - return true; -} - -/* Extended report block format (RFC 3611). - BT: block type. - block length: length of report block in 32-bits words minus one (including - the header). - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | BT | type-specific | block length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : type-specific block contents : - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ -bool RTCPUtility::RTCPParserV2::ParseXrItem() { - const int kBlockHeaderLengthInBytes = 4; - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length < kBlockHeaderLengthInBytes) { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - uint8_t block_type = *_ptrRTCPData++; - _ptrRTCPData++; // Ignore reserved. - - uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8; - block_length_in_4bytes += *_ptrRTCPData++; - - switch (block_type) { - case kBtReceiverReferenceTime: - return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes); - case kBtDlrr: - return ParseXrDlrr(block_length_in_4bytes); - case kBtVoipMetric: - return ParseXrVoipMetricItem(block_length_in_4bytes); - default: - return ParseXrUnsupportedBlockType(block_length_in_4bytes); - } -} - -/* Receiver Reference Time Report Block. - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | BT=4 | reserved | block length = 2 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | NTP timestamp, most significant word | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | NTP timestamp, least significant word | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ -bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem( - int block_length_4bytes) { - const int kBlockLengthIn4Bytes = 2; - const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4; - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (block_length_4bytes != kBlockLengthIn4Bytes || - length < kBlockLengthInBytes) { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24; - _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16; - _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8; - _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++; - - _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24; - _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16; - _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8; - _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++; - - _packetType = RTCPPacketTypes::kXrReceiverReferenceTime; - _state = ParseState::State_XRItem; - return true; -} - -/* DLRR Report Block. - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | BT=5 | reserved | block length | - +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - | SSRC_1 (SSRC of first receiver) | sub- - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block - | last RR (LRR) | 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | delay since last RR (DLRR) | - +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - | SSRC_2 (SSRC of second receiver) | sub- - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block - : ... : 2 - +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -*/ -bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) { - const int kSubBlockLengthIn4Bytes = 3; - if (block_length_4bytes < 0 || - (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - _packetType = RTCPPacketTypes::kXrDlrrReportBlock; - _state = ParseState::State_XR_DLLRItem; - _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes; - return true; -} - -bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() { - if (_numberOfBlocks == 0) { - _state = ParseState::State_XRItem; - return false; - } - const int kSubBlockLengthInBytes = 12; - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length < kSubBlockLengthInBytes) { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24; - _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16; - _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8; - _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++; - - _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24; - _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16; - _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8; - _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++; - - _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24; - _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16; - _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8; - _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++; - - _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem; - --_numberOfBlocks; - _state = ParseState::State_XR_DLLRItem; - return true; -} -/* VoIP Metrics Report Block. - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | BT=7 | reserved | block length = 8 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | SSRC of source | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | loss rate | discard rate | burst density | gap density | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | burst duration | gap duration | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | round trip delay | end system delay | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | signal level | noise level | RERL | Gmin | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | R factor | ext. R factor | MOS-LQ | MOS-CQ | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | RX config | reserved | JB nominal | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | JB maximum | JB abs max | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) { - const int kBlockLengthIn4Bytes = 8; - const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4; - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (block_length_4bytes != kBlockLengthIn4Bytes || - length < kBlockLengthInBytes) { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24; - _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16; - _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++; - _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++; - _ptrRTCPData++; // skip reserved - - _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++; - - _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8; - _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++; - - _packetType = RTCPPacketTypes::kXrVoipMetric; - _state = ParseState::State_XRItem; - return true; -} - -bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType( - int block_length_4bytes) { - const int32_t kBlockLengthInBytes = block_length_4bytes * 4; - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length < kBlockLengthInBytes) { - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - // Skip block. - _ptrRTCPData += kBlockLengthInBytes; - _state = ParseState::State_XRItem; - return false; -} - -bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) { - RTC_CHECK((header.packet_type == PT_RTPFB) || - (header.packet_type == PT_PSFB)); // Parser logic check - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - // 4 * 3, RFC4585 section 6.1 - if (length < 12) { - LOG(LS_WARNING) - << "Invalid RTCP packet: Too little data (" << length - << " bytes) left in buffer to parse a 12 byte RTPFB/PSFB message."; - return false; - } - - _ptrRTCPData += 4; // Skip RTCP header - - uint32_t senderSSRC = ByteReader::ReadBigEndian(_ptrRTCPData); - _ptrRTCPData += 4; - - uint32_t mediaSSRC = ByteReader::ReadBigEndian(_ptrRTCPData); - _ptrRTCPData += 4; - - if (header.packet_type == PT_RTPFB) { - // Transport layer feedback - - switch (header.count_or_format) { - case 1: - { - // NACK - _packetType = RTCPPacketTypes::kRtpfbNack; - _packet.NACK.SenderSSRC = senderSSRC; - _packet.NACK.MediaSSRC = mediaSSRC; - - _state = ParseState::State_RTPFB_NACKItem; - - return true; - } - case 3: - { - // TMMBR - _packetType = RTCPPacketTypes::kRtpfbTmmbr; - _packet.TMMBR.SenderSSRC = senderSSRC; - _packet.TMMBR.MediaSSRC = mediaSSRC; - - _state = ParseState::State_RTPFB_TMMBRItem; - - return true; - } - case 4: - { - // TMMBN - _packetType = RTCPPacketTypes::kRtpfbTmmbn; - _packet.TMMBN.SenderSSRC = senderSSRC; - _packet.TMMBN.MediaSSRC = mediaSSRC; - - _state = ParseState::State_RTPFB_TMMBNItem; - - return true; - } - case 5: - { - // RTCP-SR-REQ Rapid Synchronisation of RTP Flows - // draft-perkins-avt-rapid-rtp-sync-03.txt - // trigger a new RTCP SR - _packetType = RTCPPacketTypes::kRtpfbSrReq; - - // Note: No state transition, SR REQ is empty! - return true; - } - case 15: { - rtcp_packet_ = - rtcp::TransportFeedback::ParseFrom(_ptrRTCPData - 12, length); - // Since we parse the whole packet here, keep the TopLevel state and - // just end the current block. - EndCurrentBlock(); - if (rtcp_packet_.get()) { - _packetType = RTCPPacketTypes::kTransportFeedback; - return true; - } - break; - } - default: - break; - } - // Unsupported RTPFB message. Skip and move to next block. - ++num_skipped_blocks_; - return false; - } else if (header.packet_type == PT_PSFB) { - // Payload specific feedback - switch (header.count_or_format) { - case 1: - // PLI - _packetType = RTCPPacketTypes::kPsfbPli; - _packet.PLI.SenderSSRC = senderSSRC; - _packet.PLI.MediaSSRC = mediaSSRC; - - // Note: No state transition, PLI FCI is empty! - return true; - case 2: - // SLI - _packetType = RTCPPacketTypes::kPsfbSli; - _packet.SLI.SenderSSRC = senderSSRC; - _packet.SLI.MediaSSRC = mediaSSRC; - - _state = ParseState::State_PSFB_SLIItem; - - return true; - case 3: - _packetType = RTCPPacketTypes::kPsfbRpsi; - _packet.RPSI.SenderSSRC = senderSSRC; - _packet.RPSI.MediaSSRC = mediaSSRC; - - _state = ParseState::State_PSFB_RPSIItem; - return true; - case 4: - // FIR - _packetType = RTCPPacketTypes::kPsfbFir; - _packet.FIR.SenderSSRC = senderSSRC; - _packet.FIR.MediaSSRC = mediaSSRC; - - _state = ParseState::State_PSFB_FIRItem; - return true; - case 15: - _packetType = RTCPPacketTypes::kPsfbApp; - _packet.PSFBAPP.SenderSSRC = senderSSRC; - _packet.PSFBAPP.MediaSSRC = mediaSSRC; - - _state = ParseState::State_PSFB_AppItem; - return true; - default: - break; - } - - return false; - } - else - { - RTC_NOTREACHED(); - return false; - } -} - -bool RTCPUtility::RTCPParserV2::ParseRPSIItem() { - - // RFC 4585 6.3.3. Reference Picture Selection Indication (RPSI). - // - // 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 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | PB |0| Payload Type| Native RPSI bit string | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | defined per codec ... | Padding (0) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4) { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - if (length > 2 + RTCP_RPSI_DATA_SIZE) { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - - uint8_t padding_bits = *_ptrRTCPData++; - _packet.RPSI.PayloadType = *_ptrRTCPData++; - - if (padding_bits > static_cast(length - 2) * 8) { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kPsfbRpsiItem; - - memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2); - _ptrRTCPData += length - 2; - - _packet.RPSI.NumberOfValidBits = - static_cast(length - 2) * 8 - padding_bits; - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseNACKItem() -{ - // RFC 4585 6.2.1. Generic NACK - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kRtpfbNackItem; - - _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8; - _packet.NACKItem.PacketID += *_ptrRTCPData++; - - _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8; - _packet.NACKItem.BitMask += *_ptrRTCPData++; - - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParsePsfbAppItem() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - if(*_ptrRTCPData++ != 'R') - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - if(*_ptrRTCPData++ != 'E') - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - if(*_ptrRTCPData++ != 'M') - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - if(*_ptrRTCPData++ != 'B') - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _packetType = RTCPPacketTypes::kPsfbRemb; - _state = ParseState::State_PSFB_REMBItem; - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParsePsfbREMBItem() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++; - const uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F; - - uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 16; - mantissa += (_ptrRTCPData[1] << 8); - mantissa += (_ptrRTCPData[2]); - - _ptrRTCPData += 3; // Fwd read data - uint64_t bitrate_bps = (mantissa << exp); - bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0; - if (shift_overflow || bitrate_bps > kMaxBitrateBps) { - LOG(LS_ERROR) << "Unhandled remb bitrate value : " << mantissa - << "*2^" << static_cast(exp); - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - _packet.REMBItem.BitRate = bitrate_bps; - - const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kPsfbRembItem; - - for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++) - { - _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24; - _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16; - _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8; - _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++; - } - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseTMMBRItem() -{ - // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR) - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 8) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kRtpfbTmmbrItem; - - _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24; - _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16; - _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8; - _packet.TMMBRItem.SSRC += *_ptrRTCPData++; - - uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F; - - uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 15; - mantissa += (_ptrRTCPData[1] << 7); - mantissa += (_ptrRTCPData[2] >> 1) & 0x7F; - - uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8; - measuredOH += _ptrRTCPData[3]; - - _ptrRTCPData += 4; // Fwd read data - - uint64_t bitrate_bps = (mantissa << exp); - bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0; - if (shift_overflow || bitrate_bps > kMaxBitrateBps) { - LOG(LS_ERROR) << "Unhandled tmmbr bitrate value : " << mantissa - << "*2^" << static_cast(exp); - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - _packet.TMMBRItem.MaxTotalMediaBitRate = bitrate_bps / 1000; - _packet.TMMBRItem.MeasuredOverhead = measuredOH; - - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseTMMBNItem() -{ - // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN) - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 8) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kRtpfbTmmbnItem; - - _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24; - _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16; - _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8; - _packet.TMMBNItem.SSRC += *_ptrRTCPData++; - - uint8_t exp = (_ptrRTCPData[0] >> 2) & 0x3F; - - uint64_t mantissa = (_ptrRTCPData[0] & 0x03) << 15; - mantissa += (_ptrRTCPData[1] << 7); - mantissa += (_ptrRTCPData[2] >> 1) & 0x7F; - - uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8; - measuredOH += _ptrRTCPData[3]; - - _ptrRTCPData += 4; // Fwd read data - - uint64_t bitrate_bps = (mantissa << exp); - bool shift_overflow = exp > 0 && (mantissa >> (64 - exp)) != 0; - if (shift_overflow || bitrate_bps > kMaxBitrateBps) { - LOG(LS_ERROR) << "Unhandled tmmbn bitrate value : " << mantissa - << "*2^" << static_cast(exp); - _state = ParseState::State_TopLevel; - EndCurrentBlock(); - return false; - } - - _packet.TMMBNItem.MaxTotalMediaBitRate = bitrate_bps / 1000; - _packet.TMMBNItem.MeasuredOverhead = measuredOH; - - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseSLIItem() -{ - // RFC 5104 6.3.2. Slice Loss Indication (SLI) - /* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | First | Number | PictureID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 4) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _packetType = RTCPPacketTypes::kPsfbSliItem; - - uint32_t buffer; - buffer = *_ptrRTCPData++ << 24; - buffer += *_ptrRTCPData++ << 16; - buffer += *_ptrRTCPData++ << 8; - buffer += *_ptrRTCPData++; - - _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff); - _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff); - _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f); - - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseFIRItem() -{ - // RFC 5104 4.3.1. Full Intra Request (FIR) - - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 8) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - - _packetType = RTCPPacketTypes::kPsfbFirItem; - - _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24; - _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16; - _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8; - _packet.FIRItem.SSRC += *_ptrRTCPData++; - - _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++; - _ptrRTCPData += 3; // Skip "Reserved" bytes. - return true; -} - -bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) { - ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - - if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet - { - EndCurrentBlock(); - return false; - } - - _ptrRTCPData += 4; // Skip RTCP header - - uint32_t senderSSRC = *_ptrRTCPData++ << 24; - senderSSRC += *_ptrRTCPData++ << 16; - senderSSRC += *_ptrRTCPData++ << 8; - senderSSRC += *_ptrRTCPData++; - - uint32_t name = *_ptrRTCPData++ << 24; - name += *_ptrRTCPData++ << 16; - name += *_ptrRTCPData++ << 8; - name += *_ptrRTCPData++; - - length = _ptrRTCPBlockEnd - _ptrRTCPData; - - _packetType = RTCPPacketTypes::kApp; - - _packet.APP.SubType = header.count_or_format; - _packet.APP.Name = name; - - _state = ParseState::State_AppItem; - return true; -} - -bool -RTCPUtility::RTCPParserV2::ParseAPPItem() -{ - const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData; - if (length < 4) - { - _state = ParseState::State_TopLevel; - - EndCurrentBlock(); - return false; - } - _packetType = RTCPPacketTypes::kAppItem; - - if(length > kRtcpAppCode_DATA_SIZE) - { - memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE); - _packet.APP.Size = kRtcpAppCode_DATA_SIZE; - _ptrRTCPData += kRtcpAppCode_DATA_SIZE; - }else - { - memcpy(_packet.APP.Data, _ptrRTCPData, length); - _packet.APP.Size = (uint16_t)length; - _ptrRTCPData += length; - } - return true; -} - -size_t RTCPUtility::RTCPParserV2::NumSkippedBlocks() const { - return num_skipped_blocks_; -} - -RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData, - size_t rtcpDataLength) - : _ptrBegin(rtcpData), - _ptrEnd(rtcpData + rtcpDataLength), - _ptrBlock(NULL) { - memset(&_header, 0, sizeof(_header)); -} - -RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() { -} - -const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() { - _ptrBlock = _ptrBegin; - - return Iterate(); -} - -const RTCPUtility::RtcpCommonHeader* -RTCPUtility::RTCPPacketIterator::Iterate() { - if ((_ptrEnd <= _ptrBlock) || - !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) { - _ptrBlock = nullptr; - return nullptr; - } - _ptrBlock += _header.BlockSize(); - - if (_ptrBlock > _ptrEnd) { - _ptrBlock = nullptr; - return nullptr; - } - - return &_header; -} - -const RTCPUtility::RtcpCommonHeader* -RTCPUtility::RTCPPacketIterator::Current() { - if (!_ptrBlock) - { - return NULL; - } - - return &_header; -} -} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.h b/webrtc/modules/rtp_rtcp/source/rtcp_utility.h deleted file mode 100644 index 86fee8ea68..0000000000 --- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.h +++ /dev/null @@ -1,490 +0,0 @@ -/* -* Copyright (c) 2012 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_UTILITY_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_UTILITY_H_ - -#include // size_t, ptrdiff_t - -#include - -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -namespace rtcp { -class RtcpPacket; -} -namespace RTCPUtility { - -class NackStats { - public: - NackStats(); - ~NackStats(); - - // Updates stats with requested sequence number. - // This function should be called for each NACK request to calculate the - // number of unique NACKed RTP packets. - void ReportRequest(uint16_t sequence_number); - - // Gets the number of NACKed RTP packets. - uint32_t requests() const { return requests_; } - - // Gets the number of unique NACKed RTP packets. - uint32_t unique_requests() const { return unique_requests_; } - - private: - uint16_t max_sequence_number_; - uint32_t requests_; - uint32_t unique_requests_; -}; - -uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac); - -struct RTCPPacketRR { - uint32_t SenderSSRC; - uint8_t NumberOfReportBlocks; -}; -struct RTCPPacketSR { - uint32_t SenderSSRC; - uint8_t NumberOfReportBlocks; - - // sender info - uint32_t NTPMostSignificant; - uint32_t NTPLeastSignificant; - uint32_t RTPTimestamp; - uint32_t SenderPacketCount; - uint32_t SenderOctetCount; -}; -struct RTCPPacketReportBlockItem { - // report block - uint32_t SSRC; - uint8_t FractionLost; - uint32_t CumulativeNumOfPacketsLost; - uint32_t ExtendedHighestSequenceNumber; - uint32_t Jitter; - uint32_t LastSR; - uint32_t DelayLastSR; -}; -struct RTCPPacketSDESCName { - // RFC3550 - uint32_t SenderSSRC; - char CName[RTCP_CNAME_SIZE]; -}; - -struct RTCPPacketExtendedJitterReportItem { - // RFC 5450 - uint32_t Jitter; -}; - -struct RTCPPacketBYE { - uint32_t SenderSSRC; -}; -struct RTCPPacketXR { - // RFC 3611 - uint32_t OriginatorSSRC; -}; -struct RTCPPacketXRReceiverReferenceTimeItem { - // RFC 3611 4.4 - uint32_t NTPMostSignificant; - uint32_t NTPLeastSignificant; -}; -struct RTCPPacketXRDLRRReportBlockItem { - // RFC 3611 4.5 - uint32_t SSRC; - uint32_t LastRR; - uint32_t DelayLastRR; -}; -struct RTCPPacketXRVOIPMetricItem { - // RFC 3611 4.7 - uint32_t SSRC; - uint8_t lossRate; - uint8_t discardRate; - uint8_t burstDensity; - uint8_t gapDensity; - uint16_t burstDuration; - uint16_t gapDuration; - uint16_t roundTripDelay; - uint16_t endSystemDelay; - uint8_t signalLevel; - uint8_t noiseLevel; - uint8_t RERL; - uint8_t Gmin; - uint8_t Rfactor; - uint8_t extRfactor; - uint8_t MOSLQ; - uint8_t MOSCQ; - uint8_t RXconfig; - uint16_t JBnominal; - uint16_t JBmax; - uint16_t JBabsMax; -}; - -struct RTCPPacketRTPFBNACK { - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; -struct RTCPPacketRTPFBNACKItem { - // RFC4585 - uint16_t PacketID; - uint16_t BitMask; -}; - -struct RTCPPacketRTPFBTMMBR { - uint32_t SenderSSRC; - uint32_t MediaSSRC; // zero! -}; -struct RTCPPacketRTPFBTMMBRItem { - // RFC5104 - uint32_t SSRC; - uint32_t MaxTotalMediaBitRate; // In Kbit/s - uint32_t MeasuredOverhead; -}; - -struct RTCPPacketRTPFBTMMBN { - uint32_t SenderSSRC; - uint32_t MediaSSRC; // zero! -}; -struct RTCPPacketRTPFBTMMBNItem { - // RFC5104 - uint32_t SSRC; // "Owner" - uint32_t MaxTotalMediaBitRate; - uint32_t MeasuredOverhead; -}; - -struct RTCPPacketPSFBFIR { - uint32_t SenderSSRC; - uint32_t MediaSSRC; // zero! -}; -struct RTCPPacketPSFBFIRItem { - // RFC5104 - uint32_t SSRC; - uint8_t CommandSequenceNumber; -}; - -struct RTCPPacketPSFBPLI { - // RFC4585 - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; - -struct RTCPPacketPSFBSLI { - // RFC4585 - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; -struct RTCPPacketPSFBSLIItem { - // RFC4585 - uint16_t FirstMB; - uint16_t NumberOfMB; - uint8_t PictureId; -}; -struct RTCPPacketPSFBRPSI { - // RFC4585 - uint32_t SenderSSRC; - uint32_t MediaSSRC; - uint8_t PayloadType; - uint16_t NumberOfValidBits; - uint8_t NativeBitString[RTCP_RPSI_DATA_SIZE]; -}; -struct RTCPPacketPSFBAPP { - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; -struct RTCPPacketPSFBREMBItem { - uint32_t BitRate; - uint8_t NumberOfSSRCs; - uint32_t SSRCs[MAX_NUMBER_OF_REMB_FEEDBACK_SSRCS]; -}; -// generic name APP -struct RTCPPacketAPP { - uint8_t SubType; - uint32_t Name; - uint8_t Data[kRtcpAppCode_DATA_SIZE]; - uint16_t Size; -}; - -union RTCPPacket { - RTCPPacketRR RR; - RTCPPacketSR SR; - RTCPPacketReportBlockItem ReportBlockItem; - - RTCPPacketSDESCName CName; - RTCPPacketBYE BYE; - - RTCPPacketExtendedJitterReportItem ExtendedJitterReportItem; - - RTCPPacketRTPFBNACK NACK; - RTCPPacketRTPFBNACKItem NACKItem; - - RTCPPacketPSFBPLI PLI; - RTCPPacketPSFBSLI SLI; - RTCPPacketPSFBSLIItem SLIItem; - RTCPPacketPSFBRPSI RPSI; - RTCPPacketPSFBAPP PSFBAPP; - RTCPPacketPSFBREMBItem REMBItem; - - RTCPPacketRTPFBTMMBR TMMBR; - RTCPPacketRTPFBTMMBRItem TMMBRItem; - RTCPPacketRTPFBTMMBN TMMBN; - RTCPPacketRTPFBTMMBNItem TMMBNItem; - RTCPPacketPSFBFIR FIR; - RTCPPacketPSFBFIRItem FIRItem; - - RTCPPacketXR XR; - RTCPPacketXRReceiverReferenceTimeItem XRReceiverReferenceTimeItem; - RTCPPacketXRDLRRReportBlockItem XRDLRRReportBlockItem; - RTCPPacketXRVOIPMetricItem XRVOIPMetricItem; - - RTCPPacketAPP APP; -}; - -enum class RTCPPacketTypes { - kInvalid, - - // RFC3550 - kRr, - kSr, - kReportBlockItem, - - kSdes, - kSdesChunk, - kBye, - - // RFC5450 - kExtendedIj, - kExtendedIjItem, - - // RFC4585 - kRtpfbNack, - kRtpfbNackItem, - - kPsfbPli, - kPsfbRpsi, - kPsfbRpsiItem, - kPsfbSli, - kPsfbSliItem, - kPsfbApp, - kPsfbRemb, - kPsfbRembItem, - - // RFC5104 - kRtpfbTmmbr, - kRtpfbTmmbrItem, - kRtpfbTmmbn, - kRtpfbTmmbnItem, - kPsfbFir, - kPsfbFirItem, - - // draft-perkins-avt-rapid-rtp-sync - kRtpfbSrReq, - - // RFC 3611 - kXrHeader, - kXrReceiverReferenceTime, - kXrDlrrReportBlock, - kXrDlrrReportBlockItem, - kXrVoipMetric, - - kApp, - kAppItem, - - // draft-holmer-rmcat-transport-wide-cc-extensions - kTransportFeedback, -}; - -struct RTCPRawPacket { - const uint8_t* _ptrPacketBegin; - const uint8_t* _ptrPacketEnd; -}; - -struct RTCPModRawPacket { - uint8_t* _ptrPacketBegin; - uint8_t* _ptrPacketEnd; -}; - -struct RtcpCommonHeader { - static const uint8_t kHeaderSizeBytes = 4; - RtcpCommonHeader() - : version(2), - count_or_format(0), - packet_type(0), - payload_size_bytes(0), - padding_bytes(0) {} - - uint32_t BlockSize() const { - return kHeaderSizeBytes + payload_size_bytes + padding_bytes; - } - - uint8_t version; - uint8_t count_or_format; - uint8_t packet_type; - uint32_t payload_size_bytes; - uint8_t padding_bytes; -}; - -enum RTCPPT : uint8_t { - PT_IJ = 195, - PT_SR = 200, - PT_RR = 201, - PT_SDES = 202, - PT_BYE = 203, - PT_APP = 204, - PT_RTPFB = 205, - PT_PSFB = 206, - PT_XR = 207 -}; - -// Extended report blocks, RFC 3611. -enum RtcpXrBlockType : uint8_t { - kBtReceiverReferenceTime = 4, - kBtDlrr = 5, - kBtVoipMetric = 7 -}; - -bool RtcpParseCommonHeader(const uint8_t* buffer, - size_t size_bytes, - RtcpCommonHeader* parsed_header); - -class RTCPParserV2 { - public: - RTCPParserV2( - const uint8_t* rtcpData, - size_t rtcpDataLength, - bool rtcpReducedSizeEnable); // Set to true, to allow non-compound RTCP! - ~RTCPParserV2(); - - RTCPPacketTypes PacketType() const; - const RTCPPacket& Packet() const; - rtcp::RtcpPacket* ReleaseRtcpPacket(); - const RTCPRawPacket& RawPacket() const; - ptrdiff_t LengthLeft() const; - - bool IsValid() const; - size_t NumSkippedBlocks() const; - - RTCPPacketTypes Begin(); - RTCPPacketTypes Iterate(); - - private: - enum class ParseState { - State_TopLevel, // Top level packet - State_ReportBlockItem, // SR/RR report block - State_SDESChunk, // SDES chunk - State_BYEItem, // BYE item - State_ExtendedJitterItem, // Extended jitter report item - State_RTPFB_NACKItem, // NACK FCI item - State_RTPFB_TMMBRItem, // TMMBR FCI item - State_RTPFB_TMMBNItem, // TMMBN FCI item - State_PSFB_SLIItem, // SLI FCI item - State_PSFB_RPSIItem, // RPSI FCI item - State_PSFB_FIRItem, // FIR FCI item - State_PSFB_AppItem, // Application specific FCI item - State_PSFB_REMBItem, // Application specific REMB item - State_XRItem, - State_XR_DLLRItem, - State_AppItem - }; - - private: - void IterateTopLevel(); - void IterateReportBlockItem(); - void IterateSDESChunk(); - void IterateBYEItem(); - void IterateExtendedJitterItem(); - void IterateNACKItem(); - void IterateTMMBRItem(); - void IterateTMMBNItem(); - void IterateSLIItem(); - void IterateRPSIItem(); - void IterateFIRItem(); - void IteratePsfbAppItem(); - void IteratePsfbREMBItem(); - void IterateAppItem(); - void IterateXrItem(); - void IterateXrDlrrItem(); - - void Validate(); - void EndCurrentBlock(); - - bool ParseRR(); - bool ParseSR(); - bool ParseReportBlockItem(); - - bool ParseSDES(); - bool ParseSDESChunk(); - bool ParseSDESItem(); - - bool ParseBYE(); - bool ParseBYEItem(); - - bool ParseIJ(); - bool ParseIJItem(); - - bool ParseXr(); - bool ParseXrItem(); - bool ParseXrReceiverReferenceTimeItem(int block_length_4bytes); - bool ParseXrDlrr(int block_length_4bytes); - bool ParseXrDlrrItem(); - bool ParseXrVoipMetricItem(int block_length_4bytes); - bool ParseXrUnsupportedBlockType(int block_length_4bytes); - - bool ParseFBCommon(const RtcpCommonHeader& header); - bool ParseNACKItem(); - bool ParseTMMBRItem(); - bool ParseTMMBNItem(); - bool ParseSLIItem(); - bool ParseRPSIItem(); - bool ParseFIRItem(); - bool ParsePsfbAppItem(); - bool ParsePsfbREMBItem(); - - bool ParseAPP(const RtcpCommonHeader& header); - bool ParseAPPItem(); - - private: - const uint8_t* const _ptrRTCPDataBegin; - const bool _RTCPReducedSizeEnable; - const uint8_t* const _ptrRTCPDataEnd; - - bool _validPacket; - const uint8_t* _ptrRTCPData; - const uint8_t* _ptrRTCPBlockEnd; - - ParseState _state; - uint8_t _numberOfBlocks; - size_t num_skipped_blocks_; - - RTCPPacketTypes _packetType; - RTCPPacket _packet; - std::unique_ptr rtcp_packet_; -}; - -class RTCPPacketIterator { - public: - RTCPPacketIterator(uint8_t* rtcpData, size_t rtcpDataLength); - ~RTCPPacketIterator(); - - const RtcpCommonHeader* Begin(); - const RtcpCommonHeader* Iterate(); - const RtcpCommonHeader* Current(); - - private: - uint8_t* const _ptrBegin; - uint8_t* const _ptrEnd; - - uint8_t* _ptrBlock; - - RtcpCommonHeader _header; -}; -} // namespace RTCPUtility -} // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_UTILITY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_utility_unittest.cc deleted file mode 100644 index b433107098..0000000000 --- a/webrtc/modules/rtp_rtcp/source/rtcp_utility_unittest.cc +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2014 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/base/checks.h" -#include "webrtc/modules/rtp_rtcp/source/byte_io.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" -#include "webrtc/test/gtest.h" - -namespace webrtc { - -using RTCPUtility::RtcpCommonHeader; - -namespace rtcp { - -TEST(RtcpUtilityTest, MidNtp) { - const uint32_t kNtpSec = 0x12345678; - const uint32_t kNtpFrac = 0x23456789; - const uint32_t kNtpMid = 0x56782345; - EXPECT_EQ(kNtpMid, RTCPUtility::MidNtp(kNtpSec, kNtpFrac)); -} - -TEST(RtcpUtilityTest, NackRequests) { - RTCPUtility::NackStats stats; - EXPECT_EQ(0U, stats.unique_requests()); - EXPECT_EQ(0U, stats.requests()); - stats.ReportRequest(10); - EXPECT_EQ(1U, stats.unique_requests()); - EXPECT_EQ(1U, stats.requests()); - - stats.ReportRequest(10); - EXPECT_EQ(1U, stats.unique_requests()); - stats.ReportRequest(11); - EXPECT_EQ(2U, stats.unique_requests()); - - stats.ReportRequest(11); - EXPECT_EQ(2U, stats.unique_requests()); - stats.ReportRequest(13); - EXPECT_EQ(3U, stats.unique_requests()); - - stats.ReportRequest(11); - EXPECT_EQ(3U, stats.unique_requests()); - EXPECT_EQ(6U, stats.requests()); -} - -TEST(RtcpUtilityTest, NackRequestsWithWrap) { - RTCPUtility::NackStats stats; - stats.ReportRequest(65534); - EXPECT_EQ(1U, stats.unique_requests()); - - stats.ReportRequest(65534); - EXPECT_EQ(1U, stats.unique_requests()); - stats.ReportRequest(65535); - EXPECT_EQ(2U, stats.unique_requests()); - - stats.ReportRequest(65535); - EXPECT_EQ(2U, stats.unique_requests()); - stats.ReportRequest(0); - EXPECT_EQ(3U, stats.unique_requests()); - - stats.ReportRequest(65535); - EXPECT_EQ(3U, stats.unique_requests()); - stats.ReportRequest(0); - EXPECT_EQ(3U, stats.unique_requests()); - stats.ReportRequest(1); - EXPECT_EQ(4U, stats.unique_requests()); - EXPECT_EQ(8U, stats.requests()); -} - -class RtcpParseCommonHeaderTest : public ::testing::Test { - public: - RtcpParseCommonHeaderTest() { memset(buffer, 0, kBufferCapacityBytes); } - virtual ~RtcpParseCommonHeaderTest() {} - - protected: - static const size_t kBufferCapacityBytes = 40; - uint8_t buffer[kBufferCapacityBytes]; - RtcpCommonHeader header; -}; - -TEST_F(RtcpParseCommonHeaderTest, TooSmallBuffer) { - // Buffer needs to be able to hold the header. - for (size_t i = 0; i < RtcpCommonHeader::kHeaderSizeBytes; ++i) - EXPECT_FALSE(RtcpParseCommonHeader(buffer, i, &header)); -} - -TEST_F(RtcpParseCommonHeaderTest, Version) { - // Version 2 is the only allowed for now. - for (int v = 0; v < 4; ++v) { - buffer[0] = v << 6; - EXPECT_EQ(v == 2, RtcpParseCommonHeader( - buffer, RtcpCommonHeader::kHeaderSizeBytes, &header)); - } -} - -TEST_F(RtcpParseCommonHeaderTest, PacketSize) { - // Set v = 2, leave p, fmt, pt as 0. - buffer[0] = 2 << 6; - - const size_t kBlockSize = 3; - ByteWriter::WriteBigEndian(&buffer[2], kBlockSize); - const size_t kSizeInBytes = (kBlockSize + 1) * 4; - - EXPECT_FALSE(RtcpParseCommonHeader(buffer, kSizeInBytes - 1, &header)); - EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); -} - -TEST_F(RtcpParseCommonHeaderTest, PayloadSize) { - // Set v = 2, p = 1, but leave fmt, pt as 0. - buffer[0] = (2 << 6) | (1 << 5); - - // Padding bit set, but no byte for padding (can't specify padding length). - EXPECT_FALSE(RtcpParseCommonHeader(buffer, 4, &header)); - - const size_t kBlockSize = 3; - ByteWriter::WriteBigEndian(&buffer[2], kBlockSize); - const size_t kSizeInBytes = (kBlockSize + 1) * 4; - const size_t kPayloadSizeBytes = - kSizeInBytes - RtcpCommonHeader::kHeaderSizeBytes; - - // Padding one byte larger than possible. - buffer[kSizeInBytes - 1] = kPayloadSizeBytes + 1; - EXPECT_FALSE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); - - // Pure padding packet? - buffer[kSizeInBytes - 1] = kPayloadSizeBytes; - EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); - EXPECT_EQ(kPayloadSizeBytes, header.padding_bytes); - EXPECT_EQ(0u, header.payload_size_bytes); - - // Single byte of actual data. - buffer[kSizeInBytes - 1] = kPayloadSizeBytes - 1; - EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); - EXPECT_EQ(kPayloadSizeBytes - 1, header.padding_bytes); - EXPECT_EQ(1u, header.payload_size_bytes); -} - -TEST_F(RtcpParseCommonHeaderTest, FormatAndPayloadType) { - // Format/count and packet type both set to max values. - const uint8_t kCountOrFormat = 0x1F; - const uint8_t kPacketType = 0xFF; - buffer[0] = 2 << 6; // V = 2. - buffer[0] |= kCountOrFormat; - buffer[1] = kPacketType; - - EXPECT_TRUE(RtcpParseCommonHeader(buffer, RtcpCommonHeader::kHeaderSizeBytes, - &header)); - EXPECT_EQ(kCountOrFormat, header.count_or_format); - EXPECT_EQ(kPacketType, header.packet_type); -} - -} // namespace rtcp -} // namespace webrtc -