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