summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasapersson@webrtc.org <asapersson@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2014-06-16 14:09:28 +0000
committerasapersson@webrtc.org <asapersson@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2014-06-16 14:09:28 +0000
commit847dfa535730a30d57cf26d788d31070b70a02af (patch)
tree5c84330013805ff5b8b8e9d3d1dcfd00a5effba1
parente82b71dedcaaa6db0181ba52ac020fde19552189 (diff)
downloadwebrtc-847dfa535730a30d57cf26d788d31070b70a02af.tar.gz
Add SDES, APP, IJ, SLI and PLI packet types to RTCP packet class.
BUG=2450 R=mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/19559004 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@6449 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r--modules/rtp_rtcp/source/rtcp_packet.cc382
-rw-r--r--modules/rtp_rtcp/source/rtcp_packet.h467
-rw-r--r--modules/rtp_rtcp/source/rtcp_packet_unittest.cc189
-rw-r--r--test/rtcp_packet_parser.cc33
-rw-r--r--test/rtcp_packet_parser.h174
5 files changed, 1042 insertions, 203 deletions
diff --git a/modules/rtp_rtcp/source/rtcp_packet.cc b/modules/rtp_rtcp/source/rtcp_packet.cc
index 51c86aaa..a4cdfd95 100644
--- a/modules/rtp_rtcp/source/rtcp_packet.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet.cc
@@ -13,21 +13,39 @@
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
#include "webrtc/system_wrappers/interface/logging.h"
+using webrtc::RTCPUtility::PT_APP;
using webrtc::RTCPUtility::PT_BYE;
+using webrtc::RTCPUtility::PT_IJ;
using webrtc::RTCPUtility::PT_PSFB;
using webrtc::RTCPUtility::PT_RR;
using webrtc::RTCPUtility::PT_RTPFB;
+using webrtc::RTCPUtility::PT_SDES;
using webrtc::RTCPUtility::PT_SR;
+using webrtc::RTCPUtility::PT_XR;
+using webrtc::RTCPUtility::RTCPPacketAPP;
using webrtc::RTCPUtility::RTCPPacketBYE;
+using webrtc::RTCPUtility::RTCPPacketPSFBAPP;
using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
+using webrtc::RTCPUtility::RTCPPacketPSFBPLI;
+using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
+using webrtc::RTCPUtility::RTCPPacketPSFBSLI;
+using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem;
using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
using webrtc::RTCPUtility::RTCPPacketRR;
using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
+using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN;
+using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem;
+using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR;
+using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem;
using webrtc::RTCPUtility::RTCPPacketSR;
+using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
+using webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem;
+using webrtc::RTCPUtility::RTCPPacketXR;
+using webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem;
namespace webrtc {
namespace rtcp {
@@ -35,23 +53,23 @@ namespace {
// Unused SSRC of media source, set to 0.
const uint32_t kUnusedMediaSourceSsrc0 = 0;
-void AssignUWord8(uint8_t* buffer, uint16_t* offset, uint8_t value) {
+void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
buffer[(*offset)++] = value;
}
-void AssignUWord16(uint8_t* buffer, uint16_t* offset, uint16_t value) {
+void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
ModuleRTPUtility::AssignUWord16ToBuffer(buffer + *offset, value);
*offset += 2;
}
-void AssignUWord24(uint8_t* buffer, uint16_t* offset, uint32_t value) {
+void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
ModuleRTPUtility::AssignUWord24ToBuffer(buffer + *offset, value);
*offset += 3;
}
-void AssignUWord32(uint8_t* buffer, uint16_t* offset, uint32_t value) {
+void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
ModuleRTPUtility::AssignUWord32ToBuffer(buffer + *offset, value);
*offset += 4;
}
-uint16_t BlockToHeaderLength(uint16_t length_in_bytes) {
+size_t BlockToHeaderLength(size_t length_in_bytes) {
// Length in 32-bit words minus 1.
assert(length_in_bytes > 0);
assert(length_in_bytes % 4 == 0);
@@ -69,9 +87,10 @@ uint16_t BlockToHeaderLength(uint16_t length_in_bytes) {
void CreateHeader(uint8_t count_or_format, // Depends on packet type.
uint8_t packet_type,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
+ assert(length <= 0xffff);
const uint8_t kVersion = 2;
AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
AssignUWord8(buffer, pos, packet_type);
@@ -98,9 +117,9 @@ void CreateHeader(uint8_t count_or_format, // Depends on packet type.
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
void CreateSenderReport(const RTCPPacketSR& sr,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
AssignUWord32(buffer, pos, sr.SenderSSRC);
AssignUWord32(buffer, pos, sr.NTPMostSignificant);
@@ -120,9 +139,9 @@ void CreateSenderReport(const RTCPPacketSR& sr,
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
void CreateReceiverReport(const RTCPPacketRR& rr,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
AssignUWord32(buffer, pos, rr.SenderSSRC);
}
@@ -144,16 +163,89 @@ void CreateReceiverReport(const RTCPPacketRR& rr,
// | delay since last SR (DLSR) |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-void CreateReportBlock(const RTCPPacketReportBlockItem& report_block,
- uint8_t* buffer,
- uint16_t* pos) {
- AssignUWord32(buffer, pos, report_block.SSRC);
- AssignUWord8(buffer, pos, report_block.FractionLost);
- AssignUWord24(buffer, pos, report_block.CumulativeNumOfPacketsLost);
- AssignUWord32(buffer, pos, report_block.ExtendedHighestSequenceNumber);
- AssignUWord32(buffer, pos, report_block.Jitter);
- AssignUWord32(buffer, pos, report_block.LastSR);
- AssignUWord32(buffer, pos, report_block.DelayLastSR);
+void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& 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);
+ }
+}
+
+// Transmission Time Offsets in RTP Streams (RFC 5450).
+//
+// 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 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+void CreateIj(const std::vector<uint32_t>& ij_items,
+ uint8_t* buffer,
+ size_t* pos) {
+ size_t length = ij_items.size();
+ CreateHeader(length, PT_IJ, length, buffer, pos);
+ for (std::vector<uint32_t>::const_iterator it = ij_items.begin();
+ it != ij_items.end(); ++it) {
+ AssignUWord32(buffer, pos, *it);
+ }
+}
+
+// Source Description (SDES) (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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// header |V=2|P| SC | PT=SDES=202 | length |
+// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+// chunk | SSRC/CSRC_1 |
+// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | SDES items |
+// | ... |
+// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+// chunk | SSRC/CSRC_2 |
+// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | SDES items |
+// | ... |
+// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// Canonical End-Point Identifier SDES Item (CNAME)
+//
+// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | CNAME=1 | length | user and domain name ...
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
+ size_t length,
+ uint8_t* buffer,
+ size_t* pos) {
+ CreateHeader(chunks.size(), PT_SDES, length, buffer, pos);
+ const uint8_t kSdesItemType = 1;
+ for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
+ it != chunks.end(); ++it) {
+ AssignUWord32(buffer, pos, (*it).ssrc);
+ AssignUWord8(buffer, pos, kSdesItemType);
+ AssignUWord8(buffer, pos, (*it).name.length());
+ memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
+ *pos += (*it).name.length();
+ memset(buffer + *pos, 0, (*it).null_octets);
+ *pos += (*it).null_octets;
+ }
}
// Bye packet (BYE) (RFC 3550).
@@ -171,9 +263,9 @@ void CreateReportBlock(const RTCPPacketReportBlockItem& report_block,
void CreateBye(const RTCPPacketBYE& bye,
const std::vector<uint32_t>& csrcs,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
CreateHeader(length, PT_BYE, length, buffer, pos);
AssignUWord32(buffer, pos, bye.SenderSSRC);
for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
@@ -182,6 +274,32 @@ void CreateBye(const RTCPPacketBYE& bye,
}
}
+// Application-Defined packet (APP) (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| subtype | PT=APP=204 | length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | SSRC/CSRC |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | name (ASCII) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | application-dependent data ...
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+void CreateApp(const RTCPPacketAPP& app,
+ uint32_t ssrc,
+ size_t length,
+ uint8_t* buffer,
+ size_t* pos) {
+ CreateHeader(app.SubType, PT_APP, length, buffer, pos);
+ AssignUWord32(buffer, pos, ssrc);
+ AssignUWord32(buffer, pos, app.Name);
+ memcpy(buffer + *pos, app.Data, app.Size);
+ *pos += app.Size;
+}
+
// RFC 4585: Feedback format.
//
// Common packet format:
@@ -199,6 +317,47 @@ void CreateBye(const RTCPPacketBYE& bye,
// :
//
+// Picture loss indication (PLI) (RFC 4585).
+//
+// FCI: no feedback control information.
+
+void CreatePli(const RTCPPacketPSFBPLI& pli,
+ size_t length,
+ uint8_t* buffer,
+ size_t* pos) {
+ const uint8_t kFmt = 1;
+ CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
+ AssignUWord32(buffer, pos, pli.SenderSSRC);
+ AssignUWord32(buffer, pos, pli.MediaSSRC);
+}
+
+// Slice loss indication (SLI) (RFC 4585).
+//
+// FCI:
+//
+// 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 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+void CreateSli(const RTCPPacketPSFBSLI& sli,
+ const RTCPPacketPSFBSLIItem& sli_item,
+ size_t length,
+ uint8_t* buffer,
+ size_t* pos) {
+ const uint8_t kFmt = 2;
+ CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
+ AssignUWord32(buffer, pos, sli.SenderSSRC);
+ AssignUWord32(buffer, pos, sli.MediaSSRC);
+
+ AssignUWord8(buffer, pos, sli_item.FirstMB >> 5);
+ AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) +
+ ((sli_item.NumberOfMB >> 10) & 0x07));
+ AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2);
+ AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId);
+}
+
// Generic NACK (RFC 4585).
//
// FCI:
@@ -211,9 +370,9 @@ void CreateBye(const RTCPPacketBYE& bye,
void CreateNack(const RTCPPacketRTPFBNACK& nack,
const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
const uint8_t kFmt = 1;
CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
AssignUWord32(buffer, pos, nack.SenderSSRC);
@@ -239,9 +398,9 @@ void CreateNack(const RTCPPacketRTPFBNACK& nack,
void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
uint8_t padding_bytes,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
// Native bit string should be a multiple of 8 bits.
assert(rpsi.NumberOfValidBits % 8 == 0);
const uint8_t kFmt = 3;
@@ -270,9 +429,9 @@ void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
void CreateFir(const RTCPPacketPSFBFIR& fir,
const RTCPPacketPSFBFIRItem& fir_item,
- uint16_t length,
+ size_t length,
uint8_t* buffer,
- uint16_t* pos) {
+ size_t* pos) {
const uint8_t kFmt = 4;
CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
AssignUWord32(buffer, pos, fir.SenderSSRC);
@@ -281,16 +440,6 @@ void CreateFir(const RTCPPacketPSFBFIR& fir,
AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
AssignUWord24(buffer, pos, 0);
}
-
-template <typename T>
-void AppendBlocks(const std::vector<T*>& blocks,
- uint8_t* buffer,
- uint16_t* pos) {
- for (typename std::vector<T*>::const_iterator it = blocks.begin();
- it != blocks.end(); ++it) {
- (*it)->Create(buffer, pos);
- }
-}
} // namespace
void RtcpPacket::Append(RtcpPacket* packet) {
@@ -299,39 +448,41 @@ void RtcpPacket::Append(RtcpPacket* packet) {
}
RawPacket RtcpPacket::Build() const {
- uint16_t len = 0;
+ size_t length = 0;
uint8_t packet[IP_PACKET_SIZE];
- CreateAndAddAppended(packet, &len, IP_PACKET_SIZE);
- return RawPacket(packet, len);
+ CreateAndAddAppended(packet, &length, IP_PACKET_SIZE);
+ return RawPacket(packet, length);
}
-void RtcpPacket::Build(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
- *len = 0;
- CreateAndAddAppended(packet, len, max_len);
+void RtcpPacket::Build(uint8_t* packet,
+ size_t* length,
+ size_t max_length) const {
+ *length = 0;
+ CreateAndAddAppended(packet, length, max_length);
}
void RtcpPacket::CreateAndAddAppended(uint8_t* packet,
- uint16_t* len,
- uint16_t max_len) const {
- Create(packet, len, max_len);
+ size_t* length,
+ size_t max_length) const {
+ Create(packet, length, max_length);
for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
it != appended_packets_.end(); ++it) {
- (*it)->CreateAndAddAppended(packet, len, max_len);
+ (*it)->CreateAndAddAppended(packet, length, max_length);
}
}
-void Empty::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
+void Empty::Create(uint8_t* packet, size_t* length, size_t max_length) const {
}
void SenderReport::Create(uint8_t* packet,
- uint16_t* len,
- uint16_t max_len) const {
- if (*len + Length() > max_len) {
+ size_t* length,
+ size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
LOG(LS_WARNING) << "Max packet size reached.";
return;
}
- CreateSenderReport(sr_, BlockToHeaderLength(Length()), packet, len);
- AppendBlocks(report_blocks_, packet, len);
+ CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, length);
+ CreateReportBlocks(report_blocks_, packet, length);
}
void SenderReport::WithReportBlock(ReportBlock* block) {
@@ -340,19 +491,19 @@ void SenderReport::WithReportBlock(ReportBlock* block) {
LOG(LS_WARNING) << "Max report blocks reached.";
return;
}
- report_blocks_.push_back(block);
+ report_blocks_.push_back(block->report_block_);
sr_.NumberOfReportBlocks = report_blocks_.size();
}
void ReceiverReport::Create(uint8_t* packet,
- uint16_t* len,
- uint16_t max_len) const {
- if (*len + Length() > max_len) {
+ size_t* length,
+ size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
LOG(LS_WARNING) << "Max packet size reached.";
return;
}
- CreateReceiverReport(rr_, BlockToHeaderLength(Length()), packet, len);
- AppendBlocks(report_blocks_, packet, len);
+ CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, length);
+ CreateReportBlocks(report_blocks_, packet, length);
}
void ReceiverReport::WithReportBlock(ReportBlock* block) {
@@ -361,20 +512,71 @@ void ReceiverReport::WithReportBlock(ReportBlock* block) {
LOG(LS_WARNING) << "Max report blocks reached.";
return;
}
- report_blocks_.push_back(block);
+ report_blocks_.push_back(block->report_block_);
rr_.NumberOfReportBlocks = report_blocks_.size();
}
-void ReportBlock::Create(uint8_t* packet, uint16_t* len) const {
- CreateReportBlock(report_block_, packet, len);
+void Ij::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
+ LOG(LS_WARNING) << "Max packet size reached.";
+ return;
+ }
+ CreateIj(ij_items_, packet, length);
+}
+
+void Ij::WithJitterItem(uint32_t jitter) {
+ if (ij_items_.size() >= kMaxNumberOfIjItems) {
+ LOG(LS_WARNING) << "Max inter-arrival jitter items reached.";
+ return;
+ }
+ ij_items_.push_back(jitter);
+}
+
+void Sdes::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ assert(!chunks_.empty());
+ if (*length + BlockLength() > max_length) {
+ LOG(LS_WARNING) << "Max packet size reached.";
+ return;
+ }
+ CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, length);
+}
+
+void Sdes::WithCName(uint32_t ssrc, std::string cname) {
+ assert(cname.length() <= 0xff);
+ if (chunks_.size() >= kMaxNumberOfChunks) {
+ LOG(LS_WARNING) << "Max SDES chunks reached.";
+ return;
+ }
+ // In each chunk, the list of items must be terminated by one or more null
+ // octets. The next chunk must start on a 32-bit boundary.
+ // CNAME (1 byte) | length (1 byte) | name | padding.
+ int null_octets = 4 - ((2 + cname.length()) % 4);
+ Chunk chunk;
+ chunk.ssrc = ssrc;
+ chunk.name = cname;
+ chunk.null_octets = null_octets;
+ chunks_.push_back(chunk);
}
-void Bye::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
- if (*len + Length() > max_len) {
+size_t Sdes::BlockLength() const {
+ // Header (4 bytes).
+ // Chunk:
+ // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
+ size_t length = kHeaderLength;
+ for (std::vector<Chunk>::const_iterator it = chunks_.begin();
+ it != chunks_.end(); ++it) {
+ length += 6 + (*it).name.length() + (*it).null_octets;
+ }
+ assert(length % 4 == 0);
+ return length;
+}
+
+void Bye::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
LOG(LS_WARNING) << "Max packet size reached.";
return;
}
- CreateBye(bye_, csrcs_, BlockToHeaderLength(Length()), packet, len);
+ CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, length);
}
void Bye::WithCsrc(uint32_t csrc) {
@@ -385,13 +587,39 @@ void Bye::WithCsrc(uint32_t csrc) {
csrcs_.push_back(csrc);
}
-void Nack::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
+void App::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
+ LOG(LS_WARNING) << "Max packet size reached.";
+ return;
+ }
+ CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, length);
+}
+
+void Pli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
+ LOG(LS_WARNING) << "Max packet size reached.";
+ return;
+ }
+ CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, length);
+}
+
+void Sli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
+ LOG(LS_WARNING) << "Max packet size reached.";
+ return;
+ }
+ CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet,
+ length);
+}
+
+void Nack::Create(uint8_t* packet, size_t* length, size_t max_length) const {
assert(!nack_fields_.empty());
- if (*len + Length() > max_len) {
+ if (*length + BlockLength() > max_length) {
LOG(LS_WARNING) << "Max packet size reached.";
return;
}
- CreateNack(nack_, nack_fields_, BlockToHeaderLength(Length()), packet, len);
+ CreateNack(nack_, nack_fields_, BlockToHeaderLength(BlockLength()), packet,
+ length);
}
void Nack::WithList(const uint16_t* nack_list, int length) {
@@ -418,13 +646,14 @@ void Nack::WithList(const uint16_t* nack_list, int length) {
}
}
-void Rpsi::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
+void Rpsi::Create(uint8_t* packet, size_t* length, size_t max_length) const {
assert(rpsi_.NumberOfValidBits > 0);
- if (*len + Length() > max_len) {
+ if (*length + BlockLength() > max_length) {
LOG(LS_WARNING) << "Max packet size reached.";
return;
}
- CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(Length()), packet, len);
+ CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet,
+ length);
}
void Rpsi::WithPictureId(uint64_t picture_id) {
@@ -454,12 +683,13 @@ void Rpsi::WithPictureId(uint64_t picture_id) {
}
}
-void Fir::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
- if (*len + Length() > max_len) {
+void Fir::Create(uint8_t* packet, size_t* length, size_t max_length) const {
+ if (*length + BlockLength() > max_length) {
LOG(LS_WARNING) << "Max packet size reached.";
return;
}
- CreateFir(fir_, fir_item_, BlockToHeaderLength(Length()), packet, len);
+ CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet,
+ length);
}
} // namespace rtcp
} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_packet.h b/modules/rtp_rtcp/source/rtcp_packet.h
index 641bd7fd..f60e848b 100644
--- a/modules/rtp_rtcp/source/rtcp_packet.h
+++ b/modules/rtp_rtcp/source/rtcp_packet.h
@@ -12,6 +12,8 @@
#ifndef WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_
#define WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_
+#include <map>
+#include <string>
#include <vector>
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
@@ -21,8 +23,10 @@
namespace webrtc {
namespace rtcp {
+enum { kCommonFbFmtLength = 12 };
+enum { kReportBlockLength = 24 };
+
class RawPacket;
-class ReportBlock;
// Class for building RTCP packets.
//
@@ -40,9 +44,9 @@ class ReportBlock;
// fir.To(234)
// fir.WithCommandSeqNum(123);
//
-// uint16_t len = 0; // Builds an intra frame request
+// size_t length = 0; // Builds an intra frame request
// uint8_t packet[kPacketSize]; // with sequence number 123.
-// fir.Build(packet, &len, kPacketSize);
+// fir.Build(packet, &length, kPacketSize);
//
// RawPacket packet = fir.Build(); // Returns a RawPacket holding
// // the built rtcp packet.
@@ -59,18 +63,20 @@ class RtcpPacket {
RawPacket Build() const;
- void Build(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ void Build(uint8_t* packet, size_t* length, size_t max_length) const;
protected:
- RtcpPacket() {}
+ RtcpPacket() : kHeaderLength(4) {}
virtual void Create(
- uint8_t* packet, uint16_t* len, uint16_t max_len) const = 0;
+ uint8_t* packet, size_t* length, size_t max_length) const = 0;
- void CreateAndAddAppended(
- uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ const size_t kHeaderLength;
private:
+ void CreateAndAddAppended(
+ uint8_t* packet, size_t* length, size_t max_length) const;
+
std::vector<RtcpPacket*> appended_packets_;
};
@@ -81,11 +87,66 @@ class Empty : public RtcpPacket {
virtual ~Empty() {}
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ virtual void Create(uint8_t* packet, size_t* length, size_t max_length) const;
};
-//// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
+// 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
@@ -109,8 +170,7 @@ class Empty : public RtcpPacket {
class SenderReport : public RtcpPacket {
public:
- SenderReport()
- : RtcpPacket() {
+ SenderReport() : RtcpPacket() {
memset(&sr_, 0, sizeof(sr_));
}
@@ -136,20 +196,22 @@ class SenderReport : public RtcpPacket {
}
void WithReportBlock(ReportBlock* block);
- enum { kMaxNumberOfReportBlocks = 0x1f };
-
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- uint16_t Length() const {
- const uint16_t kSrBlockLen = 28;
- const uint16_t kReportBlockLen = 24;
- return kSrBlockLen + report_blocks_.size() * kReportBlockLen;
+ enum { 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_;
+ std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
};
//
@@ -167,8 +229,7 @@ class SenderReport : public RtcpPacket {
class ReceiverReport : public RtcpPacket {
public:
- ReceiverReport()
- : RtcpPacket() {
+ ReceiverReport() : RtcpPacket() {
memset(&rr_, 0, sizeof(rr_));
}
@@ -179,75 +240,117 @@ class ReceiverReport : public RtcpPacket {
}
void WithReportBlock(ReportBlock* block);
- enum { kMaxNumberOfReportBlocks = 0x1f };
-
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- uint16_t Length() const {
- const uint16_t kRrBlockLen = 8;
- const uint16_t kReportBlockLen = 24;
- return kRrBlockLen + report_blocks_.size() * kReportBlockLen;
+ enum { kMaxNumberOfReportBlocks = 0x1f };
+
+ size_t BlockLength() const {
+ const size_t kRrHeaderLength = 8;
+ return kRrHeaderLength + report_blocks_.size() * kReportBlockLength;
}
RTCPUtility::RTCPPacketRR rr_;
- std::vector<ReportBlock*> report_blocks_;
+ std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
};
+// Transmission Time Offsets in RTP Streams (RFC 5450).
//
-// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// hdr |V=2|P| RC | PT=IJ=195 | length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | inter-arrival jitter |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// . .
+// . .
+// . .
+// | inter-arrival jitter |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
-// 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) |
-// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+// If present, this RTCP packet must be placed after a receiver report
+// (inside a compound RTCP packet), and MUST have the same value for RC
+// (reception report count) as the receiver report.
-class ReportBlock {
+class Ij : public RtcpPacket {
public:
- ReportBlock() {
- memset(&report_block_, 0, sizeof(report_block_));
- }
+ Ij() : RtcpPacket() {}
- ~ReportBlock() {}
+ virtual ~Ij() {}
- void To(uint32_t ssrc) {
- report_block_.SSRC = ssrc;
- }
- void WithFractionLost(uint8_t fraction_lost) {
- report_block_.FractionLost = fraction_lost;
- }
- void WithCumPacketsLost(uint32_t cum_packets_lost) {
- report_block_.CumulativeNumOfPacketsLost = cum_packets_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;
+ void WithJitterItem(uint32_t jitter);
+
+ protected:
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
+
+ private:
+ enum { kMaxNumberOfIjItems = 0x1f };
+
+ size_t BlockLength() const {
+ return kHeaderLength + 4 * ij_items_.size();
}
- void Create(uint8_t* packet, uint16_t* len) const;
+ std::vector<uint32_t> ij_items_;
+
+ DISALLOW_COPY_AND_ASSIGN(Ij);
+};
+
+// Source Description (SDES) (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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// header |V=2|P| SC | PT=SDES=202 | length |
+// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+// chunk | SSRC/CSRC_1 |
+// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | SDES items |
+// | ... |
+// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+// chunk | SSRC/CSRC_2 |
+// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | SDES items |
+// | ... |
+// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// Canonical End-Point Identifier SDES Item (CNAME)
+//
+// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | CNAME=1 | length | user and domain name ...
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+class Sdes : public RtcpPacket {
+ public:
+ Sdes() : RtcpPacket() {}
+
+ virtual ~Sdes() {}
+
+ void WithCName(uint32_t ssrc, std::string cname);
+
+ struct Chunk {
+ uint32_t ssrc;
+ std::string name;
+ int null_octets;
+ };
+
+ protected:
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- RTCPUtility::RTCPPacketReportBlockItem report_block_;
+ enum { kMaxNumberOfChunks = 0x1f };
+
+ size_t BlockLength() const;
+
+ std::vector<Chunk> chunks_;
+
+ DISALLOW_COPY_AND_ASSIGN(Sdes);
};
//
@@ -266,8 +369,7 @@ class ReportBlock {
class Bye : public RtcpPacket {
public:
- Bye()
- : RtcpPacket() {
+ Bye() : RtcpPacket() {
memset(&bye_, 0, sizeof(bye_));
}
@@ -278,21 +380,79 @@ class Bye : public RtcpPacket {
}
void WithCsrc(uint32_t csrc);
- enum { kMaxNumberOfCsrcs = 0x1f - 1 };
-
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- uint16_t Length() const {
- const uint16_t kByeBlockLen = 8 + 4 * csrcs_.size();
- return kByeBlockLen;
+ enum { kMaxNumberOfCsrcs = 0x1f - 1 };
+
+ size_t BlockLength() const {
+ size_t source_count = 1 + csrcs_.size();
+ return kHeaderLength + 4 * source_count;
}
RTCPUtility::RTCPPacketBYE bye_;
std::vector<uint32_t> csrcs_;
};
+// Application-Defined packet (APP) (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| subtype | PT=APP=204 | length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | SSRC/CSRC |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | name (ASCII) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | application-dependent data ...
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+class App : public RtcpPacket {
+ public:
+ App()
+ : RtcpPacket(),
+ ssrc_(0) {
+ memset(&app_, 0, sizeof(app_));
+ }
+
+ virtual ~App() {}
+
+ void From(uint32_t ssrc) {
+ ssrc_ = ssrc;
+ }
+ void WithSubType(uint8_t subtype) {
+ assert(subtype <= 0x1f);
+ app_.SubType = subtype;
+ }
+ void WithName(uint32_t name) {
+ app_.Name = name;
+ }
+ void WithData(const uint8_t* data, uint16_t data_length) {
+ assert(data);
+ assert(data_length <= kRtcpAppCode_DATA_SIZE);
+ assert(data_length % 4 == 0);
+ memcpy(app_.Data, data, data_length);
+ app_.Size = data_length;
+ }
+
+ protected:
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
+
+ private:
+ size_t BlockLength() const {
+ return 12 + app_.Size;
+ }
+
+ uint32_t ssrc_;
+ RTCPUtility::RTCPPacketAPP app_;
+
+ DISALLOW_COPY_AND_ASSIGN(App);
+};
+
// RFC 4585: Feedback format.
//
// Common packet format:
@@ -309,6 +469,92 @@ class Bye : public RtcpPacket {
// : Feedback Control Information (FCI) :
// :
+// Picture loss indication (PLI) (RFC 4585).
+//
+// FCI: no feedback control information.
+
+class Pli : public RtcpPacket {
+ public:
+ Pli() : RtcpPacket() {
+ memset(&pli_, 0, sizeof(pli_));
+ }
+
+ virtual ~Pli() {}
+
+ void From(uint32_t ssrc) {
+ pli_.SenderSSRC = ssrc;
+ }
+ void To(uint32_t ssrc) {
+ pli_.MediaSSRC = ssrc;
+ }
+
+ protected:
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
+
+ private:
+ size_t BlockLength() const {
+ return kCommonFbFmtLength;
+ }
+
+ RTCPUtility::RTCPPacketPSFBPLI pli_;
+
+ DISALLOW_COPY_AND_ASSIGN(Pli);
+};
+
+// Slice loss indication (SLI) (RFC 4585).
+//
+// FCI:
+// 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 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+class Sli : public RtcpPacket {
+ public:
+ Sli() : RtcpPacket() {
+ memset(&sli_, 0, sizeof(sli_));
+ memset(&sli_item_, 0, sizeof(sli_item_));
+ }
+
+ virtual ~Sli() {}
+
+ void From(uint32_t ssrc) {
+ sli_.SenderSSRC = ssrc;
+ }
+ void To(uint32_t ssrc) {
+ sli_.MediaSSRC = ssrc;
+ }
+ void WithFirstMb(uint16_t first_mb) {
+ assert(first_mb <= 0x1fff);
+ sli_item_.FirstMB = first_mb;
+ }
+ void WithNumberOfMb(uint16_t number_mb) {
+ assert(number_mb <= 0x1fff);
+ sli_item_.NumberOfMB = number_mb;
+ }
+ void WithPictureId(uint8_t picture_id) {
+ assert(picture_id <= 0x3f);
+ sli_item_.PictureId = picture_id;
+ }
+
+ protected:
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
+
+ private:
+ size_t BlockLength() const {
+ const size_t kFciLength = 4;
+ return kCommonFbFmtLength + kFciLength;
+ }
+
+ RTCPUtility::RTCPPacketPSFBSLI sli_;
+ RTCPUtility::RTCPPacketPSFBSLIItem sli_item_;
+
+ DISALLOW_COPY_AND_ASSIGN(Sli);
+};
+
// Generic NACK (RFC 4585).
//
// FCI:
@@ -320,8 +566,7 @@ class Bye : public RtcpPacket {
class Nack : public RtcpPacket {
public:
- Nack()
- : RtcpPacket() {
+ Nack() : RtcpPacket() {
memset(&nack_, 0, sizeof(nack_));
}
@@ -336,13 +581,13 @@ class Nack : public RtcpPacket {
void WithList(const uint16_t* nack_list, int length);
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const
- OVERRIDE;
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- uint16_t Length() const {
- const uint16_t kNackBlockLen = 4 * (3 + nack_fields_.size());
- return kNackBlockLen;
+ size_t BlockLength() const {
+ size_t fci_length = 4 * nack_fields_.size();
+ return kCommonFbFmtLength + fci_length;
}
RTCPUtility::RTCPPacketRTPFBNACK nack_;
@@ -366,8 +611,8 @@ class Nack : public RtcpPacket {
class Rpsi : public RtcpPacket {
public:
Rpsi()
- : RtcpPacket(),
- padding_bytes_(0) {
+ : RtcpPacket(),
+ padding_bytes_(0) {
memset(&rpsi_, 0, sizeof(rpsi_));
}
@@ -386,14 +631,13 @@ class Rpsi : public RtcpPacket {
void WithPictureId(uint64_t picture_id);
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const
- OVERRIDE;
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- uint16_t Length() const {
- const uint16_t kRpsiBlockLen =
- 12 + 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
- return kRpsiBlockLen;
+ size_t BlockLength() const {
+ size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
+ return kCommonFbFmtLength + fci_length;
}
uint8_t padding_bytes_;
@@ -417,7 +661,7 @@ class Rpsi : public RtcpPacket {
class Fir : public RtcpPacket {
public:
Fir()
- : RtcpPacket() {
+ : RtcpPacket() {
memset(&fir_, 0, sizeof(fir_));
memset(&fir_item_, 0, sizeof(fir_item_));
}
@@ -435,12 +679,13 @@ class Fir : public RtcpPacket {
}
protected:
- virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
+ virtual void Create(
+ uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
private:
- uint16_t Length() const {
- const uint16_t kFirBlockLen = 20;
- return kFirBlockLen;
+ size_t BlockLength() const {
+ const size_t kFciLength = 8;
+ return kCommonFbFmtLength + kFciLength;
}
RTCPUtility::RTCPPacketPSFBFIR fir_;
@@ -450,7 +695,7 @@ class Fir : public RtcpPacket {
// Class holding a RTCP packet.
//
// Takes a built rtcp packet.
-// RawPacket raw_packet(buffer, len);
+// RawPacket raw_packet(buffer, length);
//
// To access the raw packet:
// raw_packet.buffer(); - pointer to the raw packet
@@ -458,22 +703,22 @@ class Fir : public RtcpPacket {
class RawPacket {
public:
- RawPacket(const uint8_t* buffer, uint16_t len) {
- assert(len <= IP_PACKET_SIZE);
- memcpy(packet_, buffer, len);
- packet_length_ = len;
+ RawPacket(const uint8_t* packet, size_t length) {
+ assert(length <= IP_PACKET_SIZE);
+ memcpy(buffer_, packet, length);
+ buffer_length_ = length;
}
const uint8_t* buffer() {
- return packet_;
+ return buffer_;
}
- uint16_t buffer_length() const {
- return packet_length_;
+ size_t buffer_length() const {
+ return buffer_length_;
}
private:
- uint16_t packet_length_;
- uint8_t packet_[IP_PACKET_SIZE];
+ size_t buffer_length_;
+ uint8_t buffer_[IP_PACKET_SIZE];
};
} // namespace rtcp
diff --git a/modules/rtp_rtcp/source/rtcp_packet_unittest.cc b/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
index d7ae9142..aa25c2e5 100644
--- a/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
@@ -15,16 +15,21 @@
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
#include "webrtc/test/rtcp_packet_parser.h"
+using webrtc::rtcp::App;
using webrtc::rtcp::Bye;
using webrtc::rtcp::Empty;
using webrtc::rtcp::Fir;
+using webrtc::rtcp::Ij;
using webrtc::rtcp::Nack;
+using webrtc::rtcp::Pli;
+using webrtc::rtcp::Sdes;
+using webrtc::rtcp::SenderReport;
+using webrtc::rtcp::Sli;
using webrtc::rtcp::RawPacket;
using webrtc::rtcp::ReceiverReport;
using webrtc::rtcp::ReportBlock;
using webrtc::rtcp::Rpsi;
using webrtc::test::RtcpPacketParser;
-using webrtc::rtcp::SenderReport;
namespace webrtc {
@@ -47,7 +52,7 @@ TEST(RtcpPacketTest, RrWithOneReportBlock) {
ReportBlock rb;
rb.To(kRemoteSsrc);
rb.WithFractionLost(55);
- rb.WithCumPacketsLost(0x111111);
+ rb.WithCumulativeLost(0x111111);
rb.WithExtHighestSeqNum(0x22222222);
rb.WithJitter(0x33333333);
rb.WithLastSr(0x44444444);
@@ -154,6 +159,164 @@ TEST(RtcpPacketTest, SrWithTwoReportBlocks) {
EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc + 1));
}
+TEST(RtcpPacketTest, IjNoItem) {
+ Ij ij;
+
+ RawPacket packet = ij.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.ij()->num_packets());
+ EXPECT_EQ(0, parser.ij_item()->num_packets());
+}
+
+TEST(RtcpPacketTest, IjOneItem) {
+ Ij ij;
+ ij.WithJitterItem(0x11111111);
+
+ RawPacket packet = ij.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.ij()->num_packets());
+ EXPECT_EQ(1, parser.ij_item()->num_packets());
+ EXPECT_EQ(0x11111111U, parser.ij_item()->Jitter());
+}
+
+TEST(RtcpPacketTest, IjTwoItems) {
+ Ij ij;
+ ij.WithJitterItem(0x11111111);
+ ij.WithJitterItem(0x22222222);
+
+ RawPacket packet = ij.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.ij()->num_packets());
+ EXPECT_EQ(2, parser.ij_item()->num_packets());
+ EXPECT_EQ(0x22222222U, parser.ij_item()->Jitter());
+}
+
+TEST(RtcpPacketTest, AppWithNoData) {
+ App app;
+ app.WithSubType(30);
+ uint32_t name = 'n' << 24;
+ name += 'a' << 16;
+ name += 'm' << 8;
+ name += 'e';
+ app.WithName(name);
+
+ RawPacket packet = app.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_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);
+
+ RawPacket packet = app.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_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, SdesWithOneChunk) {
+ Sdes sdes;
+ sdes.WithCName(kSenderSsrc, "alice@host");
+
+ RawPacket packet = sdes.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.sdes()->num_packets());
+ EXPECT_EQ(1, parser.sdes_chunk()->num_packets());
+ EXPECT_EQ(kSenderSsrc, parser.sdes_chunk()->Ssrc());
+ EXPECT_EQ("alice@host", parser.sdes_chunk()->Cname());
+}
+
+TEST(RtcpPacketTest, SdesWithMultipleChunks) {
+ Sdes sdes;
+ sdes.WithCName(kSenderSsrc, "a");
+ sdes.WithCName(kSenderSsrc + 1, "ab");
+ sdes.WithCName(kSenderSsrc + 2, "abc");
+ sdes.WithCName(kSenderSsrc + 3, "abcd");
+ sdes.WithCName(kSenderSsrc + 4, "abcde");
+ sdes.WithCName(kSenderSsrc + 5, "abcdef");
+
+ RawPacket packet = sdes.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.sdes()->num_packets());
+ EXPECT_EQ(6, parser.sdes_chunk()->num_packets());
+ EXPECT_EQ(kSenderSsrc + 5, parser.sdes_chunk()->Ssrc());
+ EXPECT_EQ("abcdef", parser.sdes_chunk()->Cname());
+}
+
+TEST(RtcpPacketTest, CnameItemWithEmptyString) {
+ Sdes sdes;
+ sdes.WithCName(kSenderSsrc, "");
+
+ RawPacket packet = sdes.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.sdes()->num_packets());
+ EXPECT_EQ(1, parser.sdes_chunk()->num_packets());
+ EXPECT_EQ(kSenderSsrc, parser.sdes_chunk()->Ssrc());
+ EXPECT_EQ("", parser.sdes_chunk()->Cname());
+}
+
+TEST(RtcpPacketTest, Pli) {
+ Pli pli;
+ pli.From(kSenderSsrc);
+ pli.To(kRemoteSsrc);
+
+ RawPacket packet = pli.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.pli()->num_packets());
+ EXPECT_EQ(kSenderSsrc, parser.pli()->Ssrc());
+ EXPECT_EQ(kRemoteSsrc, parser.pli()->MediaSsrc());
+}
+
+TEST(RtcpPacketTest, Sli) {
+ const uint16_t kFirstMb = 7777;
+ const uint16_t kNumberOfMb = 6666;
+ const uint8_t kPictureId = 60;
+ Sli sli;
+ sli.From(kSenderSsrc);
+ sli.To(kRemoteSsrc);
+ sli.WithFirstMb(kFirstMb);
+ sli.WithNumberOfMb(kNumberOfMb);
+ sli.WithPictureId(kPictureId);
+
+ RawPacket packet = sli.Build();
+ RtcpPacketParser parser;
+ parser.Parse(packet.buffer(), packet.buffer_length());
+ EXPECT_EQ(1, parser.sli()->num_packets());
+ EXPECT_EQ(kSenderSsrc, parser.sli()->Ssrc());
+ EXPECT_EQ(kRemoteSsrc, parser.sli()->MediaSsrc());
+ EXPECT_EQ(1, parser.sli_item()->num_packets());
+ EXPECT_EQ(kFirstMb, parser.sli_item()->FirstMb());
+ EXPECT_EQ(kNumberOfMb, parser.sli_item()->NumberOfMb());
+ EXPECT_EQ(kPictureId, parser.sli_item()->PictureId());
+}
+
TEST(RtcpPacketTest, Nack) {
Nack nack;
const uint16_t kList[] = {0, 1, 3, 8, 16};
@@ -373,11 +536,11 @@ TEST(RtcpPacketTest, BuildWithInputBuffer) {
rr.WithReportBlock(&rb);
rr.Append(&fir);
- const uint16_t kRrLength = 8;
- const uint16_t kReportBlockLength = 24;
- const uint16_t kFirLength = 20;
+ const size_t kRrLength = 8;
+ const size_t kReportBlockLength = 24;
+ const size_t kFirLength = 20;
- uint16_t len = 0;
+ size_t len = 0;
uint8_t packet[kRrLength + kReportBlockLength + kFirLength];
rr.Build(packet, &len, kRrLength + kReportBlockLength + kFirLength);
@@ -394,16 +557,16 @@ TEST(RtcpPacketTest, BuildWithTooSmallBuffer) {
rr.From(kSenderSsrc);
rr.WithReportBlock(&rb);
- const uint16_t kRrLength = 8;
- const uint16_t kReportBlockLength = 24;
+ const size_t kRrLength = 8;
+ const size_t kReportBlockLength = 24;
// No packet.
- uint16_t len = 0;
+ size_t len = 0;
uint8_t packet[kRrLength + kReportBlockLength - 1];
rr.Build(packet, &len, kRrLength + kReportBlockLength - 1);
RtcpPacketParser parser;
parser.Parse(packet, len);
- EXPECT_EQ(0, len);
+ EXPECT_EQ(0U, len);
}
TEST(RtcpPacketTest, BuildWithTooSmallBuffer_LastBlockFits) {
@@ -414,10 +577,10 @@ TEST(RtcpPacketTest, BuildWithTooSmallBuffer_LastBlockFits) {
rr.WithReportBlock(&rb);
rr.Append(&fir);
- const uint16_t kRrLength = 8;
- const uint16_t kReportBlockLength = 24;
+ const size_t kRrLength = 8;
+ const size_t kReportBlockLength = 24;
- uint16_t len = 0;
+ size_t len = 0;
uint8_t packet[kRrLength + kReportBlockLength - 1];
rr.Build(packet, &len, kRrLength + kReportBlockLength - 1);
RtcpPacketParser parser;
diff --git a/test/rtcp_packet_parser.cc b/test/rtcp_packet_parser.cc
index 9ae8543d..69c50d1b 100644
--- a/test/rtcp_packet_parser.cc
+++ b/test/rtcp_packet_parser.cc
@@ -30,13 +30,40 @@ void RtcpPacketParser::Parse(const void *data, int len) {
case RTCPUtility::kRtcpRrCode:
receiver_report_.Set(parser.Packet().RR);
break;
- case RTCPUtility::kRtcpByeCode:
- bye_.Set(parser.Packet().BYE);
- break;
case RTCPUtility::kRtcpReportBlockItemCode:
report_block_.Set(parser.Packet().ReportBlockItem);
++report_blocks_per_ssrc_[parser.Packet().ReportBlockItem.SSRC];
break;
+ case RTCPUtility::kRtcpSdesCode:
+ sdes_.Set();
+ break;
+ case RTCPUtility::kRtcpSdesChunkCode:
+ sdes_chunk_.Set(parser.Packet().CName);
+ break;
+ case RTCPUtility::kRtcpByeCode:
+ bye_.Set(parser.Packet().BYE);
+ break;
+ case RTCPUtility::kRtcpAppCode:
+ app_.Set(parser.Packet().APP);
+ break;
+ case RTCPUtility::kRtcpAppItemCode:
+ app_item_.Set(parser.Packet().APP);
+ break;
+ case RTCPUtility::kRtcpExtendedIjCode:
+ ij_.Set();
+ break;
+ case RTCPUtility::kRtcpExtendedIjItemCode:
+ ij_item_.Set(parser.Packet().ExtendedJitterReportItem);
+ break;
+ case RTCPUtility::kRtcpPsfbPliCode:
+ pli_.Set(parser.Packet().PLI);
+ break;
+ case RTCPUtility::kRtcpPsfbSliCode:
+ sli_.Set(parser.Packet().SLI);
+ break;
+ case RTCPUtility::kRtcpPsfbSliItemCode:
+ sli_item_.Set(parser.Packet().SLIItem);
+ break;
case RTCPUtility::kRtcpPsfbRpsiCode:
rpsi_.Set(parser.Packet().RPSI);
break;
diff --git a/test/rtcp_packet_parser.h b/test/rtcp_packet_parser.h
index 4db58c35..a09674f3 100644
--- a/test/rtcp_packet_parser.h
+++ b/test/rtcp_packet_parser.h
@@ -13,6 +13,7 @@
#define WEBRTC_TEST_RTCP_PACKET_PARSER_H_
#include <map>
+#include <string>
#include <vector>
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
@@ -100,6 +101,65 @@ class ReportBlock : public PacketType {
RTCPUtility::RTCPPacketReportBlockItem rb_;
};
+class Ij : public PacketType {
+ public:
+ Ij() {}
+ virtual ~Ij() {}
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set() { ++num_packets_; }
+};
+
+class IjItem : public PacketType {
+ public:
+ IjItem() {}
+ virtual ~IjItem() {}
+
+ uint32_t Jitter() const { return ij_item_.Jitter; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketExtendedJitterReportItem& ij_item) {
+ ij_item_ = ij_item;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketExtendedJitterReportItem ij_item_;
+};
+
+class Sdes : public PacketType {
+ public:
+ Sdes() {}
+ virtual ~Sdes() {}
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set() { ++num_packets_; }
+};
+
+class SdesChunk : public PacketType {
+ public:
+ SdesChunk() {}
+ virtual ~SdesChunk() {}
+
+ uint32_t Ssrc() const { return cname_.SenderSSRC; }
+ std::string Cname() const { return cname_.CName; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketSDESCName& cname) {
+ cname_ = cname;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketSDESCName cname_;
+};
+
class Bye : public PacketType {
public:
Bye() {}
@@ -140,6 +200,102 @@ class Rpsi : public PacketType {
RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
};
+class App : public PacketType {
+ public:
+ App() {}
+ virtual ~App() {}
+
+ uint8_t SubType() const { return app_.SubType; }
+ uint32_t Name() const { return app_.Name; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketAPP& app) {
+ app_ = app;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketAPP app_;
+};
+
+class AppItem : public PacketType {
+ public:
+ AppItem() {}
+ virtual ~AppItem() {}
+
+ uint8_t* Data() { return app_item_.Data; }
+ uint16_t DataLength() const { return app_item_.Size; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketAPP& app) {
+ app_item_ = app;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketAPP app_item_;
+};
+
+class Pli : public PacketType {
+ public:
+ Pli() {}
+ virtual ~Pli() {}
+
+ uint32_t Ssrc() const { return pli_.SenderSSRC; }
+ uint32_t MediaSsrc() const { return pli_.MediaSSRC; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketPSFBPLI& pli) {
+ pli_ = pli;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketPSFBPLI pli_;
+};
+
+class Sli : public PacketType {
+ public:
+ Sli() {}
+ virtual ~Sli() {}
+
+ uint32_t Ssrc() const { return sli_.SenderSSRC; }
+ uint32_t MediaSsrc() const { return sli_.MediaSSRC; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketPSFBSLI& sli) {
+ sli_ = sli;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketPSFBSLI sli_;
+};
+
+class SliItem : public PacketType {
+ public:
+ SliItem() {}
+ virtual ~SliItem() {}
+
+ uint16_t FirstMb() const { return sli_item_.FirstMB; }
+ uint16_t NumberOfMb() const { return sli_item_.NumberOfMB; }
+ uint8_t PictureId() const { return sli_item_.PictureId; }
+
+ private:
+ friend class RtcpPacketParser;
+
+ void Set(const RTCPUtility::RTCPPacketPSFBSLIItem& sli_item) {
+ sli_item_ = sli_item;
+ ++num_packets_;
+ }
+
+ RTCPUtility::RTCPPacketPSFBSLIItem sli_item_;
+};
+
class Fir : public PacketType {
public:
Fir() {}
@@ -232,7 +388,16 @@ class RtcpPacketParser {
SenderReport* sender_report() { return &sender_report_; }
ReceiverReport* receiver_report() { return &receiver_report_; }
ReportBlock* report_block() { return &report_block_; }
+ Sdes* sdes() { return &sdes_; }
+ SdesChunk* sdes_chunk() { return &sdes_chunk_; }
Bye* bye() { return &bye_; }
+ App* app() { return &app_; }
+ AppItem* app_item() { return &app_item_; }
+ Ij* ij() { return &ij_; }
+ IjItem* ij_item() { return &ij_item_; }
+ Pli* pli() { return &pli_; }
+ Sli* sli() { return &sli_; }
+ SliItem* sli_item() { return &sli_item_; }
Rpsi* rpsi() { return &rpsi_; }
Fir* fir() { return &fir_; }
FirItem* fir_item() { return &fir_item_; }
@@ -247,7 +412,16 @@ class RtcpPacketParser {
SenderReport sender_report_;
ReceiverReport receiver_report_;
ReportBlock report_block_;
+ Sdes sdes_;
+ SdesChunk sdes_chunk_;
Bye bye_;
+ App app_;
+ AppItem app_item_;
+ Ij ij_;
+ IjItem ij_item_;
+ Pli pli_;
+ Sli sli_;
+ SliItem sli_item_;
Rpsi rpsi_;
Fir fir_;
FirItem fir_item_;