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