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