rtcp::ReportBlock refactored to contain parsing

Review URL: https://codereview.webrtc.org/1420283022

Cr-Commit-Position: refs/heads/master@{#10633}
This commit is contained in:
danilchap 2015-11-13 03:03:13 -08:00 committed by Commit bot
parent 0a41893e36
commit df948f03b3
9 changed files with 262 additions and 72 deletions

View File

@ -247,6 +247,7 @@
'rtp_rtcp/source/remote_ntp_time_estimator_unittest.cc',
'rtp_rtcp/source/rtcp_format_remb_unittest.cc',
'rtp_rtcp/source/rtcp_packet_unittest.cc',
'rtp_rtcp/source/rtcp_packet/report_block_unittest.cc',
'rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc',
'rtp_rtcp/source/rtcp_receiver_unittest.cc',
'rtp_rtcp/source/rtcp_sender_unittest.cc',

View File

@ -46,6 +46,8 @@ source_set("rtp_rtcp") {
"source/remote_ntp_time_estimator.cc",
"source/rtcp_packet.cc",
"source/rtcp_packet.h",
"source/rtcp_packet/report_block.cc",
"source/rtcp_packet/report_block.h",
"source/rtcp_packet/transport_feedback.cc",
"source/rtcp_packet/transport_feedback.h",
"source/rtcp_receiver.cc",

View File

@ -41,6 +41,8 @@
'source/rtp_rtcp_impl.h',
'source/rtcp_packet.cc',
'source/rtcp_packet.h',
'source/rtcp_packet/report_block.cc',
'source/rtcp_packet/report_block.h',
'source/rtcp_packet/transport_feedback.cc',
'source/rtcp_packet/transport_feedback.h',
'source/rtcp_receiver.cc',

View File

@ -154,18 +154,12 @@ void CreateReceiverReport(const RTCPPacketRR& rr,
// | delay since last SR (DLSR) |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
void CreateReportBlocks(const std::vector<ReportBlock>& blocks,
uint8_t* buffer,
size_t* pos) {
for (std::vector<RTCPPacketReportBlockItem>::const_iterator
it = blocks.begin(); it != blocks.end(); ++it) {
AssignUWord32(buffer, pos, (*it).SSRC);
AssignUWord8(buffer, pos, (*it).FractionLost);
AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost);
AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber);
AssignUWord32(buffer, pos, (*it).Jitter);
AssignUWord32(buffer, pos, (*it).LastSR);
AssignUWord32(buffer, pos, (*it).DelayLastSR);
for (const ReportBlock& block : blocks) {
block.Create(buffer + *pos);
*pos += ReportBlock::kLength;
}
}
@ -781,7 +775,7 @@ bool SenderReport::WithReportBlock(const ReportBlock& block) {
LOG(LS_WARNING) << "Max report blocks reached.";
return false;
}
report_blocks_.push_back(block.report_block_);
report_blocks_.push_back(block);
sr_.NumberOfReportBlocks = report_blocks_.size();
return true;
}
@ -805,7 +799,7 @@ bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
LOG(LS_WARNING) << "Max report blocks reached.";
return false;
}
report_blocks_.push_back(block.report_block_);
report_blocks_.push_back(block);
rr_.NumberOfReportBlocks = report_blocks_.size();
return true;
}

View File

@ -17,6 +17,7 @@
#include <vector>
#include "webrtc/base/scoped_ptr.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/include/rtp_rtcp_defines.h"
#include "webrtc/typedefs.h"
@ -145,63 +146,6 @@ class Empty : public RtcpPacket {
RTC_DISALLOW_COPY_AND_ASSIGN(Empty);
};
// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
//
// RTCP report block (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
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | 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) |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
class ReportBlock {
public:
ReportBlock() {
// TODO(asapersson): Consider adding a constructor to struct.
memset(&report_block_, 0, sizeof(report_block_));
}
~ReportBlock() {}
void To(uint32_t ssrc) {
report_block_.SSRC = ssrc;
}
void WithFractionLost(uint8_t fraction_lost) {
report_block_.FractionLost = fraction_lost;
}
void WithCumulativeLost(uint32_t cumulative_lost) {
report_block_.CumulativeNumOfPacketsLost = cumulative_lost;
}
void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) {
report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num;
}
void WithJitter(uint32_t jitter) {
report_block_.Jitter = jitter;
}
void WithLastSr(uint32_t last_sr) {
report_block_.LastSR = last_sr;
}
void WithDelayLastSr(uint32_t delay_last_sr) {
report_block_.DelayLastSR = delay_last_sr;
}
private:
friend class SenderReport;
friend class ReceiverReport;
RTCPUtility::RTCPPacketReportBlockItem report_block_;
};
// 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
@ -268,7 +212,7 @@ class SenderReport : public RtcpPacket {
}
RTCPUtility::RTCPPacketSR sr_;
std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
std::vector<ReportBlock> report_blocks_;
RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport);
};
@ -314,7 +258,7 @@ class ReceiverReport : public RtcpPacket {
}
RTCPUtility::RTCPPacketRR rr_;
std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
std::vector<ReportBlock> report_blocks_;
RTC_DISALLOW_COPY_AND_ASSIGN(ReceiverReport);
};

View File

@ -0,0 +1,89 @@
/*
* 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/report_block.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
namespace webrtc {
namespace rtcp {
// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
//
// RTCP report block (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
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 0 | SSRC_1 (SSRC of first source) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 4 | fraction lost | cumulative number of packets lost |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 8 | extended highest sequence number received |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 12 | interarrival jitter |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 16 | last SR (LSR) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 20 | delay since last SR (DLSR) |
// 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
ReportBlock::ReportBlock()
: source_ssrc_(0),
fraction_lost_(0),
cumulative_lost_(0),
extended_high_seq_num_(0),
jitter_(0),
last_sr_(0),
delay_since_last_sr_(0) {}
bool ReportBlock::Parse(const uint8_t* buffer, size_t length) {
RTC_DCHECK(buffer != nullptr);
if (length < ReportBlock::kLength) {
LOG(LS_ERROR) << "Report Block should be 24 bytes long";
return false;
}
source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[0]);
fraction_lost_ = buffer[4];
cumulative_lost_ = ByteReader<uint32_t, 3>::ReadBigEndian(&buffer[5]);
extended_high_seq_num_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
jitter_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[12]);
last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[16]);
delay_since_last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[20]);
return true;
}
void ReportBlock::Create(uint8_t* buffer) const {
// Runtime check should be done while setting cumulative_lost.
RTC_DCHECK_LT(cumulative_lost(), (1u << 24)); // Have only 3 bytes for it.
ByteWriter<uint32_t>::WriteBigEndian(&buffer[0], source_ssrc());
ByteWriter<uint8_t>::WriteBigEndian(&buffer[4], fraction_lost());
ByteWriter<uint32_t, 3>::WriteBigEndian(&buffer[5], cumulative_lost());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[8], extended_high_seq_num());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[12], jitter());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[16], last_sr());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[20], delay_since_last_sr());
}
bool ReportBlock::WithCumulativeLost(uint32_t cumulative_lost) {
if (cumulative_lost >= (1u << 24)) { // Have only 3 bytes to store it.
LOG(LS_WARNING) << "Cumulative lost is too big to fit into Report Block";
return false;
}
cumulative_lost_ = cumulative_lost;
return true;
}
} // namespace rtcp
} // namespace webrtc

View File

@ -0,0 +1,67 @@
/*
* 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_REPORT_BLOCK_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_REPORT_BLOCK_H_
#include "webrtc/base/basictypes.h"
namespace webrtc {
namespace rtcp {
class ReportBlock {
public:
static const size_t kLength = 24;
ReportBlock();
~ReportBlock() {}
bool Parse(const uint8_t* buffer, size_t length);
// Fills buffer with the ReportBlock.
// Consumes ReportBlock::kLength bytes.
void Create(uint8_t* buffer) const;
void To(uint32_t ssrc) { source_ssrc_ = ssrc; }
void WithFractionLost(uint8_t fraction_lost) {
fraction_lost_ = fraction_lost;
}
bool WithCumulativeLost(uint32_t cumulative_lost);
void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) {
extended_high_seq_num_ = ext_highest_seq_num;
}
void WithJitter(uint32_t jitter) { jitter_ = jitter; }
void WithLastSr(uint32_t last_sr) { last_sr_ = last_sr; }
void WithDelayLastSr(uint32_t delay_last_sr) {
delay_since_last_sr_ = delay_last_sr;
}
uint32_t source_ssrc() const { return source_ssrc_; }
uint8_t fraction_lost() const { return fraction_lost_; }
uint32_t cumulative_lost() const { return cumulative_lost_; }
uint32_t extended_high_seq_num() const { return extended_high_seq_num_; }
uint32_t jitter() const { return jitter_; }
uint32_t last_sr() const { return last_sr_; }
uint32_t delay_since_last_sr() const { return delay_since_last_sr_; }
private:
uint32_t source_ssrc_;
uint8_t fraction_lost_;
uint32_t cumulative_lost_;
uint32_t extended_high_seq_num_;
uint32_t jitter_;
uint32_t last_sr_;
uint32_t delay_since_last_sr_;
};
} // namespace rtcp
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_REPORT_BLOCK_H_

View File

@ -0,0 +1,86 @@
/*
* 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/report_block.h"
#include <limits>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/test/random.h"
using webrtc::rtcp::ReportBlock;
namespace webrtc {
namespace {
const uint32_t kRemoteSsrc = 0x23456789;
const uint8_t kFractionLost = 55;
// Use values that are streamed differently LE and BE.
const uint32_t kCumulativeLost = 0x111213;
const uint32_t kExtHighestSeqNum = 0x22232425;
const uint32_t kJitter = 0x33343536;
const uint32_t kLastSr = 0x44454647;
const uint32_t kDelayLastSr = 0x55565758;
const size_t kBufferLength = ReportBlock::kLength;
TEST(RtcpPacketReportBlockTest, ParseChecksLength) {
uint8_t buffer[kBufferLength];
memset(buffer, 0, sizeof(buffer));
ReportBlock rb;
EXPECT_FALSE(rb.Parse(buffer, kBufferLength - 1));
EXPECT_TRUE(rb.Parse(buffer, kBufferLength));
}
TEST(RtcpPacketReportBlockTest, ParseAnyData) {
uint8_t buffer[kBufferLength];
// Fill buffer with semi-random data.
test::Random generator(testing::FLAGS_gtest_random_seed);
for (size_t i = 0; i < kBufferLength; ++i)
buffer[i] = static_cast<uint8_t>(generator.Rand(0, 0xff));
ReportBlock rb;
EXPECT_TRUE(rb.Parse(buffer, kBufferLength));
}
TEST(RtcpPacketReportBlockTest, ParseMatchCreate) {
ReportBlock rb;
rb.To(kRemoteSsrc);
rb.WithFractionLost(kFractionLost);
rb.WithCumulativeLost(kCumulativeLost);
rb.WithExtHighestSeqNum(kExtHighestSeqNum);
rb.WithJitter(kJitter);
rb.WithLastSr(kLastSr);
rb.WithDelayLastSr(kDelayLastSr);
uint8_t buffer[kBufferLength];
rb.Create(buffer);
ReportBlock parsed;
EXPECT_TRUE(parsed.Parse(buffer, kBufferLength));
EXPECT_EQ(kRemoteSsrc, parsed.source_ssrc());
EXPECT_EQ(kFractionLost, parsed.fraction_lost());
EXPECT_EQ(kCumulativeLost, parsed.cumulative_lost());
EXPECT_EQ(kExtHighestSeqNum, parsed.extended_high_seq_num());
EXPECT_EQ(kJitter, parsed.jitter());
EXPECT_EQ(kLastSr, parsed.last_sr());
EXPECT_EQ(kDelayLastSr, parsed.delay_since_last_sr());
}
TEST(RtcpPacketReportBlockTest, ValidateCumulativeLost) {
const uint32_t kMaxCumulativeLost = 0xffffff;
ReportBlock rb;
EXPECT_FALSE(rb.WithCumulativeLost(kMaxCumulativeLost + 1));
EXPECT_TRUE(rb.WithCumulativeLost(kMaxCumulativeLost));
}
} // namespace
} // namespace webrtc

View File

@ -459,7 +459,10 @@ int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
block->To(report_block.remoteSSRC);
block->WithFractionLost(report_block.fractionLost);
block->WithCumulativeLost(report_block.cumulativeLost);
if (!block->WithCumulativeLost(report_block.cumulativeLost)) {
LOG(LS_WARNING) << "Cumulative lost is oversized.";
return -1;
}
block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
block->WithJitter(report_block.jitter);
block->WithLastSr(report_block.lastSR);
@ -1024,6 +1027,8 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
RTCPReportBlock report_block;
if (PrepareReport(feedback_state, it->first, it->second,
&report_block)) {
// TODO(danilchap) AddReportBlock may fail (for 2 different reasons).
// Probably it shouldn't be ignored.
AddReportBlock(report_block);
}
}