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