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/tmmb_item.h"
12 
13 #include "modules/rtp_rtcp/source/byte_io.h"
14 #include "rtc_base/checks.h"
15 #include "rtc_base/logging.h"
16 
17 namespace webrtc {
18 namespace rtcp {
TmmbItem(uint32_t ssrc,uint64_t bitrate_bps,uint16_t overhead)19 TmmbItem::TmmbItem(uint32_t ssrc, uint64_t bitrate_bps, uint16_t overhead)
20     : ssrc_(ssrc), bitrate_bps_(bitrate_bps), packet_overhead_(overhead) {
21   RTC_DCHECK_LE(overhead, 0x1ffu);
22 }
23 
24 //    0                   1                   2                   3
25 //    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
26 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 // 0 |                              SSRC                             |
28 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 // 4 | MxTBR Exp |  MxTBR Mantissa                 |Measured Overhead|
30 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Parse(const uint8_t * buffer)31 bool TmmbItem::Parse(const uint8_t* buffer) {
32   ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[0]);
33   // Read 4 bytes into 1 block.
34   uint32_t compact = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
35   // Split 1 block into 3 components.
36   uint8_t exponent = compact >> 26;              // 6 bits.
37   uint64_t mantissa = (compact >> 9) & 0x1ffff;  // 17 bits.
38   uint16_t overhead = compact & 0x1ff;           // 9 bits.
39   // Combine 3 components into 2 values.
40   bitrate_bps_ = (mantissa << exponent);
41 
42   bool shift_overflow = (bitrate_bps_ >> exponent) != mantissa;
43   if (shift_overflow) {
44     RTC_LOG(LS_ERROR) << "Invalid tmmb bitrate value : " << mantissa << "*2^"
45                       << static_cast<int>(exponent);
46     return false;
47   }
48   packet_overhead_ = overhead;
49   return true;
50 }
51 
Create(uint8_t * buffer) const52 void TmmbItem::Create(uint8_t* buffer) const {
53   constexpr uint64_t kMaxMantissa = 0x1ffff;  // 17 bits.
54   uint64_t mantissa = bitrate_bps_;
55   uint32_t exponent = 0;
56   while (mantissa > kMaxMantissa) {
57     mantissa >>= 1;
58     ++exponent;
59   }
60 
61   ByteWriter<uint32_t>::WriteBigEndian(&buffer[0], ssrc_);
62   uint32_t compact = (exponent << 26) | (mantissa << 9) | packet_overhead_;
63   ByteWriter<uint32_t>::WriteBigEndian(&buffer[4], compact);
64 }
65 
set_packet_overhead(uint16_t overhead)66 void TmmbItem::set_packet_overhead(uint16_t overhead) {
67   RTC_DCHECK_LE(overhead, 0x1ffu);
68   packet_overhead_ = overhead;
69 }
70 }  // namespace rtcp
71 }  // namespace webrtc
72