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@6449 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -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 Bye::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
|
||||
if (*len + Length() > max_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;
|
||||
}
|
||||
CreateBye(bye_, csrcs_, BlockToHeaderLength(Length()), packet, len);
|
||||
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);
|
||||
}
|
||||
|
||||
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(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 {
|
||||
assert(!nack_fields_.empty());
|
||||
if (*len + Length() > max_len) {
|
||||
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;
|
||||
}
|
||||
CreateNack(nack_, nack_fields_, BlockToHeaderLength(Length()), packet, len);
|
||||
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 (*length + BlockLength() > max_length) {
|
||||
LOG(LS_WARNING) << "Max packet size reached.";
|
||||
return;
|
||||
}
|
||||
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
|
||||
|
Reference in New Issue
Block a user