Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Unified Diff: webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc

Issue 1847973003: [rtcp] TransportFeedback adjusted to match other rtcp packets (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Remove underused buffer check from Parse, added it to Create Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
index 356263e96f1a4560e60c50fca38777218abed174..cce0075adef1cb8d56308861f7f0327896ed4676 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
@@ -12,38 +12,33 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
-#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
namespace webrtc {
namespace rtcp {
-
+namespace {
// Header size:
-// * 12 bytes Common Packet Format for RTCP Feedback Messages
+// * 4 bytes Common RTCP Packet Header
+// * 8 bytes Common Packet Format for RTCP Feedback Messages
// * 8 bytes FeedbackPacket header
-static const uint32_t kHeaderSizeBytes = 12 + 8;
-static const uint32_t kChunkSizeBytes = 2;
-static const uint32_t kOneBitVectorCapacity = 14;
-static const uint32_t kTwoBitVectorCapacity = 7;
-static const uint32_t kRunLengthCapacity = 0x1FFF;
+constexpr size_t kTransportFeedbackHeaderSizeBytes = 4 + 8 + 8;
+constexpr size_t kChunkSizeBytes = 2;
+constexpr size_t kRunLengthCapacity = 0x1FFF;
// TODO(sprang): Add support for dynamic max size for easier fragmentation,
// eg. set it to what's left in the buffer or IP_PACKET_SIZE.
// Size constraint imposed by RTCP common header: 16bit size field interpreted
// as number of four byte words minus the first header word.
-static const uint32_t kMaxSizeBytes = (1 << 16) * 4;
-static const uint32_t kMinSizeBytes = kHeaderSizeBytes + kChunkSizeBytes;
-static const uint32_t kBaseScaleFactor =
+constexpr size_t kMaxSizeBytes = (1 << 16) * 4;
+// Payload size:
+// * 8 bytes Common Packet Format for RTCP Feedback Messages
+// * 8 bytes FeedbackPacket header.
+// * 2 bytes for one chunk.
+constexpr size_t kMinPayloadSizeBytes = 8 + 8 + 2;
+constexpr size_t kBaseScaleFactor =
TransportFeedback::kDeltaScaleFactor * (1 << 8);
-class PacketStatusChunk {
- public:
- virtual ~PacketStatusChunk() {}
- virtual uint16_t NumSymbols() const = 0;
- virtual void AppendSymbolsTo(
- std::vector<TransportFeedback::StatusSymbol>* vec) const = 0;
- virtual void WriteTo(uint8_t* buffer) const = 0;
-};
-
uint8_t EncodeSymbol(TransportFeedback::StatusSymbol symbol) {
switch (symbol) {
case TransportFeedback::StatusSymbol::kNotReceived:
@@ -52,10 +47,9 @@ uint8_t EncodeSymbol(TransportFeedback::StatusSymbol symbol) {
return 1;
case TransportFeedback::StatusSymbol::kReceivedLargeDelta:
return 2;
- default:
- RTC_NOTREACHED();
- return 0;
}
+ RTC_NOTREACHED();
+ return 0;
}
TransportFeedback::StatusSymbol DecodeSymbol(uint8_t value) {
@@ -72,18 +66,27 @@ TransportFeedback::StatusSymbol DecodeSymbol(uint8_t value) {
}
}
+} // namespace
+constexpr uint8_t TransportFeedback::kFeedbackMessageType;
+
+class TransportFeedback::PacketStatusChunk {
+ public:
+ virtual ~PacketStatusChunk() {}
+ virtual uint16_t NumSymbols() const = 0;
+ virtual void AppendSymbolsTo(
+ std::vector<TransportFeedback::StatusSymbol>* vec) const = 0;
+ virtual void WriteTo(uint8_t* buffer) const = 0;
+};
+
TransportFeedback::TransportFeedback()
- : packet_sender_ssrc_(0),
- media_source_ssrc_(0),
- base_seq_(-1),
+ : base_seq_(-1),
base_time_(-1),
feedback_seq_(0),
last_seq_(-1),
last_timestamp_(-1),
first_symbol_cardinality_(0),
vec_needs_two_bit_symbols_(false),
- size_bytes_(kHeaderSizeBytes) {
-}
+ size_bytes_(kTransportFeedbackHeaderSizeBytes) {}
TransportFeedback::~TransportFeedback() {
for (PacketStatusChunk* chunk : status_chunks_)
@@ -102,9 +105,9 @@ TransportFeedback::~TransportFeedback() {
// S = 0
// symbol list = 14 entries where 0 = not received, 1 = received
-class OneBitVectorChunk : public PacketStatusChunk {
+class OneBitVectorChunk : public TransportFeedback::PacketStatusChunk {
public:
- static const int kCapacity = 14;
+ static constexpr size_t kCapacity = 14;
explicit OneBitVectorChunk(
std::deque<TransportFeedback::StatusSymbol>* symbols) {
@@ -119,7 +122,7 @@ class OneBitVectorChunk : public PacketStatusChunk {
}
}
- virtual ~OneBitVectorChunk() {}
+ ~OneBitVectorChunk() override {}
uint16_t NumSymbols() const override { return kCapacity; }
@@ -129,8 +132,8 @@ class OneBitVectorChunk : public PacketStatusChunk {
}
void WriteTo(uint8_t* buffer) const override {
- const int kSymbolsInFirstByte = 6;
- const int kSymbolsInSecondByte = 8;
+ constexpr int kSymbolsInFirstByte = 6;
+ constexpr int kSymbolsInSecondByte = 8;
buffer[0] = 0x80u;
for (int i = 0; i < kSymbolsInFirstByte; ++i) {
uint8_t encoded_symbol = EncodeSymbol(symbols_[i]);
@@ -175,9 +178,9 @@ class OneBitVectorChunk : public PacketStatusChunk {
// S = 1
// symbol list = 7 entries of two bits each, see (Encode|Decode)Symbol
-class TwoBitVectorChunk : public PacketStatusChunk {
+class TwoBitVectorChunk : public TransportFeedback::PacketStatusChunk {
public:
- static const int kCapacity = 7;
+ static constexpr size_t kCapacity = 7;
explicit TwoBitVectorChunk(
std::deque<TransportFeedback::StatusSymbol>* symbols) {
@@ -192,7 +195,7 @@ class TwoBitVectorChunk : public PacketStatusChunk {
}
}
- virtual ~TwoBitVectorChunk() {}
+ ~TwoBitVectorChunk() override {}
uint16_t NumSymbols() const override { return kCapacity; }
@@ -244,14 +247,14 @@ class TwoBitVectorChunk : public PacketStatusChunk {
// S = symbol, see (Encode|Decode)Symbol
// Run Length = Unsigned integer denoting the run length of the symbol
-class RunLengthChunk : public PacketStatusChunk {
+class RunLengthChunk : public TransportFeedback::PacketStatusChunk {
public:
RunLengthChunk(TransportFeedback::StatusSymbol symbol, size_t size)
: symbol_(symbol), size_(size) {
RTC_DCHECK_LE(size, 0x1FFFu);
}
- virtual ~RunLengthChunk() {}
+ ~RunLengthChunk() override {}
uint16_t NumSymbols() const override { return size_; }
@@ -297,21 +300,6 @@ int64_t TransportFeedback::Unwrap(uint16_t sequence_number) {
return last_seq_ + delta;
}
-void TransportFeedback::WithPacketSenderSsrc(uint32_t ssrc) {
- packet_sender_ssrc_ = ssrc;
-}
-
-void TransportFeedback::WithMediaSourceSsrc(uint32_t ssrc) {
- media_source_ssrc_ = ssrc;
-}
-
-uint32_t TransportFeedback::GetPacketSenderSsrc() const {
- return packet_sender_ssrc_;
-}
-
-uint32_t TransportFeedback::GetMediaSourceSsrc() const {
- return media_source_ssrc_;
-}
void TransportFeedback::WithBase(uint16_t base_sequence,
int64_t ref_timestamp_us) {
RTC_DCHECK_EQ(-1, base_seq_);
@@ -390,8 +378,8 @@ bool TransportFeedback::Encode(StatusSymbol symbol) {
return false;
}
- bool is_two_bit;
- int delta_size;
+ bool is_two_bit = false;
+ int delta_size = -1;
switch (symbol) {
case StatusSymbol::kReceivedSmallDelta:
delta_size = 1;
@@ -405,10 +393,8 @@ bool TransportFeedback::Encode(StatusSymbol symbol) {
is_two_bit = false;
delta_size = 0;
break;
- default:
- RTC_NOTREACHED();
- return false;
}
+ RTC_DCHECK_GE(delta_size, 0);
if (symbol_vec_.empty()) {
if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
@@ -424,8 +410,8 @@ bool TransportFeedback::Encode(StatusSymbol symbol) {
return false;
// Capacity, in number of symbols, that a vector chunk could hold.
- size_t capacity = vec_needs_two_bit_symbols_ ? kTwoBitVectorCapacity
- : kOneBitVectorCapacity;
+ size_t capacity = vec_needs_two_bit_symbols_ ? TwoBitVectorChunk::kCapacity
+ : OneBitVectorChunk::kCapacity;
// first_symbol_cardinality_ is the number of times the first symbol in
// symbol_vec is repeated. So if that is equal to the size of symbol_vec,
@@ -468,7 +454,7 @@ bool TransportFeedback::Encode(StatusSymbol symbol) {
// If the symbols in symbol_vec can be encoded using a one-bit chunk but
// the input symbol cannot, first check if we can simply change target type.
vec_needs_two_bit_symbols_ = true;
- if (symbol_vec_.size() >= kTwoBitVectorCapacity) {
+ if (symbol_vec_.size() >= TwoBitVectorChunk::kCapacity) {
// symbol_vec contains more symbols than we can encode in a single
// two-bit chunk. Emit a new vector append to the remains, if any.
if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
@@ -481,7 +467,7 @@ bool TransportFeedback::Encode(StatusSymbol symbol) {
return Encode(symbol);
}
// symbol_vec symbols fit within a single two-bit vector chunk.
- capacity = kTwoBitVectorCapacity;
+ capacity = TwoBitVectorChunk::kCapacity;
}
symbol_vec_.push_back(symbol);
@@ -498,8 +484,8 @@ void TransportFeedback::EmitRemaining() {
if (symbol_vec_.empty())
return;
- size_t capacity = vec_needs_two_bit_symbols_ ? kTwoBitVectorCapacity
- : kOneBitVectorCapacity;
+ size_t capacity = vec_needs_two_bit_symbols_ ? TwoBitVectorChunk::kCapacity
+ : OneBitVectorChunk::kCapacity;
if (first_symbol_cardinality_ > capacity) {
EmitRunLengthChunk();
} else {
@@ -531,7 +517,8 @@ void TransportFeedback::EmitRunLengthChunk() {
}
size_t TransportFeedback::BlockLength() const {
- return size_bytes_;
+ // Round size_bytes_ up to multiple of 32bits.
+ return (size_bytes_ + 3) & (~static_cast<size_t>(3));
}
uint16_t TransportFeedback::GetBaseSequence() const {
@@ -577,17 +564,16 @@ bool TransportFeedback::Create(uint8_t* packet,
if (base_seq_ == -1)
return false;
- while (*position + size_bytes_ > max_length) {
+ while (*position + BlockLength() > max_length) {
if (!OnBufferFull(packet, position, callback))
return false;
}
+ const size_t position_end = *position + BlockLength();
- CreateHeader(kFeedbackMessageType, kPayloadType, HeaderLength(), packet,
+ CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
position);
- ByteWriter<uint32_t>::WriteBigEndian(&packet[*position], packet_sender_ssrc_);
- *position += 4;
- ByteWriter<uint32_t>::WriteBigEndian(&packet[*position], media_source_ssrc_);
- *position += 4;
+ CreateCommonFeedback(packet + *position);
+ *position += kCommonFeedbackLength;
RTC_DCHECK_LE(base_seq_, 0xFFFF);
ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], base_seq_);
@@ -623,6 +609,7 @@ bool TransportFeedback::Create(uint8_t* packet,
while ((*position % 4) != 0)
packet[(*position)++] = 0;
+ RTC_DCHECK_EQ(*position, position_end);
return true;
}
@@ -633,15 +620,15 @@ bool TransportFeedback::Create(uint8_t* packet,
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |V=2|P| FMT=15 | PT=205 | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | SSRC of packet sender |
+// 0 | SSRC of packet sender |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | SSRC of media source |
+// 4 | SSRC of media source |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | base sequence number | packet status count |
+// 8 | base sequence number | packet status count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | reference time | fb pkt. count |
+// 12 | reference time | fb pkt. count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | packet chunk | packet chunk |
+// 16 | packet chunk | packet chunk |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// . .
// . .
@@ -655,68 +642,55 @@ bool TransportFeedback::Create(uint8_t* packet,
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// De-serialize packet.
-std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom(
- const uint8_t* buffer,
- size_t length) {
- std::unique_ptr<TransportFeedback> packet(new TransportFeedback());
+bool TransportFeedback::Parse(const CommonHeader& packet) {
+ RTC_DCHECK_EQ(packet.type(), kPacketType);
+ RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType);
- if (length < kMinSizeBytes) {
- LOG(LS_WARNING) << "Buffer too small (" << length
+ if (packet.payload_size_bytes() < kMinPayloadSizeBytes) {
+ LOG(LS_WARNING) << "Buffer too small (" << packet.payload_size_bytes()
<< " bytes) to fit a "
- "FeedbackPacket. Minimum size = " << kMinSizeBytes;
- return nullptr;
+ "FeedbackPacket. Minimum size = "
+ << kMinPayloadSizeBytes;
+ return false;
}
+ // TODO(danilchap): Make parse work correctly with not new objects.
+ RTC_DCHECK(status_chunks_.empty()) << "Parse expects object to be new.";
- RTCPUtility::RtcpCommonHeader header;
- if (!RtcpParseCommonHeader(buffer, length, &header))
- return nullptr;
+ const uint8_t* const payload = packet.payload();
- if (header.count_or_format != kFeedbackMessageType) {
- LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
- << kFeedbackMessageType << " but was "
- << header.count_or_format;
- return nullptr;
- }
-
- if (header.packet_type != kPayloadType) {
- LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType
- << " but was " << header.packet_type;
- return nullptr;
- }
+ ParseCommonFeedback(payload);
- packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
- packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
- packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]);
- uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]);
- packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]);
- packet->feedback_seq_ = buffer[19];
- size_t index = 20;
- const size_t end_index = kHeaderLength + header.payload_size_bytes;
+ base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&payload[8]);
+ uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&payload[10]);
+ base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&payload[12]);
+ feedback_seq_ = payload[15];
+ size_t index = 16;
+ const size_t end_index = packet.payload_size_bytes();
if (num_packets == 0) {
LOG(LS_WARNING) << "Empty feedback messages not allowed.";
- return nullptr;
+ return false;
}
- packet->last_seq_ = packet->base_seq_ + num_packets - 1;
+ last_seq_ = base_seq_ + num_packets - 1;
size_t packets_read = 0;
while (packets_read < num_packets) {
if (index + 2 > end_index) {
LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
- return nullptr;
+ return false;
}
PacketStatusChunk* chunk =
- ParseChunk(&buffer[index], num_packets - packets_read);
+ ParseChunk(&payload[index], num_packets - packets_read);
if (chunk == nullptr)
- return nullptr;
+ return false;
index += 2;
- packet->status_chunks_.push_back(chunk);
+ status_chunks_.push_back(chunk);
packets_read += chunk->NumSymbols();
}
- std::vector<StatusSymbol> symbols = packet->GetStatusVector();
+ std::vector<StatusSymbol> symbols = GetStatusVector();
RTC_DCHECK_EQ(num_packets, symbols.size());
@@ -725,36 +699,49 @@ std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom(
case StatusSymbol::kReceivedSmallDelta:
if (index + 1 > end_index) {
LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
- return nullptr;
+ return false;
}
- packet->receive_deltas_.push_back(buffer[index]);
+ receive_deltas_.push_back(payload[index]);
++index;
break;
case StatusSymbol::kReceivedLargeDelta:
if (index + 2 > end_index) {
LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
- return nullptr;
+ return false;
}
- packet->receive_deltas_.push_back(
- ByteReader<int16_t>::ReadBigEndian(&buffer[index]));
+ receive_deltas_.push_back(
+ ByteReader<int16_t>::ReadBigEndian(&payload[index]));
index += 2;
break;
- default:
+ case StatusSymbol::kNotReceived:
continue;
}
}
- RTC_DCHECK_GE(index, end_index - 3);
RTC_DCHECK_LE(index, end_index);
- return packet;
+ return true;
+}
+
+std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom(
+ const uint8_t* buffer,
+ size_t length) {
+ CommonHeader header;
+ if (!header.Parse(buffer, length))
+ return nullptr;
+ if (header.type() != kPacketType || header.fmt() != kFeedbackMessageType)
+ return nullptr;
+ std::unique_ptr<TransportFeedback> parsed(new TransportFeedback);
+ if (!parsed->Parse(header))
+ return nullptr;
+ return parsed;
}
-PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer,
- size_t max_size) {
+TransportFeedback::PacketStatusChunk* TransportFeedback::ParseChunk(
+ const uint8_t* buffer,
+ size_t max_size) {
if (buffer[0] & 0x80) {
// First bit set => vector chunk.
- std::deque<StatusSymbol> symbols;
if (buffer[0] & 0x40) {
// Second bit set => two bits per symbol vector.
return TwoBitVectorChunk::ParseFrom(buffer);
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698