summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/congestion_controller/rtp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/congestion_controller/rtp')
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/BUILD.gn100
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.cc87
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.h54
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/control_handler_gn/moz.build237
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.cc275
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.h102
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter_unittest.cc401
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.cc95
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.h62
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer_unittest.cc99
-rw-r--r--third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_gn/moz.build237
11 files changed, 1749 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/BUILD.gn b/third_party/libwebrtc/modules/congestion_controller/rtp/BUILD.gn
new file mode 100644
index 0000000000..cd13332b7f
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/BUILD.gn
@@ -0,0 +1,100 @@
+# Copyright (c) 2014 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.
+
+import("../../../webrtc.gni")
+
+config("bwe_test_logging") {
+ if (rtc_enable_bwe_test_logging) {
+ defines = [ "BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=1" ]
+ } else {
+ defines = [ "BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=0" ]
+ }
+}
+
+rtc_library("control_handler") {
+ visibility = [ "*" ]
+ sources = [
+ "control_handler.cc",
+ "control_handler.h",
+ ]
+
+ deps = [
+ "../../../api:sequence_checker",
+ "../../../api/transport:network_control",
+ "../../../api/units:data_rate",
+ "../../../api/units:data_size",
+ "../../../api/units:time_delta",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ "../../../rtc_base:safe_conversions",
+ "../../../rtc_base:safe_minmax",
+ "../../../rtc_base/system:no_unique_address",
+ "../../../system_wrappers:field_trial",
+ "../../pacing",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+rtc_library("transport_feedback") {
+ visibility = [ "*" ]
+ sources = [
+ "transport_feedback_adapter.cc",
+ "transport_feedback_adapter.h",
+ "transport_feedback_demuxer.cc",
+ "transport_feedback_demuxer.h",
+ ]
+
+ deps = [
+ "../..:module_api_public",
+ "../../../api:sequence_checker",
+ "../../../api/transport:network_control",
+ "../../../api/units:data_size",
+ "../../../api/units:timestamp",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ "../../../rtc_base:macromagic",
+ "../../../rtc_base:network_route",
+ "../../../rtc_base:rtc_numerics",
+ "../../../rtc_base/network:sent_packet",
+ "../../../rtc_base/synchronization:mutex",
+ "../../../rtc_base/system:no_unique_address",
+ "../../../system_wrappers",
+ "../../../system_wrappers:field_trial",
+ "../../rtp_rtcp:rtp_rtcp_format",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+if (rtc_include_tests) {
+ rtc_library("congestion_controller_unittests") {
+ testonly = true
+
+ sources = [
+ "transport_feedback_adapter_unittest.cc",
+ "transport_feedback_demuxer_unittest.cc",
+ ]
+ deps = [
+ ":transport_feedback",
+ "../:congestion_controller",
+ "../../../api/transport:network_control",
+ "../../../logging:mocks",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:safe_conversions",
+ "../../../rtc_base/network:sent_packet",
+ "../../../system_wrappers",
+ "../../../test:field_trial",
+ "../../../test:test_support",
+ "../../pacing",
+ "../../remote_bitrate_estimator",
+ "../../rtp_rtcp:rtp_rtcp_format",
+ "//testing/gmock",
+ ]
+ }
+}
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.cc b/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.cc
new file mode 100644
index 0000000000..da6451c97e
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018 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/congestion_controller/rtp/control_handler.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "api/units/data_rate.h"
+#include "modules/pacing/pacing_controller.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/numerics/safe_minmax.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+namespace {
+
+// By default, pacer emergency stops encoder when buffer reaches a high level.
+bool IsPacerEmergencyStopDisabled() {
+ return field_trial::IsEnabled("WebRTC-DisablePacerEmergencyStop");
+}
+
+} // namespace
+CongestionControlHandler::CongestionControlHandler()
+ : disable_pacer_emergency_stop_(IsPacerEmergencyStopDisabled()) {}
+
+CongestionControlHandler::~CongestionControlHandler() {}
+
+void CongestionControlHandler::SetTargetRate(
+ TargetTransferRate new_target_rate) {
+ RTC_DCHECK_RUN_ON(&sequenced_checker_);
+ RTC_CHECK(new_target_rate.at_time.IsFinite());
+ last_incoming_ = new_target_rate;
+}
+
+void CongestionControlHandler::SetNetworkAvailability(bool network_available) {
+ RTC_DCHECK_RUN_ON(&sequenced_checker_);
+ network_available_ = network_available;
+}
+
+void CongestionControlHandler::SetPacerQueue(TimeDelta expected_queue_time) {
+ RTC_DCHECK_RUN_ON(&sequenced_checker_);
+ pacer_expected_queue_ms_ = expected_queue_time.ms();
+}
+
+absl::optional<TargetTransferRate> CongestionControlHandler::GetUpdate() {
+ RTC_DCHECK_RUN_ON(&sequenced_checker_);
+ if (!last_incoming_.has_value())
+ return absl::nullopt;
+ TargetTransferRate new_outgoing = *last_incoming_;
+ DataRate log_target_rate = new_outgoing.target_rate;
+ bool pause_encoding = false;
+ if (!network_available_) {
+ pause_encoding = true;
+ } else if (!disable_pacer_emergency_stop_ &&
+ pacer_expected_queue_ms_ >
+ PacingController::kMaxExpectedQueueLength.ms()) {
+ pause_encoding = true;
+ }
+ if (pause_encoding)
+ new_outgoing.target_rate = DataRate::Zero();
+ if (!last_reported_ ||
+ last_reported_->target_rate != new_outgoing.target_rate ||
+ (!new_outgoing.target_rate.IsZero() &&
+ (last_reported_->network_estimate.loss_rate_ratio !=
+ new_outgoing.network_estimate.loss_rate_ratio ||
+ last_reported_->network_estimate.round_trip_time !=
+ new_outgoing.network_estimate.round_trip_time))) {
+ if (encoder_paused_in_last_report_ != pause_encoding)
+ RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: "
+ << ToString(log_target_rate) << ".";
+ encoder_paused_in_last_report_ = pause_encoding;
+ last_reported_ = new_outgoing;
+ return new_outgoing;
+ }
+ return absl::nullopt;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.h b/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.h
new file mode 100644
index 0000000000..d8e7263a02
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 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.
+ */
+
+#ifndef MODULES_CONGESTION_CONTROLLER_RTP_CONTROL_HANDLER_H_
+#define MODULES_CONGESTION_CONTROLLER_RTP_CONTROL_HANDLER_H_
+
+#include <stdint.h>
+
+#include "absl/types/optional.h"
+#include "api/sequence_checker.h"
+#include "api/transport/network_types.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
+#include "rtc_base/system/no_unique_address.h"
+
+namespace webrtc {
+// This is used to observe the network controller state and route calls to
+// the proper handler. It also keeps cached values for safe asynchronous use.
+// This makes sure that things running on the worker queue can't access state
+// in RtpTransportControllerSend, which would risk causing data race on
+// destruction unless members are properly ordered.
+class CongestionControlHandler {
+ public:
+ CongestionControlHandler();
+ ~CongestionControlHandler();
+
+ CongestionControlHandler(const CongestionControlHandler&) = delete;
+ CongestionControlHandler& operator=(const CongestionControlHandler&) = delete;
+
+ void SetTargetRate(TargetTransferRate new_target_rate);
+ void SetNetworkAvailability(bool network_available);
+ void SetPacerQueue(TimeDelta expected_queue_time);
+ absl::optional<TargetTransferRate> GetUpdate();
+
+ private:
+ absl::optional<TargetTransferRate> last_incoming_;
+ absl::optional<TargetTransferRate> last_reported_;
+ bool network_available_ = true;
+ bool encoder_paused_in_last_report_ = false;
+
+ const bool disable_pacer_emergency_stop_;
+ int64_t pacer_expected_queue_ms_ = 0;
+
+ RTC_NO_UNIQUE_ADDRESS SequenceChecker sequenced_checker_;
+};
+} // namespace webrtc
+#endif // MODULES_CONGESTION_CONTROLLER_RTP_CONTROL_HANDLER_H_
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler_gn/moz.build b/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler_gn/moz.build
new file mode 100644
index 0000000000..7e8cb87820
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler_gn/moz.build
@@ -0,0 +1,237 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+ ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ###
+ ### DO NOT edit it by hand. ###
+
+COMPILE_FLAGS["OS_INCLUDES"] = []
+AllowCompilerWarnings()
+
+DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1"
+DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True
+DEFINES["RTC_ENABLE_VP9"] = True
+DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0"
+DEFINES["WEBRTC_LIBRARY_IMPL"] = True
+DEFINES["WEBRTC_MOZILLA_BUILD"] = True
+DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0"
+DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0"
+
+FINAL_LIBRARY = "webrtc"
+
+
+LOCAL_INCLUDES += [
+ "!/ipc/ipdl/_ipdlheaders",
+ "!/third_party/libwebrtc/gen",
+ "/ipc/chromium/src",
+ "/third_party/libwebrtc/",
+ "/third_party/libwebrtc/third_party/abseil-cpp/",
+ "/tools/profiler/public"
+]
+
+UNIFIED_SOURCES += [
+ "/third_party/libwebrtc/modules/congestion_controller/rtp/control_handler.cc"
+]
+
+if not CONFIG["MOZ_DEBUG"]:
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0"
+ DEFINES["NDEBUG"] = True
+ DEFINES["NVALGRIND"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1":
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["ANDROID"] = True
+ DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1"
+ DEFINES["HAVE_SYS_UIO_H"] = True
+ DEFINES["WEBRTC_ANDROID"] = True
+ DEFINES["WEBRTC_ANDROID_OPENSLES"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_GNU_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+ OS_LIBS += [
+ "GLESv2",
+ "log"
+ ]
+
+if CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["WEBRTC_MAC"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True
+ DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0"
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_NSS_CERTS"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_UDEV"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+ OS_LIBS += [
+ "rt"
+ ]
+
+if CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_X11"] = "1"
+ DEFINES["WEBRTC_BSD"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True
+ DEFINES["NOMINMAX"] = True
+ DEFINES["NTDDI_VERSION"] = "0x0A000000"
+ DEFINES["PSAPI_VERSION"] = "2"
+ DEFINES["RTC_ENABLE_WIN_WGC"] = True
+ DEFINES["UNICODE"] = True
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["WEBRTC_WIN"] = True
+ DEFINES["WIN32"] = True
+ DEFINES["WIN32_LEAN_AND_MEAN"] = True
+ DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP"
+ DEFINES["WINVER"] = "0x0A00"
+ DEFINES["_ATL_NO_OPENGL"] = True
+ DEFINES["_CRT_RAND_S"] = True
+ DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True
+ DEFINES["_HAS_EXCEPTIONS"] = "0"
+ DEFINES["_HAS_NODISCARD"] = True
+ DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_SECURE_ATL"] = True
+ DEFINES["_UNICODE"] = True
+ DEFINES["_WIN32_WINNT"] = "0x0A00"
+ DEFINES["_WINDOWS"] = True
+ DEFINES["__STD_C"] = True
+
+ OS_LIBS += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "x86_64":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0"
+
+if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_X11"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+Library("control_handler_gn")
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.cc b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.cc
new file mode 100644
index 0000000000..be17e50472
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.cc
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015 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/congestion_controller/rtp/transport_feedback_adapter.h"
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <cmath>
+#include <utility>
+
+#include "absl/algorithm/container.h"
+#include "api/units/timestamp.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+constexpr TimeDelta kSendTimeHistoryWindow = TimeDelta::Seconds(60);
+
+void InFlightBytesTracker::AddInFlightPacketBytes(
+ const PacketFeedback& packet) {
+ RTC_DCHECK(packet.sent.send_time.IsFinite());
+ auto it = in_flight_data_.find(packet.network_route);
+ if (it != in_flight_data_.end()) {
+ it->second += packet.sent.size;
+ } else {
+ in_flight_data_.insert({packet.network_route, packet.sent.size});
+ }
+}
+
+void InFlightBytesTracker::RemoveInFlightPacketBytes(
+ const PacketFeedback& packet) {
+ if (packet.sent.send_time.IsInfinite())
+ return;
+ auto it = in_flight_data_.find(packet.network_route);
+ if (it != in_flight_data_.end()) {
+ RTC_DCHECK_GE(it->second, packet.sent.size);
+ it->second -= packet.sent.size;
+ if (it->second.IsZero())
+ in_flight_data_.erase(it);
+ }
+}
+
+DataSize InFlightBytesTracker::GetOutstandingData(
+ const rtc::NetworkRoute& network_route) const {
+ auto it = in_flight_data_.find(network_route);
+ if (it != in_flight_data_.end()) {
+ return it->second;
+ } else {
+ return DataSize::Zero();
+ }
+}
+
+// Comparator for consistent map with NetworkRoute as key.
+bool InFlightBytesTracker::NetworkRouteComparator::operator()(
+ const rtc::NetworkRoute& a,
+ const rtc::NetworkRoute& b) const {
+ if (a.local.network_id() != b.local.network_id())
+ return a.local.network_id() < b.local.network_id();
+ if (a.remote.network_id() != b.remote.network_id())
+ return a.remote.network_id() < b.remote.network_id();
+
+ if (a.local.adapter_id() != b.local.adapter_id())
+ return a.local.adapter_id() < b.local.adapter_id();
+ if (a.remote.adapter_id() != b.remote.adapter_id())
+ return a.remote.adapter_id() < b.remote.adapter_id();
+
+ if (a.local.uses_turn() != b.local.uses_turn())
+ return a.local.uses_turn() < b.local.uses_turn();
+ if (a.remote.uses_turn() != b.remote.uses_turn())
+ return a.remote.uses_turn() < b.remote.uses_turn();
+
+ return a.connected < b.connected;
+}
+
+TransportFeedbackAdapter::TransportFeedbackAdapter() = default;
+
+void TransportFeedbackAdapter::AddPacket(const RtpPacketSendInfo& packet_info,
+ size_t overhead_bytes,
+ Timestamp creation_time) {
+ PacketFeedback packet;
+ packet.creation_time = creation_time;
+ packet.sent.sequence_number =
+ seq_num_unwrapper_.Unwrap(packet_info.transport_sequence_number);
+ packet.sent.size = DataSize::Bytes(packet_info.length + overhead_bytes);
+ packet.sent.audio = packet_info.packet_type == RtpPacketMediaType::kAudio;
+ packet.network_route = network_route_;
+ packet.sent.pacing_info = packet_info.pacing_info;
+
+ while (!history_.empty() &&
+ creation_time - history_.begin()->second.creation_time >
+ kSendTimeHistoryWindow) {
+ // TODO(sprang): Warn if erasing (too many) old items?
+ if (history_.begin()->second.sent.sequence_number > last_ack_seq_num_)
+ in_flight_.RemoveInFlightPacketBytes(history_.begin()->second);
+ history_.erase(history_.begin());
+ }
+ history_.insert(std::make_pair(packet.sent.sequence_number, packet));
+}
+
+absl::optional<SentPacket> TransportFeedbackAdapter::ProcessSentPacket(
+ const rtc::SentPacket& sent_packet) {
+ auto send_time = Timestamp::Millis(sent_packet.send_time_ms);
+ // TODO(srte): Only use one way to indicate that packet feedback is used.
+ if (sent_packet.info.included_in_feedback || sent_packet.packet_id != -1) {
+ int64_t unwrapped_seq_num =
+ seq_num_unwrapper_.Unwrap(sent_packet.packet_id);
+ auto it = history_.find(unwrapped_seq_num);
+ if (it != history_.end()) {
+ bool packet_retransmit = it->second.sent.send_time.IsFinite();
+ it->second.sent.send_time = send_time;
+ last_send_time_ = std::max(last_send_time_, send_time);
+ // TODO(srte): Don't do this on retransmit.
+ if (!pending_untracked_size_.IsZero()) {
+ if (send_time < last_untracked_send_time_)
+ RTC_LOG(LS_WARNING)
+ << "appending acknowledged data for out of order packet. (Diff: "
+ << ToString(last_untracked_send_time_ - send_time) << " ms.)";
+ it->second.sent.prior_unacked_data += pending_untracked_size_;
+ pending_untracked_size_ = DataSize::Zero();
+ }
+ if (!packet_retransmit) {
+ if (it->second.sent.sequence_number > last_ack_seq_num_)
+ in_flight_.AddInFlightPacketBytes(it->second);
+ it->second.sent.data_in_flight = GetOutstandingData();
+ return it->second.sent;
+ }
+ }
+ } else if (sent_packet.info.included_in_allocation) {
+ if (send_time < last_send_time_) {
+ RTC_LOG(LS_WARNING) << "ignoring untracked data for out of order packet.";
+ }
+ pending_untracked_size_ +=
+ DataSize::Bytes(sent_packet.info.packet_size_bytes);
+ last_untracked_send_time_ = std::max(last_untracked_send_time_, send_time);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<TransportPacketsFeedback>
+TransportFeedbackAdapter::ProcessTransportFeedback(
+ const rtcp::TransportFeedback& feedback,
+ Timestamp feedback_receive_time) {
+ if (feedback.GetPacketStatusCount() == 0) {
+ RTC_LOG(LS_INFO) << "Empty transport feedback packet received.";
+ return absl::nullopt;
+ }
+
+ TransportPacketsFeedback msg;
+ msg.feedback_time = feedback_receive_time;
+
+ msg.prior_in_flight = in_flight_.GetOutstandingData(network_route_);
+ msg.packet_feedbacks =
+ ProcessTransportFeedbackInner(feedback, feedback_receive_time);
+ if (msg.packet_feedbacks.empty())
+ return absl::nullopt;
+
+ auto it = history_.find(last_ack_seq_num_);
+ if (it != history_.end()) {
+ msg.first_unacked_send_time = it->second.sent.send_time;
+ }
+ msg.data_in_flight = in_flight_.GetOutstandingData(network_route_);
+
+ return msg;
+}
+
+void TransportFeedbackAdapter::SetNetworkRoute(
+ const rtc::NetworkRoute& network_route) {
+ network_route_ = network_route;
+}
+
+DataSize TransportFeedbackAdapter::GetOutstandingData() const {
+ return in_flight_.GetOutstandingData(network_route_);
+}
+
+std::vector<PacketResult>
+TransportFeedbackAdapter::ProcessTransportFeedbackInner(
+ const rtcp::TransportFeedback& feedback,
+ Timestamp feedback_receive_time) {
+ // Add timestamp deltas to a local time base selected on first packet arrival.
+ // This won't be the true time base, but makes it easier to manually inspect
+ // time stamps.
+ if (last_timestamp_.IsInfinite()) {
+ current_offset_ = feedback_receive_time;
+ } else {
+ // TODO(srte): We shouldn't need to do rounding here.
+ const TimeDelta delta = feedback.GetBaseDelta(last_timestamp_)
+ .RoundDownTo(TimeDelta::Millis(1));
+ // Protect against assigning current_offset_ negative value.
+ if (delta < Timestamp::Zero() - current_offset_) {
+ RTC_LOG(LS_WARNING) << "Unexpected feedback timestamp received.";
+ current_offset_ = feedback_receive_time;
+ } else {
+ current_offset_ += delta;
+ }
+ }
+ last_timestamp_ = feedback.BaseTime();
+
+ std::vector<PacketResult> packet_result_vector;
+ packet_result_vector.reserve(feedback.GetPacketStatusCount());
+
+ size_t failed_lookups = 0;
+ size_t ignored = 0;
+
+ feedback.ForAllPackets(
+ [&](uint16_t sequence_number, TimeDelta delta_since_base) {
+ int64_t seq_num = seq_num_unwrapper_.Unwrap(sequence_number);
+
+ if (seq_num > last_ack_seq_num_) {
+ // Starts at history_.begin() if last_ack_seq_num_ < 0, since any
+ // valid sequence number is >= 0.
+ for (auto it = history_.upper_bound(last_ack_seq_num_);
+ it != history_.upper_bound(seq_num); ++it) {
+ in_flight_.RemoveInFlightPacketBytes(it->second);
+ }
+ last_ack_seq_num_ = seq_num;
+ }
+
+ auto it = history_.find(seq_num);
+ if (it == history_.end()) {
+ ++failed_lookups;
+ return;
+ }
+
+ if (it->second.sent.send_time.IsInfinite()) {
+ // TODO(srte): Fix the tests that makes this happen and make this a
+ // DCHECK.
+ RTC_DLOG(LS_ERROR)
+ << "Received feedback before packet was indicated as sent";
+ return;
+ }
+
+ PacketFeedback packet_feedback = it->second;
+ if (delta_since_base.IsFinite()) {
+ packet_feedback.receive_time =
+ current_offset_ +
+ delta_since_base.RoundDownTo(TimeDelta::Millis(1));
+ // Note: Lost packets are not removed from history because they might
+ // be reported as received by a later feedback.
+ history_.erase(it);
+ }
+ if (packet_feedback.network_route == network_route_) {
+ PacketResult result;
+ result.sent_packet = packet_feedback.sent;
+ result.receive_time = packet_feedback.receive_time;
+ packet_result_vector.push_back(result);
+ } else {
+ ++ignored;
+ }
+ });
+
+ if (failed_lookups > 0) {
+ RTC_LOG(LS_WARNING) << "Failed to lookup send time for " << failed_lookups
+ << " packet" << (failed_lookups > 1 ? "s" : "")
+ << ". Send time history too small?";
+ }
+ if (ignored > 0) {
+ RTC_LOG(LS_INFO) << "Ignoring " << ignored
+ << " packets because they were sent on a different route.";
+ }
+
+ return packet_result_vector;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.h b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.h
new file mode 100644
index 0000000000..7b1243b64b
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+#ifndef MODULES_CONGESTION_CONTROLLER_RTP_TRANSPORT_FEEDBACK_ADAPTER_H_
+#define MODULES_CONGESTION_CONTROLLER_RTP_TRANSPORT_FEEDBACK_ADAPTER_H_
+
+#include <deque>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "api/sequence_checker.h"
+#include "api/transport/network_types.h"
+#include "api/units/timestamp.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "rtc_base/network/sent_packet.h"
+#include "rtc_base/network_route.h"
+#include "rtc_base/numerics/sequence_number_unwrapper.h"
+#include "rtc_base/thread_annotations.h"
+
+namespace webrtc {
+
+struct PacketFeedback {
+ PacketFeedback() = default;
+ // Time corresponding to when this object was created.
+ Timestamp creation_time = Timestamp::MinusInfinity();
+ SentPacket sent;
+ // Time corresponding to when the packet was received. Timestamped with the
+ // receiver's clock. For unreceived packet, Timestamp::PlusInfinity() is
+ // used.
+ Timestamp receive_time = Timestamp::PlusInfinity();
+
+ // The network route that this packet is associated with.
+ rtc::NetworkRoute network_route;
+};
+
+class InFlightBytesTracker {
+ public:
+ void AddInFlightPacketBytes(const PacketFeedback& packet);
+ void RemoveInFlightPacketBytes(const PacketFeedback& packet);
+ DataSize GetOutstandingData(const rtc::NetworkRoute& network_route) const;
+
+ private:
+ struct NetworkRouteComparator {
+ bool operator()(const rtc::NetworkRoute& a,
+ const rtc::NetworkRoute& b) const;
+ };
+ std::map<rtc::NetworkRoute, DataSize, NetworkRouteComparator> in_flight_data_;
+};
+
+class TransportFeedbackAdapter {
+ public:
+ TransportFeedbackAdapter();
+
+ void AddPacket(const RtpPacketSendInfo& packet_info,
+ size_t overhead_bytes,
+ Timestamp creation_time);
+ absl::optional<SentPacket> ProcessSentPacket(
+ const rtc::SentPacket& sent_packet);
+
+ absl::optional<TransportPacketsFeedback> ProcessTransportFeedback(
+ const rtcp::TransportFeedback& feedback,
+ Timestamp feedback_receive_time);
+
+ void SetNetworkRoute(const rtc::NetworkRoute& network_route);
+
+ DataSize GetOutstandingData() const;
+
+ private:
+ enum class SendTimeHistoryStatus { kNotAdded, kOk, kDuplicate };
+
+ std::vector<PacketResult> ProcessTransportFeedbackInner(
+ const rtcp::TransportFeedback& feedback,
+ Timestamp feedback_receive_time);
+
+ DataSize pending_untracked_size_ = DataSize::Zero();
+ Timestamp last_send_time_ = Timestamp::MinusInfinity();
+ Timestamp last_untracked_send_time_ = Timestamp::MinusInfinity();
+ RtpSequenceNumberUnwrapper seq_num_unwrapper_;
+ std::map<int64_t, PacketFeedback> history_;
+
+ // Sequence numbers are never negative, using -1 as it always < a real
+ // sequence number.
+ int64_t last_ack_seq_num_ = -1;
+ InFlightBytesTracker in_flight_;
+
+ Timestamp current_offset_ = Timestamp::MinusInfinity();
+ Timestamp last_timestamp_ = Timestamp::MinusInfinity();
+
+ rtc::NetworkRoute network_route_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_CONGESTION_CONTROLLER_RTP_TRANSPORT_FEEDBACK_ADAPTER_H_
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter_unittest.cc b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter_unittest.cc
new file mode 100644
index 0000000000..5aad74c46e
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter_unittest.cc
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2015 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/congestion_controller/rtp/transport_feedback_adapter.h"
+
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "system_wrappers/include/clock.h"
+#include "test/field_trial.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+
+namespace webrtc {
+
+namespace {
+constexpr uint32_t kSsrc = 8492;
+const PacedPacketInfo kPacingInfo0(0, 5, 2000);
+const PacedPacketInfo kPacingInfo1(1, 8, 4000);
+const PacedPacketInfo kPacingInfo2(2, 14, 7000);
+const PacedPacketInfo kPacingInfo3(3, 20, 10000);
+const PacedPacketInfo kPacingInfo4(4, 22, 10000);
+
+void ComparePacketFeedbackVectors(const std::vector<PacketResult>& truth,
+ const std::vector<PacketResult>& input) {
+ ASSERT_EQ(truth.size(), input.size());
+ size_t len = truth.size();
+ // truth contains the input data for the test, and input is what will be
+ // sent to the bandwidth estimator. truth.arrival_tims_ms is used to
+ // populate the transport feedback messages. As these times may be changed
+ // (because of resolution limits in the packets, and because of the time
+ // base adjustment performed by the TransportFeedbackAdapter at the first
+ // packet, the truth[x].arrival_time and input[x].arrival_time may not be
+ // equal. However, the difference must be the same for all x.
+ TimeDelta arrival_time_delta = truth[0].receive_time - input[0].receive_time;
+ for (size_t i = 0; i < len; ++i) {
+ RTC_CHECK(truth[i].IsReceived());
+ if (input[i].IsReceived()) {
+ EXPECT_EQ(truth[i].receive_time - input[i].receive_time,
+ arrival_time_delta);
+ }
+ EXPECT_EQ(truth[i].sent_packet.send_time, input[i].sent_packet.send_time);
+ EXPECT_EQ(truth[i].sent_packet.sequence_number,
+ input[i].sent_packet.sequence_number);
+ EXPECT_EQ(truth[i].sent_packet.size, input[i].sent_packet.size);
+ EXPECT_EQ(truth[i].sent_packet.pacing_info,
+ input[i].sent_packet.pacing_info);
+ }
+}
+
+PacketResult CreatePacket(int64_t receive_time_ms,
+ int64_t send_time_ms,
+ int64_t sequence_number,
+ size_t payload_size,
+ const PacedPacketInfo& pacing_info) {
+ PacketResult res;
+ res.receive_time = Timestamp::Millis(receive_time_ms);
+ res.sent_packet.send_time = Timestamp::Millis(send_time_ms);
+ res.sent_packet.sequence_number = sequence_number;
+ res.sent_packet.size = DataSize::Bytes(payload_size);
+ res.sent_packet.pacing_info = pacing_info;
+ return res;
+}
+
+class MockStreamFeedbackObserver : public webrtc::StreamFeedbackObserver {
+ public:
+ MOCK_METHOD(void,
+ OnPacketFeedbackVector,
+ (std::vector<StreamPacketInfo> packet_feedback_vector),
+ (override));
+};
+
+} // namespace
+
+class TransportFeedbackAdapterTest : public ::testing::Test {
+ public:
+ TransportFeedbackAdapterTest() : clock_(0) {}
+
+ virtual ~TransportFeedbackAdapterTest() {}
+
+ virtual void SetUp() { adapter_.reset(new TransportFeedbackAdapter()); }
+
+ virtual void TearDown() { adapter_.reset(); }
+
+ protected:
+ void OnSentPacket(const PacketResult& packet_feedback) {
+ RtpPacketSendInfo packet_info;
+ packet_info.media_ssrc = kSsrc;
+ packet_info.transport_sequence_number =
+ packet_feedback.sent_packet.sequence_number;
+ packet_info.rtp_sequence_number = 0;
+ packet_info.length = packet_feedback.sent_packet.size.bytes();
+ packet_info.pacing_info = packet_feedback.sent_packet.pacing_info;
+ packet_info.packet_type = RtpPacketMediaType::kVideo;
+ adapter_->AddPacket(RtpPacketSendInfo(packet_info), 0u,
+ clock_.CurrentTime());
+ adapter_->ProcessSentPacket(rtc::SentPacket(
+ packet_feedback.sent_packet.sequence_number,
+ packet_feedback.sent_packet.send_time.ms(), rtc::PacketInfo()));
+ }
+
+ SimulatedClock clock_;
+ std::unique_ptr<TransportFeedbackAdapter> adapter_;
+};
+
+TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) {
+ std::vector<PacketResult> packets;
+ packets.push_back(CreatePacket(100, 200, 0, 1500, kPacingInfo0));
+ packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo0));
+ packets.push_back(CreatePacket(120, 220, 2, 1500, kPacingInfo0));
+ packets.push_back(CreatePacket(130, 230, 3, 1500, kPacingInfo1));
+ packets.push_back(CreatePacket(140, 240, 4, 1500, kPacingInfo1));
+
+ for (const auto& packet : packets)
+ OnSentPacket(packet);
+
+ rtcp::TransportFeedback feedback;
+ feedback.SetBase(packets[0].sent_packet.sequence_number,
+ packets[0].receive_time);
+
+ for (const auto& packet : packets) {
+ EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
+ packet.receive_time));
+ }
+
+ feedback.Build();
+
+ auto result =
+ adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
+ ComparePacketFeedbackVectors(packets, result->packet_feedbacks);
+}
+
+TEST_F(TransportFeedbackAdapterTest, FeedbackVectorReportsUnreceived) {
+ std::vector<PacketResult> sent_packets = {
+ CreatePacket(100, 220, 0, 1500, kPacingInfo0),
+ CreatePacket(110, 210, 1, 1500, kPacingInfo0),
+ CreatePacket(120, 220, 2, 1500, kPacingInfo0),
+ CreatePacket(130, 230, 3, 1500, kPacingInfo0),
+ CreatePacket(140, 240, 4, 1500, kPacingInfo0),
+ CreatePacket(150, 250, 5, 1500, kPacingInfo0),
+ CreatePacket(160, 260, 6, 1500, kPacingInfo0)};
+
+ for (const auto& packet : sent_packets)
+ OnSentPacket(packet);
+
+ // Note: Important to include the last packet, as only unreceived packets in
+ // between received packets can be inferred.
+ std::vector<PacketResult> received_packets = {
+ sent_packets[0], sent_packets[2], sent_packets[6]};
+
+ rtcp::TransportFeedback feedback;
+ feedback.SetBase(received_packets[0].sent_packet.sequence_number,
+ received_packets[0].receive_time);
+
+ for (const auto& packet : received_packets) {
+ EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
+ packet.receive_time));
+ }
+
+ feedback.Build();
+
+ auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
+ ComparePacketFeedbackVectors(sent_packets, res->packet_feedbacks);
+}
+
+TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) {
+ std::vector<PacketResult> packets;
+ packets.push_back(CreatePacket(100, 200, 0, 1500, kPacingInfo0));
+ packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo1));
+ packets.push_back(CreatePacket(120, 220, 2, 1500, kPacingInfo2));
+ packets.push_back(CreatePacket(130, 230, 3, 1500, kPacingInfo3));
+ packets.push_back(CreatePacket(140, 240, 4, 1500, kPacingInfo4));
+
+ const uint16_t kSendSideDropBefore = 1;
+ const uint16_t kReceiveSideDropAfter = 3;
+
+ for (const auto& packet : packets) {
+ if (packet.sent_packet.sequence_number >= kSendSideDropBefore)
+ OnSentPacket(packet);
+ }
+
+ rtcp::TransportFeedback feedback;
+ feedback.SetBase(packets[0].sent_packet.sequence_number,
+ packets[0].receive_time);
+
+ for (const auto& packet : packets) {
+ if (packet.sent_packet.sequence_number <= kReceiveSideDropAfter) {
+ EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
+ packet.receive_time));
+ }
+ }
+
+ feedback.Build();
+
+ std::vector<PacketResult> expected_packets(
+ packets.begin() + kSendSideDropBefore,
+ packets.begin() + kReceiveSideDropAfter + 1);
+ // Packets that have timed out on the send-side have lost the
+ // information stored on the send-side. And they will not be reported to
+ // observers since we won't know that they come from the same networks.
+
+ auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
+ ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
+}
+
+TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) {
+ TimeDelta kHighArrivalTime =
+ rtcp::TransportFeedback::kDeltaTick * (1 << 8) * ((1 << 23) - 1);
+ std::vector<PacketResult> packets;
+ packets.push_back(CreatePacket(kHighArrivalTime.ms() + 64, 210, 0, 1500,
+ PacedPacketInfo()));
+ packets.push_back(CreatePacket(kHighArrivalTime.ms() - 64, 210, 1, 1500,
+ PacedPacketInfo()));
+ packets.push_back(
+ CreatePacket(kHighArrivalTime.ms(), 220, 2, 1500, PacedPacketInfo()));
+
+ for (const auto& packet : packets)
+ OnSentPacket(packet);
+
+ for (size_t i = 0; i < packets.size(); ++i) {
+ std::unique_ptr<rtcp::TransportFeedback> feedback(
+ new rtcp::TransportFeedback());
+ feedback->SetBase(packets[i].sent_packet.sequence_number,
+ packets[i].receive_time);
+
+ EXPECT_TRUE(feedback->AddReceivedPacket(
+ packets[i].sent_packet.sequence_number, packets[i].receive_time));
+
+ rtc::Buffer raw_packet = feedback->Build();
+ feedback = rtcp::TransportFeedback::ParseFrom(raw_packet.data(),
+ raw_packet.size());
+
+ std::vector<PacketResult> expected_packets;
+ expected_packets.push_back(packets[i]);
+
+ auto res = adapter_->ProcessTransportFeedback(*feedback.get(),
+ clock_.CurrentTime());
+ ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
+ }
+}
+
+TEST_F(TransportFeedbackAdapterTest, HandlesArrivalReordering) {
+ std::vector<PacketResult> packets;
+ packets.push_back(CreatePacket(120, 200, 0, 1500, kPacingInfo0));
+ packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo0));
+ packets.push_back(CreatePacket(100, 220, 2, 1500, kPacingInfo0));
+
+ for (const auto& packet : packets)
+ OnSentPacket(packet);
+
+ rtcp::TransportFeedback feedback;
+ feedback.SetBase(packets[0].sent_packet.sequence_number,
+ packets[0].receive_time);
+
+ for (const auto& packet : packets) {
+ EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
+ packet.receive_time));
+ }
+
+ feedback.Build();
+
+ // Adapter keeps the packets ordered by sequence number (which is itself
+ // assigned by the order of transmission). Reordering by some other criteria,
+ // eg. arrival time, is up to the observers.
+ auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
+ ComparePacketFeedbackVectors(packets, res->packet_feedbacks);
+}
+
+TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) {
+ std::vector<PacketResult> sent_packets;
+ // TODO(srte): Consider using us resolution in the constants.
+ const TimeDelta kSmallDelta = (rtcp::TransportFeedback::kDeltaTick * 0xFF)
+ .RoundDownTo(TimeDelta::Millis(1));
+ const TimeDelta kLargePositiveDelta = (rtcp::TransportFeedback::kDeltaTick *
+ std::numeric_limits<int16_t>::max())
+ .RoundDownTo(TimeDelta::Millis(1));
+ const TimeDelta kLargeNegativeDelta = (rtcp::TransportFeedback::kDeltaTick *
+ std::numeric_limits<int16_t>::min())
+ .RoundDownTo(TimeDelta::Millis(1));
+
+ PacketResult packet_feedback;
+ packet_feedback.sent_packet.sequence_number = 1;
+ packet_feedback.sent_packet.send_time = Timestamp::Millis(100);
+ packet_feedback.receive_time = Timestamp::Millis(200);
+ packet_feedback.sent_packet.size = DataSize::Bytes(1500);
+ sent_packets.push_back(packet_feedback);
+
+ // TODO(srte): This rounding maintains previous behavior, but should ot be
+ // required.
+ packet_feedback.sent_packet.send_time += kSmallDelta;
+ packet_feedback.receive_time += kSmallDelta;
+ ++packet_feedback.sent_packet.sequence_number;
+ sent_packets.push_back(packet_feedback);
+
+ packet_feedback.sent_packet.send_time += kLargePositiveDelta;
+ packet_feedback.receive_time += kLargePositiveDelta;
+ ++packet_feedback.sent_packet.sequence_number;
+ sent_packets.push_back(packet_feedback);
+
+ packet_feedback.sent_packet.send_time += kLargeNegativeDelta;
+ packet_feedback.receive_time += kLargeNegativeDelta;
+ ++packet_feedback.sent_packet.sequence_number;
+ sent_packets.push_back(packet_feedback);
+
+ // Too large, delta - will need two feedback messages.
+ packet_feedback.sent_packet.send_time +=
+ kLargePositiveDelta + TimeDelta::Millis(1);
+ packet_feedback.receive_time += kLargePositiveDelta + TimeDelta::Millis(1);
+ ++packet_feedback.sent_packet.sequence_number;
+
+ // Packets will be added to send history.
+ for (const auto& packet : sent_packets)
+ OnSentPacket(packet);
+ OnSentPacket(packet_feedback);
+
+ // Create expected feedback and send into adapter.
+ std::unique_ptr<rtcp::TransportFeedback> feedback(
+ new rtcp::TransportFeedback());
+ feedback->SetBase(sent_packets[0].sent_packet.sequence_number,
+ sent_packets[0].receive_time);
+
+ for (const auto& packet : sent_packets) {
+ EXPECT_TRUE(feedback->AddReceivedPacket(packet.sent_packet.sequence_number,
+ packet.receive_time));
+ }
+ EXPECT_FALSE(
+ feedback->AddReceivedPacket(packet_feedback.sent_packet.sequence_number,
+ packet_feedback.receive_time));
+
+ rtc::Buffer raw_packet = feedback->Build();
+ feedback =
+ rtcp::TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
+
+ std::vector<PacketResult> received_feedback;
+
+ EXPECT_TRUE(feedback.get() != nullptr);
+ auto res =
+ adapter_->ProcessTransportFeedback(*feedback.get(), clock_.CurrentTime());
+ ComparePacketFeedbackVectors(sent_packets, res->packet_feedbacks);
+
+ // Create a new feedback message and add the trailing item.
+ feedback.reset(new rtcp::TransportFeedback());
+ feedback->SetBase(packet_feedback.sent_packet.sequence_number,
+ packet_feedback.receive_time);
+ EXPECT_TRUE(
+ feedback->AddReceivedPacket(packet_feedback.sent_packet.sequence_number,
+ packet_feedback.receive_time));
+ raw_packet = feedback->Build();
+ feedback =
+ rtcp::TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
+
+ EXPECT_TRUE(feedback.get() != nullptr);
+ {
+ auto res = adapter_->ProcessTransportFeedback(*feedback.get(),
+ clock_.CurrentTime());
+ std::vector<PacketResult> expected_packets;
+ expected_packets.push_back(packet_feedback);
+ ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
+ }
+}
+
+TEST_F(TransportFeedbackAdapterTest, IgnoreDuplicatePacketSentCalls) {
+ auto packet = CreatePacket(100, 200, 0, 1500, kPacingInfo0);
+
+ // Add a packet and then mark it as sent.
+ RtpPacketSendInfo packet_info;
+ packet_info.media_ssrc = kSsrc;
+ packet_info.transport_sequence_number = packet.sent_packet.sequence_number;
+ packet_info.length = packet.sent_packet.size.bytes();
+ packet_info.pacing_info = packet.sent_packet.pacing_info;
+ packet_info.packet_type = RtpPacketMediaType::kVideo;
+ adapter_->AddPacket(packet_info, 0u, clock_.CurrentTime());
+ absl::optional<SentPacket> sent_packet = adapter_->ProcessSentPacket(
+ rtc::SentPacket(packet.sent_packet.sequence_number,
+ packet.sent_packet.send_time.ms(), rtc::PacketInfo()));
+ EXPECT_TRUE(sent_packet.has_value());
+
+ // Call ProcessSentPacket() again with the same sequence number. This packet
+ // has already been marked as sent and the call should be ignored.
+ absl::optional<SentPacket> duplicate_packet = adapter_->ProcessSentPacket(
+ rtc::SentPacket(packet.sent_packet.sequence_number,
+ packet.sent_packet.send_time.ms(), rtc::PacketInfo()));
+ EXPECT_FALSE(duplicate_packet.has_value());
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.cc b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.cc
new file mode 100644
index 0000000000..5a6a2e1e9b
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.cc
@@ -0,0 +1,95 @@
+/*
+ * 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/congestion_controller/rtp/transport_feedback_demuxer.h"
+
+#include "absl/algorithm/container.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+
+namespace webrtc {
+namespace {
+static const size_t kMaxPacketsInHistory = 5000;
+}
+
+TransportFeedbackDemuxer::TransportFeedbackDemuxer() {
+ // In case the construction thread is different from where the registration
+ // and callbacks occur, detach from the construction thread.
+ observer_checker_.Detach();
+}
+
+void TransportFeedbackDemuxer::RegisterStreamFeedbackObserver(
+ std::vector<uint32_t> ssrcs,
+ StreamFeedbackObserver* observer) {
+ RTC_DCHECK_RUN_ON(&observer_checker_);
+ RTC_DCHECK(observer);
+ RTC_DCHECK(absl::c_find_if(observers_, [=](const auto& pair) {
+ return pair.second == observer;
+ }) == observers_.end());
+ observers_.push_back({ssrcs, observer});
+}
+
+void TransportFeedbackDemuxer::DeRegisterStreamFeedbackObserver(
+ StreamFeedbackObserver* observer) {
+ RTC_DCHECK_RUN_ON(&observer_checker_);
+ RTC_DCHECK(observer);
+ const auto it = absl::c_find_if(
+ observers_, [=](const auto& pair) { return pair.second == observer; });
+ RTC_DCHECK(it != observers_.end());
+ observers_.erase(it);
+}
+
+void TransportFeedbackDemuxer::AddPacket(const RtpPacketSendInfo& packet_info) {
+ RTC_DCHECK_RUN_ON(&observer_checker_);
+
+ StreamFeedbackObserver::StreamPacketInfo info;
+ info.ssrc = packet_info.media_ssrc;
+ info.rtp_sequence_number = packet_info.rtp_sequence_number;
+ info.received = false;
+ info.is_retransmission =
+ packet_info.packet_type == RtpPacketMediaType::kRetransmission;
+ history_.insert(
+ {seq_num_unwrapper_.Unwrap(packet_info.transport_sequence_number), info});
+
+ while (history_.size() > kMaxPacketsInHistory) {
+ history_.erase(history_.begin());
+ }
+}
+
+void TransportFeedbackDemuxer::OnTransportFeedback(
+ const rtcp::TransportFeedback& feedback) {
+ RTC_DCHECK_RUN_ON(&observer_checker_);
+
+ std::vector<StreamFeedbackObserver::StreamPacketInfo> stream_feedbacks;
+ feedback.ForAllPackets(
+ [&](uint16_t sequence_number, TimeDelta delta_since_base) {
+ RTC_DCHECK_RUN_ON(&observer_checker_);
+ auto it = history_.find(seq_num_unwrapper_.PeekUnwrap(sequence_number));
+ if (it != history_.end()) {
+ auto packet_info = it->second;
+ packet_info.received = delta_since_base.IsFinite();
+ stream_feedbacks.push_back(std::move(packet_info));
+ if (delta_since_base.IsFinite())
+ history_.erase(it);
+ }
+ });
+
+ for (auto& observer : observers_) {
+ std::vector<StreamFeedbackObserver::StreamPacketInfo> selected_feedback;
+ for (const auto& packet_info : stream_feedbacks) {
+ if (absl::c_count(observer.first, packet_info.ssrc) > 0) {
+ selected_feedback.push_back(packet_info);
+ }
+ }
+ if (!selected_feedback.empty()) {
+ observer.second->OnPacketFeedbackVector(std::move(selected_feedback));
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.h b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.h
new file mode 100644
index 0000000000..278c144b61
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+#ifndef MODULES_CONGESTION_CONTROLLER_RTP_TRANSPORT_FEEDBACK_DEMUXER_H_
+#define MODULES_CONGESTION_CONTROLLER_RTP_TRANSPORT_FEEDBACK_DEMUXER_H_
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "api/sequence_checker.h"
+#include "modules/include/module_common_types_public.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "rtc_base/numerics/sequence_number_unwrapper.h"
+#include "rtc_base/system/no_unique_address.h"
+
+namespace webrtc {
+
+// Implementation of StreamFeedbackProvider that provides a way for
+// implementations of StreamFeedbackObserver to register for feedback callbacks
+// for a given set of SSRCs.
+// Registration methods need to be called from the same execution context
+// (thread or task queue) and callbacks to
+// StreamFeedbackObserver::OnPacketFeedbackVector will be made in that same
+// context.
+// TODO(tommi): This appears to be the only implementation of this interface.
+// Do we need the interface?
+class TransportFeedbackDemuxer final : public StreamFeedbackProvider {
+ public:
+ TransportFeedbackDemuxer();
+
+ // Implements StreamFeedbackProvider interface
+ void RegisterStreamFeedbackObserver(
+ std::vector<uint32_t> ssrcs,
+ StreamFeedbackObserver* observer) override;
+ void DeRegisterStreamFeedbackObserver(
+ StreamFeedbackObserver* observer) override;
+ void AddPacket(const RtpPacketSendInfo& packet_info);
+ void OnTransportFeedback(const rtcp::TransportFeedback& feedback);
+
+ private:
+ RTC_NO_UNIQUE_ADDRESS SequenceChecker observer_checker_;
+ RtpSequenceNumberUnwrapper seq_num_unwrapper_
+ RTC_GUARDED_BY(&observer_checker_);
+ std::map<int64_t, StreamFeedbackObserver::StreamPacketInfo> history_
+ RTC_GUARDED_BY(&observer_checker_);
+
+ // Maps a set of ssrcs to corresponding observer. Vectors are used rather than
+ // set/map to ensure that the processing order is consistent independently of
+ // the randomized ssrcs.
+ std::vector<std::pair<std::vector<uint32_t>, StreamFeedbackObserver*>>
+ observers_ RTC_GUARDED_BY(&observer_checker_);
+};
+} // namespace webrtc
+
+#endif // MODULES_CONGESTION_CONTROLLER_RTP_TRANSPORT_FEEDBACK_DEMUXER_H_
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer_unittest.cc b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer_unittest.cc
new file mode 100644
index 0000000000..52d8018bff
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer_unittest.cc
@@ -0,0 +1,99 @@
+/*
+ * 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/congestion_controller/rtp/transport_feedback_demuxer.h"
+
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using PacketInfo = StreamFeedbackObserver::StreamPacketInfo;
+
+static constexpr uint32_t kSsrc = 8492;
+
+class MockStreamFeedbackObserver : public webrtc::StreamFeedbackObserver {
+ public:
+ MOCK_METHOD(void,
+ OnPacketFeedbackVector,
+ (std::vector<StreamPacketInfo> packet_feedback_vector),
+ (override));
+};
+
+RtpPacketSendInfo CreatePacket(uint32_t ssrc,
+ uint16_t rtp_sequence_number,
+ int64_t transport_sequence_number,
+ bool is_retransmission) {
+ RtpPacketSendInfo res;
+ res.media_ssrc = ssrc;
+ res.transport_sequence_number = transport_sequence_number;
+ res.rtp_sequence_number = rtp_sequence_number;
+ res.packet_type = is_retransmission ? RtpPacketMediaType::kRetransmission
+ : RtpPacketMediaType::kVideo;
+ return res;
+}
+} // namespace
+
+TEST(TransportFeedbackDemuxerTest, ObserverSanity) {
+ TransportFeedbackDemuxer demuxer;
+ MockStreamFeedbackObserver mock;
+ demuxer.RegisterStreamFeedbackObserver({kSsrc}, &mock);
+
+ const uint16_t kRtpStartSeq = 55;
+ const int64_t kTransportStartSeq = 1;
+ demuxer.AddPacket(CreatePacket(kSsrc, kRtpStartSeq, kTransportStartSeq,
+ /*is_retransmit=*/false));
+ demuxer.AddPacket(CreatePacket(kSsrc, kRtpStartSeq + 1,
+ kTransportStartSeq + 1,
+ /*is_retransmit=*/false));
+ demuxer.AddPacket(CreatePacket(
+ kSsrc, kRtpStartSeq + 2, kTransportStartSeq + 2, /*is_retransmit=*/true));
+
+ rtcp::TransportFeedback feedback;
+ feedback.SetBase(kTransportStartSeq, Timestamp::Millis(1));
+ ASSERT_TRUE(
+ feedback.AddReceivedPacket(kTransportStartSeq, Timestamp::Millis(1)));
+ // Drop middle packet.
+ ASSERT_TRUE(
+ feedback.AddReceivedPacket(kTransportStartSeq + 2, Timestamp::Millis(3)));
+
+ EXPECT_CALL(
+ mock, OnPacketFeedbackVector(ElementsAre(
+ AllOf(Field(&PacketInfo::received, true),
+ Field(&PacketInfo::ssrc, kSsrc),
+ Field(&PacketInfo::rtp_sequence_number, kRtpStartSeq),
+ Field(&PacketInfo::is_retransmission, false)),
+ AllOf(Field(&PacketInfo::received, false),
+ Field(&PacketInfo::ssrc, kSsrc),
+ Field(&PacketInfo::rtp_sequence_number, kRtpStartSeq + 1),
+ Field(&PacketInfo::is_retransmission, false)),
+ AllOf(Field(&PacketInfo::received, true),
+ Field(&PacketInfo::ssrc, kSsrc),
+ Field(&PacketInfo::rtp_sequence_number, kRtpStartSeq + 2),
+ Field(&PacketInfo::is_retransmission, true)))));
+ demuxer.OnTransportFeedback(feedback);
+
+ demuxer.DeRegisterStreamFeedbackObserver(&mock);
+
+ demuxer.AddPacket(
+ CreatePacket(kSsrc, kRtpStartSeq + 3, kTransportStartSeq + 3, false));
+ rtcp::TransportFeedback second_feedback;
+ second_feedback.SetBase(kTransportStartSeq + 3, Timestamp::Millis(4));
+ ASSERT_TRUE(second_feedback.AddReceivedPacket(kTransportStartSeq + 3,
+ Timestamp::Millis(4)));
+
+ EXPECT_CALL(mock, OnPacketFeedbackVector).Times(0);
+ demuxer.OnTransportFeedback(second_feedback);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_gn/moz.build b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_gn/moz.build
new file mode 100644
index 0000000000..40ead5619c
--- /dev/null
+++ b/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_gn/moz.build
@@ -0,0 +1,237 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+ ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ###
+ ### DO NOT edit it by hand. ###
+
+COMPILE_FLAGS["OS_INCLUDES"] = []
+AllowCompilerWarnings()
+
+DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1"
+DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True
+DEFINES["RTC_ENABLE_VP9"] = True
+DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0"
+DEFINES["WEBRTC_LIBRARY_IMPL"] = True
+DEFINES["WEBRTC_MOZILLA_BUILD"] = True
+DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0"
+DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0"
+
+FINAL_LIBRARY = "webrtc"
+
+
+LOCAL_INCLUDES += [
+ "!/ipc/ipdl/_ipdlheaders",
+ "!/third_party/libwebrtc/gen",
+ "/ipc/chromium/src",
+ "/third_party/libwebrtc/",
+ "/third_party/libwebrtc/third_party/abseil-cpp/",
+ "/tools/profiler/public"
+]
+
+UNIFIED_SOURCES += [
+ "/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.cc",
+ "/third_party/libwebrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.cc"
+]
+
+if not CONFIG["MOZ_DEBUG"]:
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0"
+ DEFINES["NDEBUG"] = True
+ DEFINES["NVALGRIND"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1":
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["ANDROID"] = True
+ DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1"
+ DEFINES["HAVE_SYS_UIO_H"] = True
+ DEFINES["WEBRTC_ANDROID"] = True
+ DEFINES["WEBRTC_ANDROID_OPENSLES"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_GNU_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+ OS_LIBS += [
+ "log"
+ ]
+
+if CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["WEBRTC_MAC"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True
+ DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0"
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_NSS_CERTS"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_UDEV"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+ OS_LIBS += [
+ "rt"
+ ]
+
+if CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_X11"] = "1"
+ DEFINES["WEBRTC_BSD"] = True
+ DEFINES["WEBRTC_ENABLE_LIBEVENT"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True
+ DEFINES["NOMINMAX"] = True
+ DEFINES["NTDDI_VERSION"] = "0x0A000000"
+ DEFINES["PSAPI_VERSION"] = "2"
+ DEFINES["RTC_ENABLE_WIN_WGC"] = True
+ DEFINES["UNICODE"] = True
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["WEBRTC_WIN"] = True
+ DEFINES["WIN32"] = True
+ DEFINES["WIN32_LEAN_AND_MEAN"] = True
+ DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP"
+ DEFINES["WINVER"] = "0x0A00"
+ DEFINES["_ATL_NO_OPENGL"] = True
+ DEFINES["_CRT_RAND_S"] = True
+ DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True
+ DEFINES["_HAS_EXCEPTIONS"] = "0"
+ DEFINES["_HAS_NODISCARD"] = True
+ DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_SECURE_ATL"] = True
+ DEFINES["_UNICODE"] = True
+ DEFINES["_WIN32_WINNT"] = "0x0A00"
+ DEFINES["_WINDOWS"] = True
+ DEFINES["__STD_C"] = True
+
+ OS_LIBS += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "x86_64":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0"
+
+if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_X11"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+Library("transport_feedback_gn")