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