aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules
diff options
context:
space:
mode:
authordanilchap <danilchap@webrtc.org>2015-12-16 01:56:20 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-16 09:56:22 +0000
commit54999d411b97e3df54121e5f7bfb28846f3c8086 (patch)
tree95b31e98f7610d2c21485043207b7dd1043070b7 /webrtc/modules
parent29e2f9385b7e0dde4af7317af5cd0ce6adf1ee9d (diff)
downloadwebrtc-54999d411b97e3df54121e5f7bfb28846f3c8086.tar.gz
rtcp::Dlrr block moved into own file and got Parse function
BUG=webrtc:5260 Review URL: https://codereview.webrtc.org/1453973005 Cr-Commit-Position: refs/heads/master@{#11044}
Diffstat (limited to 'webrtc/modules')
-rw-r--r--webrtc/modules/modules.gyp1
-rw-r--r--webrtc/modules/rtp_rtcp/BUILD.gn2
-rw-r--r--webrtc/modules/rtp_rtcp/rtp_rtcp.gypi2
-rw-r--r--webrtc/modules/rtp_rtcp/source/rtcp_packet.cc77
-rw-r--r--webrtc/modules/rtp_rtcp/source/rtcp_packet.h38
-rw-r--r--webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc100
-rw-r--r--webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h63
-rw-r--r--webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc102
8 files changed, 280 insertions, 105 deletions
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index f58e0f4034..0dec33749d 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -306,6 +306,7 @@
'rtp_rtcp/source/rtcp_packet_unittest.cc',
'rtp_rtcp/source/rtcp_packet/app_unittest.cc',
'rtp_rtcp/source/rtcp_packet/bye_unittest.cc',
+ 'rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc',
'rtp_rtcp/source/rtcp_packet/extended_jitter_report_unittest.cc',
'rtp_rtcp/source/rtcp_packet/pli_unittest.cc',
'rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc',
diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn
index be6e2e4c7d..aa2e9c5800 100644
--- a/webrtc/modules/rtp_rtcp/BUILD.gn
+++ b/webrtc/modules/rtp_rtcp/BUILD.gn
@@ -50,6 +50,8 @@ source_set("rtp_rtcp") {
"source/rtcp_packet/app.h",
"source/rtcp_packet/bye.cc",
"source/rtcp_packet/bye.h",
+ "source/rtcp_packet/dlrr.cc",
+ "source/rtcp_packet/dlrr.h",
"source/rtcp_packet/extended_jitter_report.cc",
"source/rtcp_packet/extended_jitter_report.h",
"source/rtcp_packet/pli.cc",
diff --git a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi
index 1b88055695..98b2659c94 100644
--- a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi
+++ b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi
@@ -45,6 +45,8 @@
'source/rtcp_packet/app.h',
'source/rtcp_packet/bye.cc',
'source/rtcp_packet/bye.h',
+ 'source/rtcp_packet/dlrr.cc',
+ 'source/rtcp_packet/dlrr.h',
'source/rtcp_packet/extended_jitter_report.cc',
'source/rtcp_packet/extended_jitter_report.h',
'source/rtcp_packet/pli.cc',
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
index 28cb20eca2..1508658f5d 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
@@ -407,50 +407,6 @@ void CreateXrHeader(const RTCPPacketXR& header,
AssignUWord32(buffer, pos, header.OriginatorSSRC);
}
-void CreateXrBlockHeader(uint8_t block_type,
- uint16_t block_length,
- uint8_t* buffer,
- size_t* pos) {
- AssignUWord8(buffer, pos, block_type);
- AssignUWord8(buffer, pos, 0);
- AssignUWord16(buffer, pos, block_length);
-}
-
-// DLRR Report Block (RFC 3611).
-//
-// 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
-
-void CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs,
- uint8_t* buffer,
- size_t* pos) {
- for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin();
- it != dlrrs.end(); ++it) {
- if ((*it).empty()) {
- continue;
- }
- uint16_t block_length = 3 * (*it).size();
- CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos);
- for (Xr::DlrrBlock::const_iterator it_block = (*it).begin();
- it_block != (*it).end(); ++it_block) {
- AssignUWord32(buffer, pos, (*it_block).SSRC);
- AssignUWord32(buffer, pos, (*it_block).LastRR);
- AssignUWord32(buffer, pos, (*it_block).DelayLastRR);
- }
- }
-}
} // namespace
void RtcpPacket::Append(RtcpPacket* packet) {
@@ -834,7 +790,10 @@ bool Xr::Create(uint8_t* packet,
block.Create(packet + *index);
*index += Rrtr::kLength;
}
- CreateDlrr(dlrr_blocks_, packet, index);
+ for (const Dlrr& block : dlrr_blocks_) {
+ block.Create(packet + *index);
+ *index += block.BlockLength();
+ }
for (const VoipMetric& block : voip_metric_blocks_) {
block.Create(packet + *index);
*index += VoipMetric::kLength;
@@ -853,12 +812,12 @@ bool Xr::WithRrtr(Rrtr* rrtr) {
}
bool Xr::WithDlrr(Dlrr* dlrr) {
- assert(dlrr);
+ RTC_DCHECK(dlrr);
if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) {
LOG(LS_WARNING) << "Max DLRR blocks reached.";
return false;
}
- dlrr_blocks_.push_back(dlrr->dlrr_block_);
+ dlrr_blocks_.push_back(*dlrr);
return true;
}
@@ -873,33 +832,13 @@ bool Xr::WithVoipMetric(VoipMetric* voip_metric) {
}
size_t Xr::DlrrLength() const {
- const size_t kBlockHeaderLen = 4;
- const size_t kSubBlockLen = 12;
size_t length = 0;
- for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin();
- it != dlrr_blocks_.end(); ++it) {
- if (!(*it).empty()) {
- length += kBlockHeaderLen + kSubBlockLen * (*it).size();
- }
+ for (const Dlrr& block : dlrr_blocks_) {
+ length += block.BlockLength();
}
return length;
}
-bool Dlrr::WithDlrrItem(uint32_t ssrc,
- uint32_t last_rr,
- uint32_t delay_last_rr) {
- if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) {
- LOG(LS_WARNING) << "Max DLRR items reached.";
- return false;
- }
- RTCPPacketXRDLRRReportBlockItem dlrr;
- dlrr.SSRC = ssrc;
- dlrr.LastRR = last_rr;
- dlrr.DelayLastRR = delay_last_rr;
- dlrr_block_.push_back(dlrr);
- 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 dcbb1e72d3..3adcc9a759 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
@@ -18,6 +18,7 @@
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.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/rrtr.h"
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h"
@@ -30,7 +31,6 @@ namespace rtcp {
static const int kCommonFbFmtLength = 12;
static const int kReportBlockLength = 24;
-class Dlrr;
class RawPacket;
// Class for building RTCP packets.
@@ -679,46 +679,12 @@ class Xr : public RtcpPacket {
RTCPUtility::RTCPPacketXR xr_header_;
std::vector<Rrtr> rrtr_blocks_;
- std::vector<DlrrBlock> dlrr_blocks_;
+ std::vector<Dlrr> dlrr_blocks_;
std::vector<VoipMetric> voip_metric_blocks_;
RTC_DISALLOW_COPY_AND_ASSIGN(Xr);
};
-// DLRR Report Block (RFC 3611).
-//
-// 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
-
-class Dlrr {
- public:
- Dlrr() {}
- ~Dlrr() {}
-
- // Max 100 DLRR Items can be added per DLRR report block.
- bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr);
-
- private:
- friend class Xr;
- static const int kMaxNumberOfDlrrItems = 100;
-
- std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> dlrr_block_;
-
- RTC_DISALLOW_COPY_AND_ASSIGN(Dlrr);
-};
-
// Class holding a RTCP packet.
//
// Takes a built rtcp packet.
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc
new file mode 100644
index 0000000000..6d6c48fada
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015 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/dlrr.h"
+
+#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
+
+namespace webrtc {
+namespace rtcp {
+// DLRR Report Block (RFC 3611).
+//
+// 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 Dlrr::Parse(const uint8_t* buffer, uint16_t block_length_32bits) {
+ RTC_DCHECK(buffer[0] == kBlockType);
+ // kReserved = buffer[1];
+ RTC_DCHECK_EQ(block_length_32bits,
+ ByteReader<uint16_t>::ReadBigEndian(&buffer[2]));
+ if (block_length_32bits % 3 != 0) {
+ LOG(LS_WARNING) << "Invalid size for dlrr block.";
+ return false;
+ }
+
+ size_t blocks_count = block_length_32bits / 3;
+ const uint8_t* read_at = buffer + kBlockHeaderLength;
+ sub_blocks_.resize(blocks_count);
+ for (SubBlock& sub_block : sub_blocks_) {
+ sub_block.ssrc = ByteReader<uint32_t>::ReadBigEndian(&read_at[0]);
+ sub_block.last_rr = ByteReader<uint32_t>::ReadBigEndian(&read_at[4]);
+ sub_block.delay_since_last_rr =
+ ByteReader<uint32_t>::ReadBigEndian(&read_at[8]);
+ read_at += kSubBlockLength;
+ }
+ return true;
+}
+
+size_t Dlrr::BlockLength() const {
+ if (sub_blocks_.empty())
+ return 0;
+ return kBlockHeaderLength + kSubBlockLength * sub_blocks_.size();
+}
+
+void Dlrr::Create(uint8_t* buffer) const {
+ if (sub_blocks_.empty()) // No subblocks, no need to write header either.
+ return;
+ // Create block header.
+ const uint8_t kReserved = 0;
+ buffer[0] = kBlockType;
+ buffer[1] = kReserved;
+ ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], 3 * sub_blocks_.size());
+ // Create sub blocks.
+ uint8_t* write_at = buffer + kBlockHeaderLength;
+ for (const SubBlock& sub_block : sub_blocks_) {
+ ByteWriter<uint32_t>::WriteBigEndian(&write_at[0], sub_block.ssrc);
+ ByteWriter<uint32_t>::WriteBigEndian(&write_at[4], sub_block.last_rr);
+ ByteWriter<uint32_t>::WriteBigEndian(&write_at[8],
+ sub_block.delay_since_last_rr);
+ write_at += kSubBlockLength;
+ }
+ RTC_DCHECK_EQ(buffer + BlockLength(), write_at);
+}
+
+bool Dlrr::WithDlrrItem(uint32_t ssrc,
+ uint32_t last_rr,
+ uint32_t delay_last_rr) {
+ if (sub_blocks_.size() >= kMaxNumberOfDlrrItems) {
+ LOG(LS_WARNING) << "Max DLRR items reached.";
+ return false;
+ }
+ SubBlock block;
+ block.ssrc = ssrc;
+ block.last_rr = last_rr;
+ block.delay_since_last_rr = delay_last_rr;
+ sub_blocks_.push_back(block);
+ return true;
+}
+
+} // namespace rtcp
+} // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h
new file mode 100644
index 0000000000..9af2dedf3f
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 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_DLRR_H_
+#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_DLRR_H_
+
+#include <vector>
+
+#include "webrtc/base/basictypes.h"
+
+namespace webrtc {
+namespace rtcp {
+
+// DLRR Report Block: Delay since the Last Receiver Report (RFC 3611).
+class Dlrr {
+ public:
+ struct SubBlock {
+ // RFC 3611 4.5
+ uint32_t ssrc;
+ uint32_t last_rr;
+ uint32_t delay_since_last_rr;
+ };
+
+ static const uint8_t kBlockType = 5;
+ static const size_t kMaxNumberOfDlrrItems = 100;
+
+ Dlrr() {}
+ Dlrr(const Dlrr& other) = default;
+ ~Dlrr() {}
+
+ Dlrr& operator=(const Dlrr& other) = default;
+
+ // Second parameter is value read from block header,
+ // i.e. size of block in 32bits excluding block header itself.
+ bool Parse(const uint8_t* buffer, uint16_t block_length_32bits);
+
+ size_t BlockLength() const;
+ // Fills buffer with the Dlrr.
+ // Consumes BlockLength() bytes.
+ void Create(uint8_t* buffer) const;
+
+ // Max 100 DLRR Items can be added per DLRR report block.
+ bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr);
+
+ const std::vector<SubBlock>& sub_blocks() const { return sub_blocks_; }
+
+ private:
+ static const size_t kBlockHeaderLength = 4;
+ static const size_t kSubBlockLength = 12;
+
+ std::vector<SubBlock> sub_blocks_;
+};
+} // namespace rtcp
+} // namespace webrtc
+#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_DLRR_H_
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc
new file mode 100644
index 0000000000..c7c139c560
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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/dlrr.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
+
+using webrtc::rtcp::Dlrr;
+
+namespace webrtc {
+namespace {
+
+const uint32_t kSsrc = 0x12345678;
+const uint32_t kLastRR = 0x23344556;
+const uint32_t kDelay = 0x33343536;
+const uint8_t kBlock[] = {0x05, 0x00, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78,
+ 0x23, 0x34, 0x45, 0x56, 0x33, 0x34, 0x35, 0x36};
+const size_t kBlockSizeBytes = sizeof(kBlock);
+
+TEST(RtcpPacketDlrrTest, Empty) {
+ Dlrr dlrr;
+
+ EXPECT_EQ(0u, dlrr.BlockLength());
+}
+
+TEST(RtcpPacketDlrrTest, Create) {
+ Dlrr dlrr;
+ EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc, kLastRR, kDelay));
+
+ ASSERT_EQ(kBlockSizeBytes, dlrr.BlockLength());
+ uint8_t buffer[kBlockSizeBytes];
+
+ dlrr.Create(buffer);
+ EXPECT_EQ(0, memcmp(buffer, kBlock, kBlockSizeBytes));
+}
+
+TEST(RtcpPacketDlrrTest, Parse) {
+ Dlrr dlrr;
+ uint16_t block_length = ByteReader<uint16_t>::ReadBigEndian(&kBlock[2]);
+ EXPECT_TRUE(dlrr.Parse(kBlock, block_length));
+
+ EXPECT_EQ(1u, dlrr.sub_blocks().size());
+ const Dlrr::SubBlock& block = dlrr.sub_blocks().front();
+ EXPECT_EQ(kSsrc, block.ssrc);
+ EXPECT_EQ(kLastRR, block.last_rr);
+ EXPECT_EQ(kDelay, block.delay_since_last_rr);
+}
+
+TEST(RtcpPacketDlrrTest, ParseFailsOnBadSize) {
+ const size_t kBigBufferSize = 0x100; // More than enough.
+ uint8_t buffer[kBigBufferSize];
+ buffer[0] = Dlrr::kBlockType;
+ buffer[1] = 0; // Reserved.
+ buffer[2] = 0; // Most significant size byte.
+ for (uint8_t size = 3; size < 6; ++size) {
+ buffer[3] = size;
+ Dlrr dlrr;
+ // Parse should be successful only when size is multiple of 3.
+ EXPECT_EQ(size % 3 == 0, dlrr.Parse(buffer, static_cast<uint16_t>(size)));
+ }
+}
+
+TEST(RtcpPacketDlrrTest, FailsOnTooManySubBlocks) {
+ Dlrr dlrr;
+ for (size_t i = 1; i <= Dlrr::kMaxNumberOfDlrrItems; ++i) {
+ EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc + i, kLastRR + i, kDelay + i));
+ }
+ EXPECT_FALSE(dlrr.WithDlrrItem(kSsrc, kLastRR, kDelay));
+}
+
+TEST(RtcpPacketDlrrTest, CreateAndParseMaxSubBlocks) {
+ const size_t kBufferSize = 0x1000; // More than enough.
+ uint8_t buffer[kBufferSize];
+
+ // Create.
+ Dlrr dlrr;
+ for (size_t i = 1; i <= Dlrr::kMaxNumberOfDlrrItems; ++i) {
+ EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc + i, kLastRR + i, kDelay + i));
+ }
+ size_t used_buffer_size = dlrr.BlockLength();
+ ASSERT_LE(used_buffer_size, kBufferSize);
+ dlrr.Create(buffer);
+
+ // Parse.
+ Dlrr parsed;
+ uint16_t block_length = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]);
+ EXPECT_EQ(used_buffer_size, (block_length + 1) * 4u);
+ EXPECT_TRUE(parsed.Parse(buffer, block_length));
+ EXPECT_TRUE(parsed.sub_blocks().size() == Dlrr::kMaxNumberOfDlrrItems);
+}
+
+} // namespace
+} // namespace webrtc