Home | History | Annotate | Download | only in rtcp_packet
      1 /*
      2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
     12 
     13 #include "webrtc/base/checks.h"
     14 #include "webrtc/base/logging.h"
     15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
     16 
     17 using webrtc::RTCPUtility::RtcpCommonHeader;
     18 
     19 namespace webrtc {
     20 namespace rtcp {
     21 
     22 //
     23 // RTCP receiver report (RFC 3550).
     24 //
     25 //   0                   1                   2                   3
     26 //   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
     27 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     28 //  |V=2|P|    RC   |   PT=RR=201   |             length            |
     29 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     30 //  |                     SSRC of packet sender                     |
     31 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     32 //  |                         report block(s)                       |
     33 //  |                            ....                               |
     34 bool ReceiverReport::Parse(const RTCPUtility::RtcpCommonHeader& header,
     35                            const uint8_t* payload) {
     36   RTC_DCHECK(header.packet_type == kPacketType);
     37 
     38   const uint8_t report_blocks_count = header.count_or_format;
     39 
     40   if (header.payload_size_bytes <
     41       kRrBaseLength + report_blocks_count * ReportBlock::kLength) {
     42     LOG(LS_WARNING) << "Packet is too small to contain all the data.";
     43     return false;
     44   }
     45 
     46   sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload);
     47 
     48   const uint8_t* next_report_block = payload + kRrBaseLength;
     49 
     50   report_blocks_.resize(report_blocks_count);
     51   for (ReportBlock& block : report_blocks_) {
     52     block.Parse(next_report_block, ReportBlock::kLength);
     53     next_report_block += ReportBlock::kLength;
     54   }
     55 
     56   RTC_DCHECK_LE(next_report_block, payload + header.payload_size_bytes);
     57   return true;
     58 }
     59 
     60 bool ReceiverReport::Create(uint8_t* packet,
     61                             size_t* index,
     62                             size_t max_length,
     63                             RtcpPacket::PacketReadyCallback* callback) const {
     64   while (*index + BlockLength() > max_length) {
     65     if (!OnBufferFull(packet, index, callback))
     66       return false;
     67   }
     68   CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet,
     69                index);
     70   ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc_);
     71   *index += kRrBaseLength;
     72   for (const ReportBlock& block : report_blocks_) {
     73     block.Create(packet + *index);
     74     *index += ReportBlock::kLength;
     75   }
     76   return true;
     77 }
     78 
     79 bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
     80   if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
     81     LOG(LS_WARNING) << "Max report blocks reached.";
     82     return false;
     83   }
     84   report_blocks_.push_back(block);
     85   return true;
     86 }
     87 
     88 }  // namespace rtcp
     89 }  // namespace webrtc
     90