xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 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 #include "modules/rtp_rtcp/source/rtcp_packet/remote_estimate.h"
11 
12 #include <algorithm>
13 #include <cmath>
14 #include <type_traits>
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 "rtc_base/logging.h"
21 
22 namespace webrtc {
23 namespace rtcp {
24 namespace {
25 
26 static constexpr int kFieldValueSize = 3;
27 static constexpr int kFieldSize = 1 + kFieldValueSize;
28 static constexpr DataRate kDataRateResolution = DataRate::KilobitsPerSec(1);
29 constexpr int64_t kMaxEncoded = (1 << (kFieldValueSize * 8)) - 1;
30 
31 class DataRateSerializer {
32  public:
DataRateSerializer(uint8_t id,std::function<DataRate * (NetworkStateEstimate *)> field_getter)33   DataRateSerializer(
34       uint8_t id,
35       std::function<DataRate*(NetworkStateEstimate*)> field_getter)
36       : id_(id), field_getter_(field_getter) {}
37 
id() const38   uint8_t id() const { return id_; }
39 
Read(const uint8_t * src,NetworkStateEstimate * target) const40   void Read(const uint8_t* src, NetworkStateEstimate* target) const {
41     int64_t scaled = ByteReader<uint32_t, kFieldValueSize>::ReadBigEndian(src);
42     if (scaled == kMaxEncoded) {
43       *field_getter_(target) = DataRate::PlusInfinity();
44     } else {
45       *field_getter_(target) = kDataRateResolution * scaled;
46     }
47   }
48 
Write(const NetworkStateEstimate & src,uint8_t * target) const49   bool Write(const NetworkStateEstimate& src, uint8_t* target) const {
50     auto value = *field_getter_(const_cast<NetworkStateEstimate*>(&src));
51     if (value.IsMinusInfinity()) {
52       RTC_LOG(LS_WARNING) << "Trying to serialize MinusInfinity";
53       return false;
54     }
55     ByteWriter<uint8_t>::WriteBigEndian(target++, id_);
56     int64_t scaled;
57     if (value.IsPlusInfinity()) {
58       scaled = kMaxEncoded;
59     } else {
60       scaled = value / kDataRateResolution;
61       if (scaled >= kMaxEncoded) {
62         scaled = kMaxEncoded;
63         RTC_LOG(LS_WARNING) << ToString(value) << " is larger than max ("
64                             << ToString(kMaxEncoded * kDataRateResolution)
65                             << "), encoded as PlusInfinity.";
66       }
67     }
68     ByteWriter<uint32_t, kFieldValueSize>::WriteBigEndian(target, scaled);
69     return true;
70   }
71 
72  private:
73   const uint8_t id_;
74   const std::function<DataRate*(NetworkStateEstimate*)> field_getter_;
75 };
76 
77 class RemoteEstimateSerializerImpl : public RemoteEstimateSerializer {
78  public:
RemoteEstimateSerializerImpl(std::vector<DataRateSerializer> fields)79   explicit RemoteEstimateSerializerImpl(std::vector<DataRateSerializer> fields)
80       : fields_(fields) {}
81 
Serialize(const NetworkStateEstimate & src) const82   rtc::Buffer Serialize(const NetworkStateEstimate& src) const override {
83     size_t max_size = fields_.size() * kFieldSize;
84     size_t size = 0;
85     rtc::Buffer buf(max_size);
86     for (const auto& field : fields_) {
87       if (field.Write(src, buf.data() + size)) {
88         size += kFieldSize;
89       }
90     }
91     buf.SetSize(size);
92     return buf;
93   }
94 
Parse(rtc::ArrayView<const uint8_t> src,NetworkStateEstimate * target) const95   bool Parse(rtc::ArrayView<const uint8_t> src,
96              NetworkStateEstimate* target) const override {
97     if (src.size() % kFieldSize != 0)
98       return false;
99     RTC_DCHECK_EQ(src.size() % kFieldSize, 0);
100     for (const uint8_t* data_ptr = src.data(); data_ptr < src.end();
101          data_ptr += kFieldSize) {
102       uint8_t field_id = ByteReader<uint8_t>::ReadBigEndian(data_ptr);
103       for (const auto& field : fields_) {
104         if (field.id() == field_id) {
105           field.Read(data_ptr + 1, target);
106           break;
107         }
108       }
109     }
110     return true;
111   }
112 
113  private:
114   const std::vector<DataRateSerializer> fields_;
115 };
116 
117 }  // namespace
118 
GetRemoteEstimateSerializer()119 const RemoteEstimateSerializer* GetRemoteEstimateSerializer() {
120   using E = NetworkStateEstimate;
121   static auto* serializer = new RemoteEstimateSerializerImpl({
122       {1, [](E* e) { return &e->link_capacity_lower; }},
123       {2, [](E* e) { return &e->link_capacity_upper; }},
124   });
125   return serializer;
126 }
127 
RemoteEstimate()128 RemoteEstimate::RemoteEstimate() : serializer_(GetRemoteEstimateSerializer()) {
129   SetSubType(kSubType);
130   SetName(kName);
131   SetSenderSsrc(0);
132 }
133 
RemoteEstimate(App && app)134 RemoteEstimate::RemoteEstimate(App&& app)
135     : App(std::move(app)), serializer_(GetRemoteEstimateSerializer()) {}
136 
ParseData()137 bool RemoteEstimate::ParseData() {
138   return serializer_->Parse({data(), data_size()}, &estimate_);
139 }
140 
SetEstimate(NetworkStateEstimate estimate)141 void RemoteEstimate::SetEstimate(NetworkStateEstimate estimate) {
142   estimate_ = estimate;
143   auto buf = serializer_->Serialize(estimate);
144   SetData(buf.data(), buf.size());
145 }
146 
147 }  // namespace rtcp
148 }  // namespace webrtc
149