tmmbr.cc (4344B)
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/tmmbr.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 16 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h" 17 #include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" 18 #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" 19 #include "rtc_base/checks.h" 20 #include "rtc_base/logging.h" 21 22 namespace webrtc { 23 namespace rtcp { 24 // RFC 4585: Feedback format. 25 // Common packet format: 26 // 27 // 0 1 2 3 28 // 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 29 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 30 // |V=2|P| FMT | PT | length | 31 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 32 // | SSRC of packet sender | 33 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 34 // | SSRC of media source (unused) = 0 | 35 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 36 // : Feedback Control Information (FCI) : 37 // : : 38 // Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). 39 // The Feedback Control Information (FCI) for the TMMBR 40 // consists of one or more FCI entries. 41 // FCI: 42 // 0 1 2 3 43 // 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 44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45 // | SSRC | 46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47 // | MxTBR Exp | MxTBR Mantissa |Measured Overhead| 48 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 49 50 Tmmbr::Tmmbr() = default; 51 52 Tmmbr::~Tmmbr() = default; 53 54 bool Tmmbr::Parse(const CommonHeader& packet) { 55 RTC_DCHECK_EQ(packet.type(), kPacketType); 56 RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType); 57 58 if (packet.payload_size_bytes() < kCommonFeedbackLength + TmmbItem::kLength) { 59 RTC_LOG(LS_WARNING) << "Payload length " << packet.payload_size_bytes() 60 << " is too small for a TMMBR."; 61 return false; 62 } 63 size_t items_size_bytes = packet.payload_size_bytes() - kCommonFeedbackLength; 64 if (items_size_bytes % TmmbItem::kLength != 0) { 65 RTC_LOG(LS_WARNING) << "Payload length " << packet.payload_size_bytes() 66 << " is not valid for a TMMBR."; 67 return false; 68 } 69 ParseCommonFeedback(packet.payload()); 70 71 const uint8_t* next_item = packet.payload() + kCommonFeedbackLength; 72 size_t number_of_items = items_size_bytes / TmmbItem::kLength; 73 items_.resize(number_of_items); 74 for (TmmbItem& item : items_) { 75 if (!item.Parse(next_item)) 76 return false; 77 next_item += TmmbItem::kLength; 78 } 79 return true; 80 } 81 82 void Tmmbr::AddTmmbr(const TmmbItem& item) { 83 items_.push_back(item); 84 } 85 86 size_t Tmmbr::BlockLength() const { 87 return kHeaderLength + kCommonFeedbackLength + 88 TmmbItem::kLength * items_.size(); 89 } 90 91 bool Tmmbr::Create(uint8_t* packet, 92 size_t* index, 93 size_t max_length, 94 PacketReadyCallback callback) const { 95 RTC_DCHECK(!items_.empty()); 96 while (*index + BlockLength() > max_length) { 97 if (!OnBufferFull(packet, index, callback)) 98 return false; 99 } 100 const size_t index_end = *index + BlockLength(); 101 102 CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet, 103 index); 104 RTC_DCHECK_EQ(0, Rtpfb::media_ssrc()); 105 CreateCommonFeedback(packet + *index); 106 *index += kCommonFeedbackLength; 107 for (const TmmbItem& item : items_) { 108 item.Create(packet + *index); 109 *index += TmmbItem::kLength; 110 } 111 RTC_CHECK_EQ(index_end, *index); 112 return true; 113 } 114 } // namespace rtcp 115 } // namespace webrtc