blob: 490fc46d7c55a28469a25cc95108f02b15621123 [file] [log] [blame]
Niels Möllere0446cb2018-11-30 09:35:52 +01001/*
2 * Copyright 2018 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
11#include "api/test/loopback_media_transport.h"
12
13#include "absl/memory/memory.h"
Steve Anton10542f22019-01-11 09:11:00 -080014#include "rtc_base/time_utils.h"
Niels Möllere0446cb2018-11-30 09:35:52 +010015
16namespace webrtc {
17
18namespace {
19
20// Wrapper used to hand out unique_ptrs to loopback media transports without
21// ownership changes.
22class WrapperMediaTransport : public MediaTransportInterface {
23 public:
24 explicit WrapperMediaTransport(MediaTransportInterface* wrapped)
25 : wrapped_(wrapped) {}
26
27 RTCError SendAudioFrame(uint64_t channel_id,
28 MediaTransportEncodedAudioFrame frame) override {
29 return wrapped_->SendAudioFrame(channel_id, std::move(frame));
30 }
31
32 RTCError SendVideoFrame(
33 uint64_t channel_id,
34 const MediaTransportEncodedVideoFrame& frame) override {
35 return wrapped_->SendVideoFrame(channel_id, frame);
36 }
37
Niels Möller1c7f5f62018-12-10 11:06:02 +010038 void SetKeyFrameRequestCallback(
39 MediaTransportKeyFrameRequestCallback* callback) override {
40 wrapped_->SetKeyFrameRequestCallback(callback);
41 }
42
Niels Möllere0446cb2018-11-30 09:35:52 +010043 RTCError RequestKeyFrame(uint64_t channel_id) override {
44 return wrapped_->RequestKeyFrame(channel_id);
45 }
46
47 void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {
48 wrapped_->SetReceiveAudioSink(sink);
49 }
50
51 void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {
52 wrapped_->SetReceiveVideoSink(sink);
53 }
54
Niels Möller46879152019-01-07 15:54:47 +010055 void AddTargetTransferRateObserver(
56 TargetTransferRateObserver* observer) override {
57 wrapped_->AddTargetTransferRateObserver(observer);
58 }
59
60 void RemoveTargetTransferRateObserver(
61 TargetTransferRateObserver* observer) override {
62 wrapped_->RemoveTargetTransferRateObserver(observer);
63 }
64
Niels Möllere0446cb2018-11-30 09:35:52 +010065 void SetMediaTransportStateCallback(
66 MediaTransportStateCallback* callback) override {
67 wrapped_->SetMediaTransportStateCallback(callback);
68 }
69
Bjorn Mellem9ded4852019-02-28 12:27:11 -080070 RTCError OpenChannel(int channel_id) override {
71 return wrapped_->OpenChannel(channel_id);
72 }
73
Niels Möllere0446cb2018-11-30 09:35:52 +010074 RTCError SendData(int channel_id,
75 const SendDataParams& params,
76 const rtc::CopyOnWriteBuffer& buffer) override {
77 return wrapped_->SendData(channel_id, params, buffer);
78 }
79
80 RTCError CloseChannel(int channel_id) override {
81 return wrapped_->CloseChannel(channel_id);
82 }
83
84 void SetDataSink(DataChannelSink* sink) override {
85 wrapped_->SetDataSink(sink);
86 }
87
Piotr (Peter) Slatala48c54932019-01-28 06:50:38 -080088 void SetAllocatedBitrateLimits(
89 const MediaTransportAllocatedBitrateLimits& limits) override {}
90
Niels Möllere0446cb2018-11-30 09:35:52 +010091 private:
92 MediaTransportInterface* wrapped_;
93};
94
95} // namespace
96
97WrapperMediaTransportFactory::WrapperMediaTransportFactory(
98 MediaTransportInterface* wrapped)
99 : wrapped_(wrapped) {}
100
101RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
102WrapperMediaTransportFactory::CreateMediaTransport(
103 rtc::PacketTransportInternal* packet_transport,
104 rtc::Thread* network_thread,
105 const MediaTransportSettings& settings) {
106 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
107}
108
109MediaTransportPair::LoopbackMediaTransport::LoopbackMediaTransport(
110 rtc::Thread* thread,
111 LoopbackMediaTransport* other)
112 : thread_(thread), other_(other) {}
113
114MediaTransportPair::LoopbackMediaTransport::~LoopbackMediaTransport() {
115 rtc::CritScope lock(&sink_lock_);
116 RTC_CHECK(audio_sink_ == nullptr);
117 RTC_CHECK(video_sink_ == nullptr);
118 RTC_CHECK(data_sink_ == nullptr);
Niels Möller46879152019-01-07 15:54:47 +0100119 RTC_CHECK(target_transfer_rate_observers_.empty());
120 RTC_CHECK(rtt_observers_.empty());
Niels Möllere0446cb2018-11-30 09:35:52 +0100121}
122
123RTCError MediaTransportPair::LoopbackMediaTransport::SendAudioFrame(
124 uint64_t channel_id,
125 MediaTransportEncodedAudioFrame frame) {
126 {
127 rtc::CritScope lock(&stats_lock_);
128 ++stats_.sent_audio_frames;
129 }
130 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id, frame] {
Mirko Bonadei05cf6be2019-01-31 21:38:12 +0100131 other_->OnData(channel_id, frame);
Niels Möllere0446cb2018-11-30 09:35:52 +0100132 });
133 return RTCError::OK();
134}
135
136RTCError MediaTransportPair::LoopbackMediaTransport::SendVideoFrame(
137 uint64_t channel_id,
138 const MediaTransportEncodedVideoFrame& frame) {
139 {
140 rtc::CritScope lock(&stats_lock_);
141 ++stats_.sent_video_frames;
142 }
143 // Ensure that we own the referenced data.
144 MediaTransportEncodedVideoFrame frame_copy = frame;
145 frame_copy.Retain();
146 invoker_.AsyncInvoke<void>(
Mirko Bonadei80a86872019-02-04 15:01:43 +0100147 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy]() mutable {
Niels Möllere0446cb2018-11-30 09:35:52 +0100148 other_->OnData(channel_id, std::move(frame_copy));
149 });
150 return RTCError::OK();
151}
152
Niels Möller1c7f5f62018-12-10 11:06:02 +0100153void MediaTransportPair::LoopbackMediaTransport::SetKeyFrameRequestCallback(
154 MediaTransportKeyFrameRequestCallback* callback) {
155 rtc::CritScope lock(&sink_lock_);
156 if (callback) {
157 RTC_CHECK(key_frame_callback_ == nullptr);
158 }
159 key_frame_callback_ = callback;
160}
161
Niels Möllere0446cb2018-11-30 09:35:52 +0100162RTCError MediaTransportPair::LoopbackMediaTransport::RequestKeyFrame(
163 uint64_t channel_id) {
Niels Möller1c7f5f62018-12-10 11:06:02 +0100164 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
165 other_->OnKeyFrameRequested(channel_id);
166 });
Niels Möllere0446cb2018-11-30 09:35:52 +0100167 return RTCError::OK();
168}
169
170void MediaTransportPair::LoopbackMediaTransport::SetReceiveAudioSink(
171 MediaTransportAudioSinkInterface* sink) {
172 rtc::CritScope lock(&sink_lock_);
173 if (sink) {
174 RTC_CHECK(audio_sink_ == nullptr);
175 }
176 audio_sink_ = sink;
177}
178
179void MediaTransportPair::LoopbackMediaTransport::SetReceiveVideoSink(
180 MediaTransportVideoSinkInterface* sink) {
181 rtc::CritScope lock(&sink_lock_);
182 if (sink) {
183 RTC_CHECK(video_sink_ == nullptr);
184 }
185 video_sink_ = sink;
186}
187
Niels Möller46879152019-01-07 15:54:47 +0100188void MediaTransportPair::LoopbackMediaTransport::AddTargetTransferRateObserver(
189 TargetTransferRateObserver* observer) {
190 RTC_CHECK(observer);
191 {
192 rtc::CritScope cs(&sink_lock_);
193 RTC_CHECK(std::find(target_transfer_rate_observers_.begin(),
194 target_transfer_rate_observers_.end(),
195 observer) == target_transfer_rate_observers_.end());
196 target_transfer_rate_observers_.push_back(observer);
197 }
198 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
199 RTC_DCHECK_RUN_ON(thread_);
200 const DataRate kBitrate = DataRate::kbps(300);
201 const Timestamp now = Timestamp::us(rtc::TimeMicros());
202
203 TargetTransferRate transfer_rate;
204 transfer_rate.at_time = now;
205 transfer_rate.target_rate = kBitrate;
206 transfer_rate.network_estimate.at_time = now;
207 transfer_rate.network_estimate.round_trip_time = TimeDelta::ms(20);
208 transfer_rate.network_estimate.bwe_period = TimeDelta::seconds(3);
209 transfer_rate.network_estimate.bandwidth = kBitrate;
210
211 rtc::CritScope cs(&sink_lock_);
212
213 for (auto* o : target_transfer_rate_observers_) {
214 o->OnTargetTransferRate(transfer_rate);
215 }
216 });
217}
218
219void MediaTransportPair::LoopbackMediaTransport::
220 RemoveTargetTransferRateObserver(TargetTransferRateObserver* observer) {
221 rtc::CritScope cs(&sink_lock_);
222 auto it = std::find(target_transfer_rate_observers_.begin(),
223 target_transfer_rate_observers_.end(), observer);
224 if (it == target_transfer_rate_observers_.end()) {
225 RTC_LOG(LS_WARNING)
226 << "Attempt to remove an unknown TargetTransferRate observer";
227 return;
228 }
229 target_transfer_rate_observers_.erase(it);
230}
231
232void MediaTransportPair::LoopbackMediaTransport::AddRttObserver(
233 MediaTransportRttObserver* observer) {
234 RTC_CHECK(observer);
235 {
236 rtc::CritScope cs(&sink_lock_);
237 RTC_CHECK(std::find(rtt_observers_.begin(), rtt_observers_.end(),
238 observer) == rtt_observers_.end());
239 rtt_observers_.push_back(observer);
240 }
241 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
242 RTC_DCHECK_RUN_ON(thread_);
243
244 rtc::CritScope cs(&sink_lock_);
245 for (auto* o : rtt_observers_) {
246 o->OnRttUpdated(20);
247 }
248 });
249}
250
251void MediaTransportPair::LoopbackMediaTransport::RemoveRttObserver(
252 MediaTransportRttObserver* observer) {
253 rtc::CritScope cs(&sink_lock_);
254 auto it = std::find(rtt_observers_.begin(), rtt_observers_.end(), observer);
255 if (it == rtt_observers_.end()) {
256 RTC_LOG(LS_WARNING) << "Attempt to remove an unknown RTT observer";
257 return;
258 }
259 rtt_observers_.erase(it);
260}
261
Niels Möllere0446cb2018-11-30 09:35:52 +0100262void MediaTransportPair::LoopbackMediaTransport::SetMediaTransportStateCallback(
263 MediaTransportStateCallback* callback) {
264 rtc::CritScope lock(&sink_lock_);
265 state_callback_ = callback;
266 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
267 RTC_DCHECK_RUN_ON(thread_);
268 OnStateChanged();
269 });
270}
271
Bjorn Mellem9ded4852019-02-28 12:27:11 -0800272RTCError MediaTransportPair::LoopbackMediaTransport::OpenChannel(
273 int channel_id) {
274 // No-op. No need to open channels for the loopback.
275 return RTCError::OK();
276}
277
Niels Möllere0446cb2018-11-30 09:35:52 +0100278RTCError MediaTransportPair::LoopbackMediaTransport::SendData(
279 int channel_id,
280 const SendDataParams& params,
281 const rtc::CopyOnWriteBuffer& buffer) {
282 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
283 [this, channel_id, params, buffer] {
284 other_->OnData(channel_id, params.type, buffer);
285 });
286 return RTCError::OK();
287}
288
289RTCError MediaTransportPair::LoopbackMediaTransport::CloseChannel(
290 int channel_id) {
291 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
292 other_->OnRemoteCloseChannel(channel_id);
293 rtc::CritScope lock(&sink_lock_);
294 if (data_sink_) {
295 data_sink_->OnChannelClosed(channel_id);
296 }
297 });
298 return RTCError::OK();
299}
300
301void MediaTransportPair::LoopbackMediaTransport::SetDataSink(
302 DataChannelSink* sink) {
303 rtc::CritScope lock(&sink_lock_);
304 data_sink_ = sink;
305}
306void MediaTransportPair::LoopbackMediaTransport::SetState(
307 MediaTransportState state) {
308 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
309 RTC_DCHECK_RUN_ON(thread_);
310 state_ = state;
311 OnStateChanged();
312 });
313}
314
315void MediaTransportPair::LoopbackMediaTransport::FlushAsyncInvokes() {
316 invoker_.Flush(thread_);
317}
318
319MediaTransportPair::Stats
320MediaTransportPair::LoopbackMediaTransport::GetStats() {
321 rtc::CritScope lock(&stats_lock_);
322 return stats_;
323}
324
325void MediaTransportPair::LoopbackMediaTransport::OnData(
326 uint64_t channel_id,
327 MediaTransportEncodedAudioFrame frame) {
328 {
329 rtc::CritScope lock(&sink_lock_);
Sergey Silkine049eba2019-02-18 09:52:26 +0000330 if (audio_sink_) {
Niels Möllere0446cb2018-11-30 09:35:52 +0100331 audio_sink_->OnData(channel_id, frame);
332 }
333 }
334 {
335 rtc::CritScope lock(&stats_lock_);
336 ++stats_.received_audio_frames;
337 }
338}
339
340void MediaTransportPair::LoopbackMediaTransport::OnData(
341 uint64_t channel_id,
342 MediaTransportEncodedVideoFrame frame) {
343 {
344 rtc::CritScope lock(&sink_lock_);
345 if (video_sink_) {
346 video_sink_->OnData(channel_id, frame);
347 }
348 }
349 {
350 rtc::CritScope lock(&stats_lock_);
351 ++stats_.received_video_frames;
352 }
353}
354
355void MediaTransportPair::LoopbackMediaTransport::OnData(
356 int channel_id,
357 DataMessageType type,
358 const rtc::CopyOnWriteBuffer& buffer) {
359 rtc::CritScope lock(&sink_lock_);
360 if (data_sink_) {
361 data_sink_->OnDataReceived(channel_id, type, buffer);
362 }
363}
364
Niels Möller1c7f5f62018-12-10 11:06:02 +0100365void MediaTransportPair::LoopbackMediaTransport::OnKeyFrameRequested(
366 int channel_id) {
367 rtc::CritScope lock(&sink_lock_);
368 if (key_frame_callback_) {
369 key_frame_callback_->OnKeyFrameRequested(channel_id);
370 }
371}
372
Niels Möllere0446cb2018-11-30 09:35:52 +0100373void MediaTransportPair::LoopbackMediaTransport::OnRemoteCloseChannel(
374 int channel_id) {
375 rtc::CritScope lock(&sink_lock_);
376 if (data_sink_) {
377 data_sink_->OnChannelClosing(channel_id);
378 data_sink_->OnChannelClosed(channel_id);
379 }
380}
381
382void MediaTransportPair::LoopbackMediaTransport::OnStateChanged() {
383 rtc::CritScope lock(&sink_lock_);
384 if (state_callback_) {
385 state_callback_->OnStateChanged(state_);
386 }
387}
Piotr (Peter) Slatala48c54932019-01-28 06:50:38 -0800388
389void MediaTransportPair::LoopbackMediaTransport::SetAllocatedBitrateLimits(
390 const MediaTransportAllocatedBitrateLimits& limits) {}
391
Niels Möllere0446cb2018-11-30 09:35:52 +0100392} // namespace webrtc