tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

remb.cc (5403B)


      1 /*
      2 *  Copyright (c) 2016 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 "modules/rtp_rtcp/source/rtcp_packet/remb.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <utility>
     16 #include <vector>
     17 
     18 #include "modules/rtp_rtcp/source/byte_io.h"
     19 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
     20 #include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
     21 #include "rtc_base/checks.h"
     22 #include "rtc_base/logging.h"
     23 
     24 namespace webrtc {
     25 namespace rtcp {
     26 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
     27 //
     28 //     0                   1                   2                   3
     29 //     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
     30 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     31 //    |V=2|P| FMT=15  |   PT=206      |             length            |
     32 //    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     33 //  0 |                  SSRC of packet sender                        |
     34 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     35 //  4 |                       Unused = 0                              |
     36 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     37 //  8 |  Unique identifier 'R' 'E' 'M' 'B'                            |
     38 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     39 // 12 |  Num SSRC     | BR Exp    |  BR Mantissa                      |
     40 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     41 // 16 |   SSRC feedback                                               |
     42 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     43 //    :  ...                                                          :
     44 
     45 Remb::Remb() : bitrate_bps_(0) {}
     46 
     47 Remb::Remb(const Remb& rhs) = default;
     48 
     49 Remb::~Remb() = default;
     50 
     51 bool Remb::Parse(const CommonHeader& packet) {
     52  RTC_DCHECK(packet.type() == kPacketType);
     53  RTC_DCHECK_EQ(packet.fmt(), Psfb::kAfbMessageType);
     54 
     55  if (packet.payload_size_bytes() < 16) {
     56    RTC_LOG(LS_WARNING) << "Payload length " << packet.payload_size_bytes()
     57                        << " is too small for Remb packet.";
     58    return false;
     59  }
     60  const uint8_t* const payload = packet.payload();
     61  if (kUniqueIdentifier != ByteReader<uint32_t>::ReadBigEndian(&payload[8])) {
     62    return false;
     63  }
     64  uint8_t number_of_ssrcs = payload[12];
     65  if (packet.payload_size_bytes() !=
     66      kCommonFeedbackLength + (2 + number_of_ssrcs) * 4) {
     67    RTC_LOG(LS_WARNING) << "Payload size " << packet.payload_size_bytes()
     68                        << " does not match " << number_of_ssrcs << " ssrcs.";
     69    return false;
     70  }
     71 
     72  ParseCommonFeedback(payload);
     73  uint8_t exponent = payload[13] >> 2;
     74  uint64_t mantissa = (static_cast<uint32_t>(payload[13] & 0x03) << 16) |
     75                      ByteReader<uint16_t>::ReadBigEndian(&payload[14]);
     76  bitrate_bps_ = (mantissa << exponent);
     77  bool shift_overflow =
     78      (static_cast<uint64_t>(bitrate_bps_) >> exponent) != mantissa;
     79  if (bitrate_bps_ < 0 || shift_overflow) {
     80    RTC_LOG(LS_ERROR) << "Invalid remb bitrate value : " << mantissa << "*2^"
     81                      << static_cast<int>(exponent);
     82    return false;
     83  }
     84 
     85  const uint8_t* next_ssrc = payload + 16;
     86  ssrcs_.clear();
     87  ssrcs_.reserve(number_of_ssrcs);
     88  for (uint8_t i = 0; i < number_of_ssrcs; ++i) {
     89    ssrcs_.push_back(ByteReader<uint32_t>::ReadBigEndian(next_ssrc));
     90    next_ssrc += sizeof(uint32_t);
     91  }
     92 
     93  return true;
     94 }
     95 
     96 bool Remb::SetSsrcs(std::vector<uint32_t> ssrcs) {
     97  if (ssrcs.size() > kMaxNumberOfSsrcs) {
     98    RTC_LOG(LS_WARNING) << "Not enough space for all given SSRCs.";
     99    return false;
    100  }
    101  ssrcs_ = std::move(ssrcs);
    102  return true;
    103 }
    104 
    105 size_t Remb::BlockLength() const {
    106  return kHeaderLength + kCommonFeedbackLength + (2 + ssrcs_.size()) * 4;
    107 }
    108 
    109 bool Remb::Create(uint8_t* packet,
    110                  size_t* index,
    111                  size_t max_length,
    112                  PacketReadyCallback callback) const {
    113  while (*index + BlockLength() > max_length) {
    114    if (!OnBufferFull(packet, index, callback))
    115      return false;
    116  }
    117  size_t index_end = *index + BlockLength();
    118  CreateHeader(Psfb::kAfbMessageType, kPacketType, HeaderLength(), packet,
    119               index);
    120  RTC_DCHECK_EQ(0, Psfb::media_ssrc());
    121  CreateCommonFeedback(packet + *index);
    122  *index += kCommonFeedbackLength;
    123 
    124  ByteWriter<uint32_t>::WriteBigEndian(packet + *index, kUniqueIdentifier);
    125  *index += sizeof(uint32_t);
    126  const uint32_t kMaxMantissa = 0x3ffff;  // 18 bits.
    127  uint64_t mantissa = bitrate_bps_;
    128  uint8_t exponenta = 0;
    129  while (mantissa > kMaxMantissa) {
    130    mantissa >>= 1;
    131    ++exponenta;
    132  }
    133  packet[(*index)++] = static_cast<uint8_t>(ssrcs_.size());
    134  packet[(*index)++] = (exponenta << 2) | (mantissa >> 16);
    135  ByteWriter<uint16_t>::WriteBigEndian(packet + *index, mantissa & 0xffff);
    136  *index += sizeof(uint16_t);
    137 
    138  for (uint32_t ssrc : ssrcs_) {
    139    ByteWriter<uint32_t>::WriteBigEndian(packet + *index, ssrc);
    140    *index += sizeof(uint32_t);
    141  }
    142  RTC_DCHECK_EQ(index_end, *index);
    143  return true;
    144 }
    145 }  // namespace rtcp
    146 }  // namespace webrtc