blob: fde732e49b99518838eb480d41307dc4cc8454a2 [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
70 RTCError SendData(int channel_id,
71 const SendDataParams& params,
72 const rtc::CopyOnWriteBuffer& buffer) override {
73 return wrapped_->SendData(channel_id, params, buffer);
74 }
75
76 RTCError CloseChannel(int channel_id) override {
77 return wrapped_->CloseChannel(channel_id);
78 }
79
80 void SetDataSink(DataChannelSink* sink) override {
81 wrapped_->SetDataSink(sink);
82 }
83
Piotr (Peter) Slatala48c54932019-01-28 06:50:38 -080084 void SetAllocatedBitrateLimits(
85 const MediaTransportAllocatedBitrateLimits& limits) override {}
86
Niels Möllere0446cb2018-11-30 09:35:52 +010087 private:
88 MediaTransportInterface* wrapped_;
89};
90
91} // namespace
92
93WrapperMediaTransportFactory::WrapperMediaTransportFactory(
94 MediaTransportInterface* wrapped)
95 : wrapped_(wrapped) {}
96
97RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
98WrapperMediaTransportFactory::CreateMediaTransport(
99 rtc::PacketTransportInternal* packet_transport,
100 rtc::Thread* network_thread,
101 const MediaTransportSettings& settings) {
102 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
103}
104
105MediaTransportPair::LoopbackMediaTransport::LoopbackMediaTransport(
106 rtc::Thread* thread,
107 LoopbackMediaTransport* other)
108 : thread_(thread), other_(other) {}
109
110MediaTransportPair::LoopbackMediaTransport::~LoopbackMediaTransport() {
111 rtc::CritScope lock(&sink_lock_);
Niels Möller0d8eed62019-02-18 09:10:30 +0100112 RTC_CHECK(audio_sinks_.empty());
Niels Möllere0446cb2018-11-30 09:35:52 +0100113 RTC_CHECK(audio_sink_ == nullptr);
114 RTC_CHECK(video_sink_ == nullptr);
115 RTC_CHECK(data_sink_ == nullptr);
Niels Möller46879152019-01-07 15:54:47 +0100116 RTC_CHECK(target_transfer_rate_observers_.empty());
117 RTC_CHECK(rtt_observers_.empty());
Niels Möllere0446cb2018-11-30 09:35:52 +0100118}
119
Niels Möller0d8eed62019-02-18 09:10:30 +0100120class MediaTransportPair::LoopbackMediaTransport::AudioSender
121 : public MediaTransportAudioSender {
122 public:
123 AudioSender(LoopbackMediaTransport* transport, uint64_t channel_id)
124 : transport_(transport), channel_id_(channel_id) {}
125 void SendAudioFrame(MediaTransportEncodedAudioFrame frame) override {
126 transport_->SendAudioFrame(channel_id_, std::move(frame));
127 }
128
129 private:
130 LoopbackMediaTransport* transport_;
131 uint64_t channel_id_;
132};
133
134class MediaTransportPair::LoopbackMediaTransport::AudioReceiver
135 : public MediaTransportAudioReceiver {
136 public:
137 AudioReceiver(LoopbackMediaTransport* transport, uint64_t channel_id)
138 : transport_(transport), channel_id_(channel_id) {}
139 ~AudioReceiver() override {
140 transport_->UnregisterAudioReceiver(channel_id_);
141 }
142
143 private:
144 LoopbackMediaTransport* transport_;
145 uint64_t channel_id_;
146};
147
148std::unique_ptr<MediaTransportAudioSender>
149MediaTransportPair::LoopbackMediaTransport::CreateAudioSender(
150 uint64_t channel_id) {
151 return absl::make_unique<AudioSender>(this, channel_id);
152}
153
154std::unique_ptr<MediaTransportAudioReceiver>
155MediaTransportPair::LoopbackMediaTransport::CreateAudioReceiver(
156 uint64_t channel_id,
157 MediaTransportAudioSinkInterface* sink) {
158 rtc::CritScope cs(&sink_lock_);
159 auto res = audio_sinks_.emplace(channel_id, sink);
160 RTC_DCHECK(res.second);
161 return absl::make_unique<AudioReceiver>(this, channel_id);
162}
163
164void MediaTransportPair::LoopbackMediaTransport::UnregisterAudioReceiver(
165 uint64_t channel_id) {
166 rtc::CritScope cs(&sink_lock_);
167 auto it = audio_sinks_.find(channel_id);
168 RTC_DCHECK(it != audio_sinks_.end());
169 audio_sinks_.erase(it);
170}
171
Niels Möllere0446cb2018-11-30 09:35:52 +0100172RTCError MediaTransportPair::LoopbackMediaTransport::SendAudioFrame(
173 uint64_t channel_id,
174 MediaTransportEncodedAudioFrame frame) {
175 {
176 rtc::CritScope lock(&stats_lock_);
177 ++stats_.sent_audio_frames;
178 }
179 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id, frame] {
Mirko Bonadei05cf6be2019-01-31 21:38:12 +0100180 other_->OnData(channel_id, frame);
Niels Möllere0446cb2018-11-30 09:35:52 +0100181 });
182 return RTCError::OK();
183}
184
185RTCError MediaTransportPair::LoopbackMediaTransport::SendVideoFrame(
186 uint64_t channel_id,
187 const MediaTransportEncodedVideoFrame& frame) {
188 {
189 rtc::CritScope lock(&stats_lock_);
190 ++stats_.sent_video_frames;
191 }
192 // Ensure that we own the referenced data.
193 MediaTransportEncodedVideoFrame frame_copy = frame;
194 frame_copy.Retain();
195 invoker_.AsyncInvoke<void>(
Mirko Bonadei80a86872019-02-04 15:01:43 +0100196 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy]() mutable {
Niels Möllere0446cb2018-11-30 09:35:52 +0100197 other_->OnData(channel_id, std::move(frame_copy));
198 });
199 return RTCError::OK();
200}
201
Niels Möller1c7f5f62018-12-10 11:06:02 +0100202void MediaTransportPair::LoopbackMediaTransport::SetKeyFrameRequestCallback(
203 MediaTransportKeyFrameRequestCallback* callback) {
204 rtc::CritScope lock(&sink_lock_);
205 if (callback) {
206 RTC_CHECK(key_frame_callback_ == nullptr);
207 }
208 key_frame_callback_ = callback;
209}
210
Niels Möllere0446cb2018-11-30 09:35:52 +0100211RTCError MediaTransportPair::LoopbackMediaTransport::RequestKeyFrame(
212 uint64_t channel_id) {
Niels Möller1c7f5f62018-12-10 11:06:02 +0100213 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
214 other_->OnKeyFrameRequested(channel_id);
215 });
Niels Möllere0446cb2018-11-30 09:35:52 +0100216 return RTCError::OK();
217}
218
219void MediaTransportPair::LoopbackMediaTransport::SetReceiveAudioSink(
220 MediaTransportAudioSinkInterface* sink) {
221 rtc::CritScope lock(&sink_lock_);
222 if (sink) {
223 RTC_CHECK(audio_sink_ == nullptr);
224 }
225 audio_sink_ = sink;
226}
227
228void MediaTransportPair::LoopbackMediaTransport::SetReceiveVideoSink(
229 MediaTransportVideoSinkInterface* sink) {
230 rtc::CritScope lock(&sink_lock_);
231 if (sink) {
232 RTC_CHECK(video_sink_ == nullptr);
233 }
234 video_sink_ = sink;
235}
236
Niels Möller46879152019-01-07 15:54:47 +0100237void MediaTransportPair::LoopbackMediaTransport::AddTargetTransferRateObserver(
238 TargetTransferRateObserver* observer) {
239 RTC_CHECK(observer);
240 {
241 rtc::CritScope cs(&sink_lock_);
242 RTC_CHECK(std::find(target_transfer_rate_observers_.begin(),
243 target_transfer_rate_observers_.end(),
244 observer) == target_transfer_rate_observers_.end());
245 target_transfer_rate_observers_.push_back(observer);
246 }
247 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
248 RTC_DCHECK_RUN_ON(thread_);
249 const DataRate kBitrate = DataRate::kbps(300);
250 const Timestamp now = Timestamp::us(rtc::TimeMicros());
251
252 TargetTransferRate transfer_rate;
253 transfer_rate.at_time = now;
254 transfer_rate.target_rate = kBitrate;
255 transfer_rate.network_estimate.at_time = now;
256 transfer_rate.network_estimate.round_trip_time = TimeDelta::ms(20);
257 transfer_rate.network_estimate.bwe_period = TimeDelta::seconds(3);
258 transfer_rate.network_estimate.bandwidth = kBitrate;
259
260 rtc::CritScope cs(&sink_lock_);
261
262 for (auto* o : target_transfer_rate_observers_) {
263 o->OnTargetTransferRate(transfer_rate);
264 }
265 });
266}
267
268void MediaTransportPair::LoopbackMediaTransport::
269 RemoveTargetTransferRateObserver(TargetTransferRateObserver* observer) {
270 rtc::CritScope cs(&sink_lock_);
271 auto it = std::find(target_transfer_rate_observers_.begin(),
272 target_transfer_rate_observers_.end(), observer);
273 if (it == target_transfer_rate_observers_.end()) {
274 RTC_LOG(LS_WARNING)
275 << "Attempt to remove an unknown TargetTransferRate observer";
276 return;
277 }
278 target_transfer_rate_observers_.erase(it);
279}
280
281void MediaTransportPair::LoopbackMediaTransport::AddRttObserver(
282 MediaTransportRttObserver* observer) {
283 RTC_CHECK(observer);
284 {
285 rtc::CritScope cs(&sink_lock_);
286 RTC_CHECK(std::find(rtt_observers_.begin(), rtt_observers_.end(),
287 observer) == rtt_observers_.end());
288 rtt_observers_.push_back(observer);
289 }
290 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
291 RTC_DCHECK_RUN_ON(thread_);
292
293 rtc::CritScope cs(&sink_lock_);
294 for (auto* o : rtt_observers_) {
295 o->OnRttUpdated(20);
296 }
297 });
298}
299
300void MediaTransportPair::LoopbackMediaTransport::RemoveRttObserver(
301 MediaTransportRttObserver* observer) {
302 rtc::CritScope cs(&sink_lock_);
303 auto it = std::find(rtt_observers_.begin(), rtt_observers_.end(), observer);
304 if (it == rtt_observers_.end()) {
305 RTC_LOG(LS_WARNING) << "Attempt to remove an unknown RTT observer";
306 return;
307 }
308 rtt_observers_.erase(it);
309}
310
Niels Möllere0446cb2018-11-30 09:35:52 +0100311void MediaTransportPair::LoopbackMediaTransport::SetMediaTransportStateCallback(
312 MediaTransportStateCallback* callback) {
313 rtc::CritScope lock(&sink_lock_);
314 state_callback_ = callback;
315 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
316 RTC_DCHECK_RUN_ON(thread_);
317 OnStateChanged();
318 });
319}
320
321RTCError MediaTransportPair::LoopbackMediaTransport::SendData(
322 int channel_id,
323 const SendDataParams& params,
324 const rtc::CopyOnWriteBuffer& buffer) {
325 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
326 [this, channel_id, params, buffer] {
327 other_->OnData(channel_id, params.type, buffer);
328 });
329 return RTCError::OK();
330}
331
332RTCError MediaTransportPair::LoopbackMediaTransport::CloseChannel(
333 int channel_id) {
334 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
335 other_->OnRemoteCloseChannel(channel_id);
336 rtc::CritScope lock(&sink_lock_);
337 if (data_sink_) {
338 data_sink_->OnChannelClosed(channel_id);
339 }
340 });
341 return RTCError::OK();
342}
343
344void MediaTransportPair::LoopbackMediaTransport::SetDataSink(
345 DataChannelSink* sink) {
346 rtc::CritScope lock(&sink_lock_);
347 data_sink_ = sink;
348}
349void MediaTransportPair::LoopbackMediaTransport::SetState(
350 MediaTransportState state) {
351 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
352 RTC_DCHECK_RUN_ON(thread_);
353 state_ = state;
354 OnStateChanged();
355 });
356}
357
358void MediaTransportPair::LoopbackMediaTransport::FlushAsyncInvokes() {
359 invoker_.Flush(thread_);
360}
361
362MediaTransportPair::Stats
363MediaTransportPair::LoopbackMediaTransport::GetStats() {
364 rtc::CritScope lock(&stats_lock_);
365 return stats_;
366}
367
368void MediaTransportPair::LoopbackMediaTransport::OnData(
369 uint64_t channel_id,
370 MediaTransportEncodedAudioFrame frame) {
371 {
372 rtc::CritScope lock(&sink_lock_);
Niels Möller0d8eed62019-02-18 09:10:30 +0100373 const auto it = audio_sinks_.find(channel_id);
374 if (it != audio_sinks_.end()) {
375 it->second->OnData(frame);
376 } else if (audio_sink_) {
Niels Möllere0446cb2018-11-30 09:35:52 +0100377 audio_sink_->OnData(channel_id, frame);
378 }
379 }
380 {
381 rtc::CritScope lock(&stats_lock_);
382 ++stats_.received_audio_frames;
383 }
384}
385
386void MediaTransportPair::LoopbackMediaTransport::OnData(
387 uint64_t channel_id,
388 MediaTransportEncodedVideoFrame frame) {
389 {
390 rtc::CritScope lock(&sink_lock_);
391 if (video_sink_) {
392 video_sink_->OnData(channel_id, frame);
393 }
394 }
395 {
396 rtc::CritScope lock(&stats_lock_);
397 ++stats_.received_video_frames;
398 }
399}
400
401void MediaTransportPair::LoopbackMediaTransport::OnData(
402 int channel_id,
403 DataMessageType type,
404 const rtc::CopyOnWriteBuffer& buffer) {
405 rtc::CritScope lock(&sink_lock_);
406 if (data_sink_) {
407 data_sink_->OnDataReceived(channel_id, type, buffer);
408 }
409}
410
Niels Möller1c7f5f62018-12-10 11:06:02 +0100411void MediaTransportPair::LoopbackMediaTransport::OnKeyFrameRequested(
412 int channel_id) {
413 rtc::CritScope lock(&sink_lock_);
414 if (key_frame_callback_) {
415 key_frame_callback_->OnKeyFrameRequested(channel_id);
416 }
417}
418
Niels Möllere0446cb2018-11-30 09:35:52 +0100419void MediaTransportPair::LoopbackMediaTransport::OnRemoteCloseChannel(
420 int channel_id) {
421 rtc::CritScope lock(&sink_lock_);
422 if (data_sink_) {
423 data_sink_->OnChannelClosing(channel_id);
424 data_sink_->OnChannelClosed(channel_id);
425 }
426}
427
428void MediaTransportPair::LoopbackMediaTransport::OnStateChanged() {
429 rtc::CritScope lock(&sink_lock_);
430 if (state_callback_) {
431 state_callback_->OnStateChanged(state_);
432 }
433}
Piotr (Peter) Slatala48c54932019-01-28 06:50:38 -0800434
435void MediaTransportPair::LoopbackMediaTransport::SetAllocatedBitrateLimits(
436 const MediaTransportAllocatedBitrateLimits& limits) {}
437
Niels Möllere0446cb2018-11-30 09:35:52 +0100438} // namespace webrtc