Chromium Code Reviews| Index: webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc |
| diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc |
| index a78ad464b72174d4106020dd90c6ab32a8473a9a..980267017c076ab88d95ae391b4b5e6404cb97ec 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc |
| @@ -14,16 +14,10 @@ |
| #include "webrtc/base/logging.h" |
| #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| -using webrtc::RTCPUtility::PT_XR; |
| -using webrtc::RTCPUtility::RTCPPacketXR; |
| +using webrtc::RTCPUtility::RtcpCommonHeader; |
| namespace webrtc { |
| namespace rtcp { |
| -namespace { |
| -void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { |
| - ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value); |
| - *offset += 4; |
| -} |
| // From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR). |
| // |
| // Format for XR packets: |
| @@ -37,65 +31,114 @@ void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| // : report blocks : |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| -void CreateXrHeader(const RTCPPacketXR& header, |
| - uint8_t* buffer, |
| - size_t* pos) { |
| - AssignUWord32(buffer, pos, header.OriginatorSSRC); |
| -} |
| -} // namespace |
| +// |
| +// Report header: |
|
åsapersson
2016/01/29 12:46:09
maybe Report block header:
danilchap
2016/01/29 13:49:30
To match specification included full report block
|
| +// 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 |
| +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| +// | Block Type | reserved | block length | |
| +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| +ExtendedReports::ExtendedReports() : sender_ssrc_(0) {} |
| +ExtendedReports::~ExtendedReports() {} |
| -bool ExtendedReports::Create(uint8_t* packet, |
| - size_t* index, |
| - size_t max_length, |
| - RtcpPacket::PacketReadyCallback* callback) const { |
| - while (*index + BlockLength() > max_length) { |
| - if (!OnBufferFull(packet, index, callback)) |
| - return false; |
| - } |
| - CreateHeader(0U, PT_XR, HeaderLength(), packet, index); |
| - CreateXrHeader(xr_header_, packet, index); |
| - for (const Rrtr& block : rrtr_blocks_) { |
| - block.Create(packet + *index); |
| - *index += Rrtr::kLength; |
| - } |
| - for (const Dlrr& block : dlrr_blocks_) { |
| - block.Create(packet + *index); |
| - *index += block.BlockLength(); |
| +bool ExtendedReports::Parse(const RtcpCommonHeader& header, |
| + const uint8_t* payload) { |
| + RTC_CHECK(header.packet_type == kPacketType); |
| + |
| + if (header.payload_size_bytes < kXrHeaderLength) { |
| + LOG(LS_WARNING) << "Packet is too small to be an ExtendedReports packet."; |
| + return false; |
| } |
| - for (const VoipMetric& block : voip_metric_blocks_) { |
| - block.Create(packet + *index); |
| - *index += VoipMetric::kLength; |
| + |
| + sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload); |
| + |
|
åsapersson
2016/01/29 12:46:09
should the blocks be resized to zero here?
danilchap
2016/01/29 13:49:30
Done.
|
| + const uint8_t* current_block = payload + kXrHeaderLength; |
| + const uint8_t* const packet_end = payload + header.payload_size_bytes; |
| + const size_t kBlockHeaderSizeBytes = 4; |
| + while (current_block + kBlockHeaderSizeBytes <= packet_end) { |
| + uint8_t block_type = ByteReader<uint8_t>::ReadBigEndian(current_block); |
| + uint16_t block_size = |
|
åsapersson
2016/01/29 12:46:09
perhaps call block_length (as in figure)
danilchap
2016/01/29 13:49:30
Done. Word 'size' may also give false impression i
|
| + ByteReader<uint16_t>::ReadBigEndian(current_block + 2); |
| + const uint8_t* next_block = |
| + current_block + kBlockHeaderSizeBytes + block_size * 4; |
| + if (next_block > packet_end) { |
| + LOG(LS_WARNING) << "Report block in extended report packet is too big."; |
| + return false; |
| + } |
| + switch (block_type) { |
| + case Rrtr::kBlockType: |
| + ParseRrtrBlock(current_block, block_size); |
| + break; |
| + case Dlrr::kBlockType: |
| + ParseDlrrBlock(current_block, block_size); |
| + break; |
| + case VoipMetric::kBlockType: |
| + ParseVoipMetricBlock(current_block, block_size); |
| + break; |
| + default: |
| + // Unknown block, ignore. |
| + LOG(LS_WARNING) << "Unknown extended report block type " << block_type; |
| + break; |
| + } |
| + current_block = next_block; |
| } |
| + |
| return true; |
| } |
| -bool ExtendedReports::WithRrtr(Rrtr* rrtr) { |
| - RTC_DCHECK(rrtr); |
| +bool ExtendedReports::WithRrtr(const Rrtr& rrtr) { |
| if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) { |
| LOG(LS_WARNING) << "Max RRTR blocks reached."; |
| return false; |
| } |
| - rrtr_blocks_.push_back(*rrtr); |
| + rrtr_blocks_.push_back(rrtr); |
| return true; |
| } |
| -bool ExtendedReports::WithDlrr(Dlrr* dlrr) { |
| - RTC_DCHECK(dlrr); |
| +bool ExtendedReports::WithDlrr(const Dlrr& dlrr) { |
| if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) { |
| LOG(LS_WARNING) << "Max DLRR blocks reached."; |
| return false; |
| } |
| - dlrr_blocks_.push_back(*dlrr); |
| + dlrr_blocks_.push_back(dlrr); |
| return true; |
| } |
| -bool ExtendedReports::WithVoipMetric(VoipMetric* voip_metric) { |
| - assert(voip_metric); |
| +bool ExtendedReports::WithVoipMetric(const VoipMetric& voip_metric) { |
| if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) { |
| LOG(LS_WARNING) << "Max Voip Metric blocks reached."; |
| return false; |
| } |
| - voip_metric_blocks_.push_back(*voip_metric); |
| + voip_metric_blocks_.push_back(voip_metric); |
| + return true; |
| +} |
| + |
| +bool ExtendedReports::Create(uint8_t* packet, |
| + size_t* index, |
| + size_t max_length, |
| + RtcpPacket::PacketReadyCallback* callback) const { |
| + while (*index + BlockLength() > max_length) { |
| + if (!OnBufferFull(packet, index, callback)) |
| + return false; |
| + } |
| + size_t index_end = *index + BlockLength(); |
| + const uint8_t kReserved = 0; |
| + CreateHeader(kReserved, kPacketType, HeaderLength(), packet, index); |
| + ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc_); |
| + *index += sizeof(uint32_t); |
| + for (const Rrtr& block : rrtr_blocks_) { |
| + block.Create(packet + *index); |
| + *index += Rrtr::kLength; |
| + } |
| + for (const Dlrr& block : dlrr_blocks_) { |
| + block.Create(packet + *index); |
| + *index += block.BlockLength(); |
| + } |
| + for (const VoipMetric& block : voip_metric_blocks_) { |
| + block.Create(packet + *index); |
| + *index += VoipMetric::kLength; |
| + } |
| + RTC_CHECK_EQ(*index, index_end); |
| return true; |
| } |
| @@ -107,5 +150,34 @@ size_t ExtendedReports::DlrrLength() const { |
| return length; |
| } |
| +void ExtendedReports::ParseRrtrBlock(const uint8_t* block, |
| + uint16_t block_size) { |
| + if (block_size != Rrtr::kBlockLength) { |
| + LOG(LS_WARNING) << "Incorrect rrtr block size " << block_size |
| + << " Should be " << Rrtr::kBlockLength; |
| + return; |
| + } |
| + rrtr_blocks_.push_back(Rrtr()); |
| + rrtr_blocks_.back().Parse(block); |
| +} |
| + |
| +void ExtendedReports::ParseDlrrBlock(const uint8_t* block, |
| + uint16_t block_size) { |
| + dlrr_blocks_.push_back(Dlrr()); |
| + if (!dlrr_blocks_.back().Parse(block, block_size)) { |
| + dlrr_blocks_.pop_back(); |
| + } |
| +} |
| + |
| +void ExtendedReports::ParseVoipMetricBlock(const uint8_t* block, |
| + uint16_t block_size) { |
| + if (block_size != VoipMetric::kBlockLength) { |
| + LOG(LS_WARNING) << "Incorrect voip metric block size " << block_size |
| + << " Should be " << VoipMetric::kBlockLength; |
| + return; |
| + } |
| + voip_metric_blocks_.push_back(VoipMetric()); |
| + voip_metric_blocks_.back().Parse(block); |
| +} |
| } // namespace rtcp |
| } // namespace webrtc |