• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstdint>
14 #include <utility>
15 
16 #include "modules/rtp_rtcp/source/byte_io.h"
17 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/logging.h"
20 
21 namespace webrtc {
22 namespace rtcp {
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(const Remb& rhs) = default;
45 
46 Remb::~Remb() = default;
47 
Parse(const CommonHeader & packet)48 bool Remb::Parse(const CommonHeader& packet) {
49   RTC_DCHECK(packet.type() == kPacketType);
50   RTC_DCHECK_EQ(packet.fmt(), Psfb::kAfbMessageType);
51 
52   if (packet.payload_size_bytes() < 16) {
53     RTC_LOG(LS_WARNING) << "Payload length " << packet.payload_size_bytes()
54                         << " is too small for Remb packet.";
55     return false;
56   }
57   const uint8_t* const payload = packet.payload();
58   if (kUniqueIdentifier != ByteReader<uint32_t>::ReadBigEndian(&payload[8])) {
59     return false;
60   }
61   uint8_t number_of_ssrcs = payload[12];
62   if (packet.payload_size_bytes() !=
63       kCommonFeedbackLength + (2 + number_of_ssrcs) * 4) {
64     RTC_LOG(LS_WARNING) << "Payload size " << packet.payload_size_bytes()
65                         << " does not match " << number_of_ssrcs << " ssrcs.";
66     return false;
67   }
68 
69   ParseCommonFeedback(payload);
70   uint8_t exponenta = payload[13] >> 2;
71   uint64_t mantissa = (static_cast<uint32_t>(payload[13] & 0x03) << 16) |
72                       ByteReader<uint16_t>::ReadBigEndian(&payload[14]);
73   bitrate_bps_ = (mantissa << exponenta);
74   bool shift_overflow =
75       (static_cast<uint64_t>(bitrate_bps_) >> exponenta) != mantissa;
76   if (shift_overflow) {
77     RTC_LOG(LS_ERROR) << "Invalid remb bitrate value : " << mantissa << "*2^"
78                       << static_cast<int>(exponenta);
79     return false;
80   }
81 
82   const uint8_t* next_ssrc = payload + 16;
83   ssrcs_.clear();
84   ssrcs_.reserve(number_of_ssrcs);
85   for (uint8_t i = 0; i < number_of_ssrcs; ++i) {
86     ssrcs_.push_back(ByteReader<uint32_t>::ReadBigEndian(next_ssrc));
87     next_ssrc += sizeof(uint32_t);
88   }
89 
90   return true;
91 }
92 
SetSsrcs(std::vector<uint32_t> ssrcs)93 bool Remb::SetSsrcs(std::vector<uint32_t> ssrcs) {
94   if (ssrcs.size() > kMaxNumberOfSsrcs) {
95     RTC_LOG(LS_WARNING) << "Not enough space for all given SSRCs.";
96     return false;
97   }
98   ssrcs_ = std::move(ssrcs);
99   return true;
100 }
101 
BlockLength() const102 size_t Remb::BlockLength() const {
103   return kHeaderLength + kCommonFeedbackLength + (2 + ssrcs_.size()) * 4;
104 }
105 
Create(uint8_t * packet,size_t * index,size_t max_length,PacketReadyCallback callback) const106 bool Remb::Create(uint8_t* packet,
107                   size_t* index,
108                   size_t max_length,
109                   PacketReadyCallback callback) const {
110   while (*index + BlockLength() > max_length) {
111     if (!OnBufferFull(packet, index, callback))
112       return false;
113   }
114   size_t index_end = *index + BlockLength();
115   CreateHeader(Psfb::kAfbMessageType, kPacketType, HeaderLength(), packet,
116                index);
117   RTC_DCHECK_EQ(0, Psfb::media_ssrc());
118   CreateCommonFeedback(packet + *index);
119   *index += kCommonFeedbackLength;
120 
121   ByteWriter<uint32_t>::WriteBigEndian(packet + *index, kUniqueIdentifier);
122   *index += sizeof(uint32_t);
123   const uint32_t kMaxMantissa = 0x3ffff;  // 18 bits.
124   uint64_t mantissa = bitrate_bps_;
125   uint8_t exponenta = 0;
126   while (mantissa > kMaxMantissa) {
127     mantissa >>= 1;
128     ++exponenta;
129   }
130   packet[(*index)++] = static_cast<uint8_t>(ssrcs_.size());
131   packet[(*index)++] = (exponenta << 2) | (mantissa >> 16);
132   ByteWriter<uint16_t>::WriteBigEndian(packet + *index, mantissa & 0xffff);
133   *index += sizeof(uint16_t);
134 
135   for (uint32_t ssrc : ssrcs_) {
136     ByteWriter<uint32_t>::WriteBigEndian(packet + *index, ssrc);
137     *index += sizeof(uint32_t);
138   }
139   RTC_DCHECK_EQ(index_end, *index);
140   return true;
141 }
142 }  // namespace rtcp
143 }  // namespace webrtc
144