File: intercepting_network_controller.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (234 lines) | stat: -rw-r--r-- 9,326 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/peerconnection/intercepting_network_controller.h"

#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"

namespace blink {

namespace {

webrtc::TargetTransferRate CreateTargetTransferRate(
    webrtc::Timestamp at_time,
    uint64_t custom_max_bitrate_bps) {
  webrtc::DataRate data_rate =
      webrtc::DataRate::BitsPerSec(custom_max_bitrate_bps);

  webrtc::NetworkEstimate network_estimate;
  network_estimate.at_time = at_time;
  network_estimate.bandwidth = data_rate;

  // This RTT is used within libwebrtc to configure FEC.
  // TODO(crbug.com/345101934): Supply it from a different RTT estimator, or add
  // it to the JS interface.
  network_estimate.round_trip_time = webrtc::TimeDelta::Millis(0);
  // The bwe_period field is deprecated in webrtc, having been replaced by
  // stable_target_rate, but must still be set.
  network_estimate.bwe_period = webrtc::TimeDelta::Millis(0);
  return {
      .at_time = at_time,
      .network_estimate = network_estimate,
      .target_rate = data_rate,
      .stable_target_rate = data_rate,
  };
}

webrtc::NetworkControlUpdate OverwriteTargetRate(
    webrtc::NetworkControlUpdate fallback_update,
    std::optional<uint64_t> custom_max_bitrate_bps) {
  if (!fallback_update.target_rate || !custom_max_bitrate_bps) {
    return fallback_update;
  }
  webrtc::TargetTransferRate target_transfer_rate = CreateTargetTransferRate(
      fallback_update.target_rate->at_time, *custom_max_bitrate_bps);

  fallback_update.target_rate = target_transfer_rate;
  return fallback_update;
}

}  // namespace

InterceptingNetworkController::InterceptingNetworkController(
    std::unique_ptr<webrtc::NetworkControllerInterface> fallback_controller,
    CrossThreadWeakHandle<RTCRtpTransport> rtp_transport_handle,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : fallback_controller_(std::move(fallback_controller)),
      feedback_provider_(base::MakeRefCounted<FeedbackProviderImpl>()) {
  PostCrossThreadTask(
      *task_runner, FROM_HERE,
      CrossThreadBindOnce(
          &RTCRtpTransport::RegisterFeedbackProvider,
          MakeUnwrappingCrossThreadWeakHandle(rtp_transport_handle),
          feedback_provider_));
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnNetworkAvailability(
    webrtc::NetworkAvailability na) {
  return OverwriteTargetRate(fallback_controller_->OnNetworkAvailability(na),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnNetworkRouteChange(
    webrtc::NetworkRouteChange nrc) {
  return OverwriteTargetRate(fallback_controller_->OnNetworkRouteChange(nrc),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate InterceptingNetworkController::OnProcessInterval(
    webrtc::ProcessInterval pi) {
  webrtc::NetworkControlUpdate fallback_update =
      fallback_controller_->OnProcessInterval(pi);

  if (!feedback_provider_->CustomMaxBitrateBps()) {
    return fallback_update;
  }
  webrtc::TargetTransferRate target_rate = CreateTargetTransferRate(
      pi.at_time, *feedback_provider_->CustomMaxBitrateBps());
  webrtc::NetworkControlUpdate update;
  update.target_rate = target_rate;
  return update;
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnRemoteBitrateReport(
    webrtc::RemoteBitrateReport rbr) {
  return OverwriteTargetRate(fallback_controller_->OnRemoteBitrateReport(rbr),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnRoundTripTimeUpdate(
    webrtc::RoundTripTimeUpdate rttu) {
  return OverwriteTargetRate(fallback_controller_->OnRoundTripTimeUpdate(rttu),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate InterceptingNetworkController::OnSentPacket(
    webrtc::SentPacket sp) {
  feedback_provider_->OnSentPacket(sp);
  return OverwriteTargetRate(fallback_controller_->OnSentPacket(sp),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate InterceptingNetworkController::OnReceivedPacket(
    webrtc::ReceivedPacket rp) {
  return OverwriteTargetRate(fallback_controller_->OnReceivedPacket(rp),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate InterceptingNetworkController::OnStreamsConfig(
    webrtc::StreamsConfig sc) {
  return OverwriteTargetRate(fallback_controller_->OnStreamsConfig(sc),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnTargetRateConstraints(
    webrtc::TargetRateConstraints trc) {
  return OverwriteTargetRate(fallback_controller_->OnTargetRateConstraints(trc),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnTransportLossReport(
    webrtc::TransportLossReport tlr) {
  return OverwriteTargetRate(fallback_controller_->OnTransportLossReport(tlr),
                             feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnTransportPacketsFeedback(
    webrtc::TransportPacketsFeedback tpf) {
  feedback_provider_->OnFeedback(tpf);
  return OverwriteTargetRate(
      fallback_controller_->OnTransportPacketsFeedback(tpf),
      feedback_provider_->CustomMaxBitrateBps());
}

webrtc::NetworkControlUpdate
InterceptingNetworkController::OnNetworkStateEstimate(
    webrtc::NetworkStateEstimate nse) {
  return OverwriteTargetRate(fallback_controller_->OnNetworkStateEstimate(nse),
                             feedback_provider_->CustomMaxBitrateBps());
}

void InterceptingNetworkController::FeedbackProviderImpl::OnFeedback(
    webrtc::TransportPacketsFeedback feedback) {
  // Called on a WebRTC thread.
  base::AutoLock mutex(processor_lock_);
  // TODO(crbug.com/345101934): Consider buffering these until the
  // processor_handle has been created and then replaying them.
  if (!rtp_transport_processor_handle_) {
    return;
  }
  CHECK(!rtp_transport_processor_task_runner_->RunsTasksInCurrentSequence());
  PostCrossThreadTask(
      *rtp_transport_processor_task_runner_, FROM_HERE,
      CrossThreadBindOnce(&InterceptingNetworkController::FeedbackProviderImpl::
                              OnFeedbackOnDestinationTaskRunner,
                          WrapRefCounted(this), feedback,
                          MakeUnwrappingCrossThreadWeakHandle(
                              *rtp_transport_processor_handle_)));
}

void InterceptingNetworkController::FeedbackProviderImpl::
    OnFeedbackOnDestinationTaskRunner(
        webrtc::TransportPacketsFeedback feedback,
        RTCRtpTransportProcessor* rtp_transport_processor) {
  // Runs on the task runner  matching the JS thread of rtp_transport_processor.
  if (rtp_transport_processor) {
    rtp_transport_processor->OnFeedback(feedback);
  }
}

void InterceptingNetworkController::FeedbackProviderImpl::OnSentPacket(
    webrtc::SentPacket sp) {
  // Called on a WebRTC thread.
  base::AutoLock mutex(processor_lock_);
  // TODO(crbug.com/345101934): Consider buffering these until the
  // processor_handle has been created and then replaying them
  if (!rtp_transport_processor_handle_) {
    return;
  }
  CHECK(!rtp_transport_processor_task_runner_->RunsTasksInCurrentSequence());
  PostCrossThreadTask(
      *rtp_transport_processor_task_runner_, FROM_HERE,
      CrossThreadBindOnce(&InterceptingNetworkController::FeedbackProviderImpl::
                              OnSentPacketOnDestinationTaskRunner,
                          WrapRefCounted(this), sp,
                          MakeUnwrappingCrossThreadWeakHandle(
                              *rtp_transport_processor_handle_)));
}

void InterceptingNetworkController::FeedbackProviderImpl::
    OnSentPacketOnDestinationTaskRunner(
        webrtc::SentPacket sp,
        RTCRtpTransportProcessor* rtp_transport_processor) {
  // Runs on the task runner matching the JS thread of rtp_transport_processor
  // ie a worker.
  if (rtp_transport_processor) {
    rtp_transport_processor->OnSentPacket(sp);
  }
}

void InterceptingNetworkController::FeedbackProviderImpl::SetProcessor(
    CrossThreadWeakHandle<RTCRtpTransportProcessor>
        rtp_transport_processor_handle,
    scoped_refptr<base::SequencedTaskRunner>
        rtp_transport_processor_task_runner) {
  // Called on the main JS thread owning the RTCRtpTransport instance.
  base::AutoLock mutex(processor_lock_);
  rtp_transport_processor_handle_.emplace(
      std::move(rtp_transport_processor_handle));
  rtp_transport_processor_task_runner_ =
      std::move(rtp_transport_processor_task_runner);
}

}  // namespace blink