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 "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" 12 13 #include "webrtc/base/logging.h" 14 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 15 16 using webrtc::RTCPUtility::PT_RTPFB; 17 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR; 18 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem; 19 20 namespace webrtc { 21 namespace rtcp { 22 namespace { 23 const uint32_t kUnusedMediaSourceSsrc0 = 0; 24 25 void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) { 26 buffer[(*offset)++] = value; 27 } 28 29 void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { 30 ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value); 31 *offset += 4; 32 } 33 34 void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10, 35 uint8_t bits_mantissa, 36 uint32_t* mantissa, 37 uint8_t* exp) { 38 // input_base10 = mantissa * 2^exp 39 assert(bits_mantissa <= 32); 40 uint32_t mantissa_max = (1 << bits_mantissa) - 1; 41 uint8_t exponent = 0; 42 for (uint32_t i = 0; i < 64; ++i) { 43 if (input_base10 <= (mantissa_max << i)) { 44 exponent = i; 45 break; 46 } 47 } 48 *exp = exponent; 49 *mantissa = (input_base10 >> exponent); 50 } 51 52 void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item, 53 uint8_t* buffer, 54 size_t* pos) { 55 uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000; 56 uint32_t mantissa = 0; 57 uint8_t exp = 0; 58 ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp); 59 60 AssignUWord32(buffer, pos, tmmbr_item.SSRC); 61 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03)); 62 AssignUWord8(buffer, pos, mantissa >> 7); 63 AssignUWord8(buffer, pos, (mantissa << 1) + 64 ((tmmbr_item.MeasuredOverhead >> 8) & 0x01)); 65 AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead); 66 } 67 68 // Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). 69 // 70 // FCI: 71 // 72 // 0 1 2 3 73 // 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 74 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 75 // | SSRC | 76 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 77 // | MxTBR Exp | MxTBR Mantissa |Measured Overhead| 78 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 79 80 void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr, 81 const RTCPPacketRTPFBTMMBRItem& tmmbr_item, 82 uint8_t* buffer, 83 size_t* pos) { 84 AssignUWord32(buffer, pos, tmmbr.SenderSSRC); 85 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 86 CreateTmmbrItem(tmmbr_item, buffer, pos); 87 } 88 } // namespace 89 90 bool Tmmbr::Create(uint8_t* packet, 91 size_t* index, 92 size_t max_length, 93 RtcpPacket::PacketReadyCallback* callback) const { 94 while (*index + BlockLength() > max_length) { 95 if (!OnBufferFull(packet, index, callback)) 96 return false; 97 } 98 const uint8_t kFmt = 3; 99 CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index); 100 CreateTmmbr(tmmbr_, tmmbr_item_, packet, index); 101 return true; 102 } 103 104 } // namespace rtcp 105 } // namespace webrtc 106