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