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/dlrr.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 namespace webrtc {
     18 namespace rtcp {
     19 // DLRR Report Block (RFC 3611).
     20 //
     21 //   0                   1                   2                   3
     22 //   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
     23 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     24 //  |     BT=5      |   reserved    |         block length          |
     25 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     26 //  |                 SSRC_1 (SSRC of first receiver)               | sub-
     27 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
     28 //  |                         last RR (LRR)                         |   1
     29 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     30 //  |                   delay since last RR (DLRR)                  |
     31 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     32 //  |                 SSRC_2 (SSRC of second receiver)              | sub-
     33 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
     34 //  :                               ...                             :   2
     35 bool Dlrr::Parse(const uint8_t* buffer, uint16_t block_length_32bits) {
     36   RTC_DCHECK(buffer[0] == kBlockType);
     37   // kReserved = buffer[1];
     38   RTC_DCHECK_EQ(block_length_32bits,
     39                 ByteReader<uint16_t>::ReadBigEndian(&buffer[2]));
     40   if (block_length_32bits % 3 != 0) {
     41     LOG(LS_WARNING) << "Invalid size for dlrr block.";
     42     return false;
     43   }
     44 
     45   size_t blocks_count = block_length_32bits / 3;
     46   const uint8_t* read_at = buffer + kBlockHeaderLength;
     47   sub_blocks_.resize(blocks_count);
     48   for (SubBlock& sub_block : sub_blocks_) {
     49     sub_block.ssrc = ByteReader<uint32_t>::ReadBigEndian(&read_at[0]);
     50     sub_block.last_rr = ByteReader<uint32_t>::ReadBigEndian(&read_at[4]);
     51     sub_block.delay_since_last_rr =
     52         ByteReader<uint32_t>::ReadBigEndian(&read_at[8]);
     53     read_at += kSubBlockLength;
     54   }
     55   return true;
     56 }
     57 
     58 size_t Dlrr::BlockLength() const {
     59   if (sub_blocks_.empty())
     60     return 0;
     61   return kBlockHeaderLength + kSubBlockLength * sub_blocks_.size();
     62 }
     63 
     64 void Dlrr::Create(uint8_t* buffer) const {
     65   if (sub_blocks_.empty())  // No subblocks, no need to write header either.
     66     return;
     67   // Create block header.
     68   const uint8_t kReserved = 0;
     69   buffer[0] = kBlockType;
     70   buffer[1] = kReserved;
     71   ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], 3 * sub_blocks_.size());
     72   // Create sub blocks.
     73   uint8_t* write_at = buffer + kBlockHeaderLength;
     74   for (const SubBlock& sub_block : sub_blocks_) {
     75     ByteWriter<uint32_t>::WriteBigEndian(&write_at[0], sub_block.ssrc);
     76     ByteWriter<uint32_t>::WriteBigEndian(&write_at[4], sub_block.last_rr);
     77     ByteWriter<uint32_t>::WriteBigEndian(&write_at[8],
     78                                          sub_block.delay_since_last_rr);
     79     write_at += kSubBlockLength;
     80   }
     81   RTC_DCHECK_EQ(buffer + BlockLength(), write_at);
     82 }
     83 
     84 bool Dlrr::WithDlrrItem(uint32_t ssrc,
     85                         uint32_t last_rr,
     86                         uint32_t delay_last_rr) {
     87   if (sub_blocks_.size() >= kMaxNumberOfDlrrItems) {
     88     LOG(LS_WARNING) << "Max DLRR items reached.";
     89     return false;
     90   }
     91   SubBlock block;
     92   block.ssrc = ssrc;
     93   block.last_rr = last_rr;
     94   block.delay_since_last_rr = delay_last_rr;
     95   sub_blocks_.push_back(block);
     96   return true;
     97 }
     98 
     99 }  // namespace rtcp
    100 }  // namespace webrtc
    101