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