tmmbn.cc revision ef3d805f6e50bc488f8e4e9e353068b78c73d17f
1ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap/* 2ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * 4ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * Use of this source code is governed by a BSD-style license 5ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * that can be found in the LICENSE file in the root of the source 6ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * tree. An additional intellectual property rights grant can be found 7ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * in the file PATENTS. All contributing project authors may 8ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap * be found in the AUTHORS file in the root of the source tree. 9ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap */ 10ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 11ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h" 12ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 13ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap#include "webrtc/base/logging.h" 14ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 15ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 16ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapusing webrtc::RTCPUtility::PT_RTPFB; 17ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapusing webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN; 18ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapusing webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem; 19ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 20ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapnamespace webrtc { 21ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapnamespace rtcp { 22ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapnamespace { 23ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapconst uint32_t kUnusedMediaSourceSsrc0 = 0; 24ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapvoid AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) { 25ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap buffer[(*offset)++] = value; 26ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 27ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapvoid AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { 28ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value); 29ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap *offset += 4; 30ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 31ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 32ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapvoid ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10, 33ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint8_t bits_mantissa, 34ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint32_t* mantissa, 35ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint8_t* exp) { 36ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap // input_base10 = mantissa * 2^exp 37ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap assert(bits_mantissa <= 32); 38ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint32_t mantissa_max = (1 << bits_mantissa) - 1; 39ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint8_t exponent = 0; 40ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap for (uint32_t i = 0; i < 64; ++i) { 41ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap if (input_base10 <= (mantissa_max << i)) { 42ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap exponent = i; 43ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap break; 44ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap } 45ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap } 46ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap *exp = exponent; 47ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap *mantissa = (input_base10 >> exponent); 48ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 49ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 50ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapvoid CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item, 51ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint8_t* buffer, 52ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap size_t* pos) { 53ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000; 54ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint32_t mantissa = 0; 55ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint8_t exp = 0; 56ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp); 57ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 58ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord32(buffer, pos, tmmbr_item.SSRC); 59ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03)); 60ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord8(buffer, pos, mantissa >> 7); 61ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord8(buffer, pos, (mantissa << 1) + 62ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap ((tmmbr_item.MeasuredOverhead >> 8) & 0x01)); 63ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead); 64ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 65ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 66ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104). 67ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// 68ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// FCI: 69ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// 70ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// 0 1 2 3 71ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// 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 72ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 73ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// | SSRC | 74ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 75ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| 76ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 77ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 78ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapvoid CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn, 79ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items, 80ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap uint8_t* buffer, 81ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap size_t* pos) { 82ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord32(buffer, pos, tmmbn.SenderSSRC); 83ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 84ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap for (uint8_t i = 0; i < tmmbn_items.size(); ++i) { 85ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap CreateTmmbrItem(tmmbn_items[i], buffer, pos); 86ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap } 87ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 88ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} // namespace 89ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 90ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapbool Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) { 91ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap assert(overhead <= 0x1ff); 92ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) { 93ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap LOG(LS_WARNING) << "Max TMMBN size reached."; 94ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap return false; 95ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap } 96ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap RTCPPacketRTPFBTMMBRItem tmmbn_item; 97ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap tmmbn_item.SSRC = ssrc; 98ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps; 99ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap tmmbn_item.MeasuredOverhead = overhead; 100ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap tmmbn_items_.push_back(tmmbn_item); 101ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap return true; 102ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 103ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 104ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchapbool Tmmbn::Create(uint8_t* packet, 105ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap size_t* index, 106ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap size_t max_length, 107ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap RtcpPacket::PacketReadyCallback* callback) const { 108ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap while (*index + BlockLength() > max_length) { 109ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap if (!OnBufferFull(packet, index, callback)) 110ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap return false; 111ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap } 112ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap const uint8_t kFmt = 4; 113ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index); 114ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap CreateTmmbn(tmmbn_, tmmbn_items_, packet, index); 115ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap return true; 116ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} 117ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap 118ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} // namespace rtcp 119ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap} // namespace webrtc 120