Add packetization and coding/decoding of feedback message format.

BUG=webrtc:4312
R=stefan@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#9651}
This commit is contained in:
Erik Språng
2015-07-29 10:46:54 +02:00
parent f1828e8ed9
commit a3b8769860
9 changed files with 1442 additions and 90 deletions

View File

@ -92,34 +92,6 @@ void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,
*mantissa = (input_base10 >> exponent);
}
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);
return (length_in_bytes / 4) - 1;
}
// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
//
// RTP header format.
// 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/FMT | PT | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
void CreateHeader(uint8_t count_or_format, // Depends on packet type.
uint8_t packet_type,
size_t length,
uint8_t* buffer,
size_t* pos) {
assert(length <= 0xffff);
const uint8_t kVersion = 2;
AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
AssignUWord8(buffer, pos, packet_type);
AssignUWord16(buffer, pos, length);
}
// 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
@ -140,10 +112,8 @@ void CreateHeader(uint8_t count_or_format, // Depends on packet type.
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
void CreateSenderReport(const RTCPPacketSR& sr,
size_t length,
uint8_t* buffer,
size_t* pos) {
CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
AssignUWord32(buffer, pos, sr.SenderSSRC);
AssignUWord32(buffer, pos, sr.NTPMostSignificant);
AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
@ -162,10 +132,8 @@ void CreateSenderReport(const RTCPPacketSR& sr,
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
void CreateReceiverReport(const RTCPPacketRR& rr,
size_t length,
uint8_t* buffer,
size_t* pos) {
CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
AssignUWord32(buffer, pos, rr.SenderSSRC);
}
@ -219,12 +187,8 @@ void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
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);
}
for (uint32_t item : ij_items)
AssignUWord32(buffer, pos, item);
}
// Source Description (SDES) (RFC 3550).
@ -254,10 +218,8 @@ void CreateIj(const std::vector<uint32_t>& ij_items,
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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) {
@ -286,10 +248,8 @@ void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
void CreateBye(const RTCPPacketBYE& bye,
const std::vector<uint32_t>& csrcs,
size_t length,
uint8_t* buffer,
size_t* pos) {
CreateHeader(length, PT_BYE, length, buffer, pos);
AssignUWord32(buffer, pos, bye.SenderSSRC);
for (uint32_t csrc : csrcs)
AssignUWord32(buffer, pos, csrc);
@ -311,10 +271,8 @@ void CreateBye(const RTCPPacketBYE& bye,
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);
@ -343,11 +301,8 @@ void CreateApp(const RTCPPacketAPP& app,
// 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);
}
@ -364,11 +319,8 @@ void CreatePli(const RTCPPacketPSFBPLI& pli,
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);
@ -393,11 +345,8 @@ void CreateNack(const RTCPPacketRTPFBNACK& nack,
const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
size_t start_index,
size_t end_index,
size_t length,
uint8_t* buffer,
size_t* pos) {
const uint8_t kFmt = 1;
CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
AssignUWord32(buffer, pos, nack.SenderSSRC);
AssignUWord32(buffer, pos, nack.MediaSSRC);
for (size_t i = start_index; i < end_index; ++i) {
@ -421,13 +370,10 @@ void CreateNack(const RTCPPacketRTPFBNACK& nack,
void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
uint8_t padding_bytes,
size_t length,
uint8_t* buffer,
size_t* pos) {
// Native bit string should be a multiple of 8 bits.
assert(rpsi.NumberOfValidBits % 8 == 0);
const uint8_t kFmt = 3;
CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
AssignUWord32(buffer, pos, rpsi.SenderSSRC);
AssignUWord32(buffer, pos, rpsi.MediaSSRC);
AssignUWord8(buffer, pos, padding_bytes * 8);
@ -452,11 +398,8 @@ void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
void CreateFir(const RTCPPacketPSFBFIR& fir,
const RTCPPacketPSFBFIRItem& fir_item,
size_t length,
uint8_t* buffer,
size_t* pos) {
const uint8_t kFmt = 4;
CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
AssignUWord32(buffer, pos, fir.SenderSSRC);
AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
AssignUWord32(buffer, pos, fir_item.SSRC);
@ -494,11 +437,8 @@ void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr,
const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
size_t length,
uint8_t* buffer,
size_t* pos) {
const uint8_t kFmt = 3;
CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
AssignUWord32(buffer, pos, tmmbr.SenderSSRC);
AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
CreateTmmbrItem(tmmbr_item, buffer, pos);
@ -518,11 +458,8 @@ void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr,
void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn,
const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items,
size_t length,
uint8_t* buffer,
size_t* pos) {
const uint8_t kFmt = 4;
CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
AssignUWord32(buffer, pos, tmmbn.SenderSSRC);
AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
for (uint8_t i = 0; i < tmmbn_items.size(); ++i) {
@ -551,15 +488,12 @@ void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn,
void CreateRemb(const RTCPPacketPSFBAPP& remb,
const RTCPPacketPSFBREMBItem& remb_item,
size_t length,
uint8_t* buffer,
size_t* pos) {
uint32_t mantissa = 0;
uint8_t exp = 0;
ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp);
const uint8_t kFmt = 15;
CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
AssignUWord32(buffer, pos, remb.SenderSSRC);
AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
AssignUWord8(buffer, pos, 'R');
@ -590,10 +524,8 @@ void CreateRemb(const RTCPPacketPSFBAPP& remb,
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
void CreateXrHeader(const RTCPPacketXR& header,
size_t length,
uint8_t* buffer,
size_t* pos) {
CreateHeader(0U, PT_XR, length, buffer, pos);
AssignUWord32(buffer, pos, header.OriginatorSSRC);
}
@ -790,6 +722,35 @@ bool RtcpPacket::OnBufferFull(uint8_t* packet,
return true;
}
size_t RtcpPacket::HeaderLength() const {
size_t length_in_bytes = BlockLength();
// Length in 32-bit words minus 1.
assert(length_in_bytes > 0);
return ((length_in_bytes + 3) / 4) - 1;
}
// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
//
// RTP header format.
// 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/FMT | PT | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
void RtcpPacket::CreateHeader(
uint8_t count_or_format, // Depends on packet type.
uint8_t packet_type,
size_t length,
uint8_t* buffer,
size_t* pos) const {
assert(length <= 0xffff);
const uint8_t kVersion = 2;
AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
AssignUWord8(buffer, pos, packet_type);
AssignUWord16(buffer, pos, length);
}
bool Empty::Create(uint8_t* packet,
size_t* index,
size_t max_length,
@ -797,6 +758,10 @@ bool Empty::Create(uint8_t* packet,
return true;
}
size_t Empty::BlockLength() const {
return 0;
}
bool SenderReport::Create(uint8_t* packet,
size_t* index,
size_t max_length,
@ -805,7 +770,8 @@ bool SenderReport::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, index);
CreateHeader(sr_.NumberOfReportBlocks, PT_SR, HeaderLength(), packet, index);
CreateSenderReport(sr_, packet, index);
CreateReportBlocks(report_blocks_, packet, index);
return true;
}
@ -828,7 +794,8 @@ bool ReceiverReport::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, index);
CreateHeader(rr_.NumberOfReportBlocks, PT_RR, HeaderLength(), packet, index);
CreateReceiverReport(rr_, packet, index);
CreateReportBlocks(report_blocks_, packet, index);
return true;
}
@ -851,6 +818,8 @@ bool Ij::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
size_t length = ij_items_.size();
CreateHeader(length, PT_IJ, length, packet, index);
CreateIj(ij_items_, packet, index);
return true;
}
@ -873,7 +842,8 @@ bool Sdes::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, index);
CreateHeader(chunks_.size(), PT_SDES, HeaderLength(), packet, index);
CreateSdes(chunks_, packet, index);
return true;
}
@ -914,7 +884,9 @@ bool Bye::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, index);
size_t length = HeaderLength();
CreateHeader(length, PT_BYE, length, packet, index);
CreateBye(bye_, csrcs_, packet, index);
return true;
}
@ -935,7 +907,8 @@ bool App::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, index);
CreateHeader(app_.SubType, PT_APP, HeaderLength(), packet, index);
CreateApp(app_, ssrc_, packet, index);
return true;
}
@ -947,7 +920,9 @@ bool Pli::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, index);
const uint8_t kFmt = 1;
CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
CreatePli(pli_, packet, index);
return true;
}
@ -959,7 +934,9 @@ bool Sli::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet, index);
const uint8_t kFmt = 2;
CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
CreateSli(sli_, sli_item_, packet, index);
return true;
}
@ -981,8 +958,11 @@ bool Nack::Create(uint8_t* packet,
std::min((bytes_left_in_buffer - kCommonFbFmtLength) / 4,
nack_fields_.size() - nack_index);
const uint8_t kFmt = 1;
size_t size_bytes = (num_nack_fields * 4) + kCommonFbFmtLength;
size_t header_length = ((size_bytes + 3) / 4) - 1; // As 32bit words - 1
CreateHeader(kFmt, PT_RTPFB, header_length, packet, index);
CreateNack(nack_, nack_fields_, nack_index, nack_index + num_nack_fields,
BlockToHeaderLength((num_nack_fields * 4) + kCommonFbFmtLength),
packet, index);
nack_index += num_nack_fields;
@ -991,6 +971,10 @@ bool Nack::Create(uint8_t* packet,
return true;
}
size_t Nack::BlockLength() const {
return (nack_fields_.size() * 4) + kCommonFbFmtLength;
}
void Nack::WithList(const uint16_t* nack_list, int length) {
assert(nack_list);
assert(nack_fields_.empty());
@ -1024,8 +1008,9 @@ bool Rpsi::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet,
index);
const uint8_t kFmt = 3;
CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
CreateRpsi(rpsi_, padding_bytes_, packet, index);
return true;
}
@ -1064,7 +1049,9 @@ bool Fir::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet, index);
const uint8_t kFmt = 4;
CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
CreateFir(fir_, fir_item_, packet, index);
return true;
}
@ -1076,8 +1063,9 @@ bool Remb::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateRemb(remb_, remb_item_, BlockToHeaderLength(BlockLength()), packet,
index);
const uint8_t kFmt = 15;
CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
CreateRemb(remb_, remb_item_, packet, index);
return true;
}
@ -1097,8 +1085,9 @@ bool Tmmbr::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateTmmbr(tmmbr_, tmmbr_item_, BlockToHeaderLength(BlockLength()), packet,
index);
const uint8_t kFmt = 3;
CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index);
CreateTmmbr(tmmbr_, tmmbr_item_, packet, index);
return true;
}
@ -1124,8 +1113,9 @@ bool Tmmbn::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateTmmbn(tmmbn_, tmmbn_items_, BlockToHeaderLength(BlockLength()), packet,
index);
const uint8_t kFmt = 4;
CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index);
CreateTmmbn(tmmbn_, tmmbn_items_, packet, index);
return true;
}
@ -1137,7 +1127,8 @@ bool Xr::Create(uint8_t* packet,
if (!OnBufferFull(packet, index, callback))
return false;
}
CreateXrHeader(xr_header_, BlockToHeaderLength(BlockLength()), packet, index);
CreateHeader(0U, PT_XR, HeaderLength(), packet, index);
CreateXrHeader(xr_header_, packet, index);
CreateRrtr(rrtr_blocks_, packet, index);
CreateDlrr(dlrr_blocks_, packet, index);
CreateVoipMetric(voip_metric_blocks_, packet, index);