diff options
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.cc | 148 |
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 |