summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc')
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc148
1 files changed, 148 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc
new file mode 100644
index 0000000000..ca59791248
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/remote_estimate.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/rtp_rtcp/source/rtcp_packet/remote_estimate.h"
+
+#include <algorithm>
+#include <cmath>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace rtcp {
+namespace {
+
+static constexpr int kFieldValueSize = 3;
+static constexpr int kFieldSize = 1 + kFieldValueSize;
+static constexpr DataRate kDataRateResolution = DataRate::KilobitsPerSec(1);
+constexpr int64_t kMaxEncoded = (1 << (kFieldValueSize * 8)) - 1;
+
+class DataRateSerializer {
+ public:
+ DataRateSerializer(
+ uint8_t id,
+ std::function<DataRate*(NetworkStateEstimate*)> field_getter)
+ : id_(id), field_getter_(field_getter) {}
+
+ uint8_t id() const { return id_; }
+
+ void Read(const uint8_t* src, NetworkStateEstimate* target) const {
+ int64_t scaled = ByteReader<uint32_t, kFieldValueSize>::ReadBigEndian(src);
+ if (scaled == kMaxEncoded) {
+ *field_getter_(target) = DataRate::PlusInfinity();
+ } else {
+ *field_getter_(target) = kDataRateResolution * scaled;
+ }
+ }
+
+ bool Write(const NetworkStateEstimate& src, uint8_t* target) const {
+ auto value = *field_getter_(const_cast<NetworkStateEstimate*>(&src));
+ if (value.IsMinusInfinity()) {
+ RTC_LOG(LS_WARNING) << "Trying to serialize MinusInfinity";
+ return false;
+ }
+ ByteWriter<uint8_t>::WriteBigEndian(target++, id_);
+ int64_t scaled;
+ if (value.IsPlusInfinity()) {
+ scaled = kMaxEncoded;
+ } else {
+ scaled = value / kDataRateResolution;
+ if (scaled >= kMaxEncoded) {
+ scaled = kMaxEncoded;
+ RTC_LOG(LS_WARNING) << ToString(value) << " is larger than max ("
+ << ToString(kMaxEncoded * kDataRateResolution)
+ << "), encoded as PlusInfinity.";
+ }
+ }
+ ByteWriter<uint32_t, kFieldValueSize>::WriteBigEndian(target, scaled);
+ return true;
+ }
+
+ private:
+ const uint8_t id_;
+ const std::function<DataRate*(NetworkStateEstimate*)> field_getter_;
+};
+
+class RemoteEstimateSerializerImpl : public RemoteEstimateSerializer {
+ public:
+ explicit RemoteEstimateSerializerImpl(std::vector<DataRateSerializer> fields)
+ : fields_(fields) {}
+
+ rtc::Buffer Serialize(const NetworkStateEstimate& src) const override {
+ size_t max_size = fields_.size() * kFieldSize;
+ size_t size = 0;
+ rtc::Buffer buf(max_size);
+ for (const auto& field : fields_) {
+ if (field.Write(src, buf.data() + size)) {
+ size += kFieldSize;
+ }
+ }
+ buf.SetSize(size);
+ return buf;
+ }
+
+ bool Parse(rtc::ArrayView<const uint8_t> src,
+ NetworkStateEstimate* target) const override {
+ if (src.size() % kFieldSize != 0)
+ return false;
+ RTC_DCHECK_EQ(src.size() % kFieldSize, 0);
+ for (const uint8_t* data_ptr = src.data(); data_ptr < src.end();
+ data_ptr += kFieldSize) {
+ uint8_t field_id = ByteReader<uint8_t>::ReadBigEndian(data_ptr);
+ for (const auto& field : fields_) {
+ if (field.id() == field_id) {
+ field.Read(data_ptr + 1, target);
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ private:
+ const std::vector<DataRateSerializer> fields_;
+};
+
+} // namespace
+
+const RemoteEstimateSerializer* GetRemoteEstimateSerializer() {
+ using E = NetworkStateEstimate;
+ static auto* serializer = new RemoteEstimateSerializerImpl({
+ {1, [](E* e) { return &e->link_capacity_lower; }},
+ {2, [](E* e) { return &e->link_capacity_upper; }},
+ });
+ return serializer;
+}
+
+RemoteEstimate::RemoteEstimate() : serializer_(GetRemoteEstimateSerializer()) {
+ SetSubType(kSubType);
+ SetName(kName);
+ SetSenderSsrc(0);
+}
+
+RemoteEstimate::RemoteEstimate(App&& app)
+ : App(std::move(app)), serializer_(GetRemoteEstimateSerializer()) {}
+
+bool RemoteEstimate::ParseData() {
+ return serializer_->Parse({data(), data_size()}, &estimate_);
+}
+
+void RemoteEstimate::SetEstimate(NetworkStateEstimate estimate) {
+ estimate_ = estimate;
+ auto buf = serializer_->Serialize(estimate);
+ SetData(buf.data(), buf.size());
+}
+
+} // namespace rtcp
+} // namespace webrtc