blob: e7ccb0afd8fa638198f52a1f1e33f23f6bac1d2a [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_);
112 RTC_CHECK(audio_sink_ == nullptr);
113 RTC_CHECK(video_sink_ == nullptr);
114 RTC_CHECK(data_sink_ == nullptr);
Niels Möller46879152019-01-07 15:54:47 +0100115 RTC_CHECK(target_transfer_rate_observers_.empty());
116 RTC_CHECK(rtt_observers_.empty());
Niels Möllere0446cb2018-11-30 09:35:52 +0100117}
118
119RTCError MediaTransportPair::LoopbackMediaTransport::SendAudioFrame(
120 uint64_t channel_id,
121 MediaTransportEncodedAudioFrame frame) {
122 {
123 rtc::CritScope lock(&stats_lock_);
124 ++stats_.sent_audio_frames;
125 }
126 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id, frame] {
127 other_->OnData(channel_id, std::move(frame));
128 });
129 return RTCError::OK();
130}
131
132RTCError MediaTransportPair::LoopbackMediaTransport::SendVideoFrame(
133 uint64_t channel_id,
134 const MediaTransportEncodedVideoFrame& frame) {
135 {
136 rtc::CritScope lock(&stats_lock_);
137 ++stats_.sent_video_frames;
138 }
139 // Ensure that we own the referenced data.
140 MediaTransportEncodedVideoFrame frame_copy = frame;
141 frame_copy.Retain();
142 invoker_.AsyncInvoke<void>(
143 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy] {
144 other_->OnData(channel_id, std::move(frame_copy));
145 });
146 return RTCError::OK();
147}
148
Niels Möller1c7f5f62018-12-10 11:06:02 +0100149void MediaTransportPair::LoopbackMediaTransport::SetKeyFrameRequestCallback(
150 MediaTransportKeyFrameRequestCallback* callback) {
151 rtc::CritScope lock(&sink_lock_);
152 if (callback) {
153 RTC_CHECK(key_frame_callback_ == nullptr);
154 }
155 key_frame_callback_ = callback;
156}
157
Niels Möllere0446cb2018-11-30 09:35:52 +0100158RTCError MediaTransportPair::LoopbackMediaTransport::RequestKeyFrame(
159 uint64_t channel_id) {
Niels Möller1c7f5f62018-12-10 11:06:02 +0100160 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
161 other_->OnKeyFrameRequested(channel_id);
162 });
Niels Möllere0446cb2018-11-30 09:35:52 +0100163 return RTCError::OK();
164}
165
166void MediaTransportPair::LoopbackMediaTransport::SetReceiveAudioSink(
167 MediaTransportAudioSinkInterface* sink) {
168 rtc::CritScope lock(&sink_lock_);
169 if (sink) {
170 RTC_CHECK(audio_sink_ == nullptr);
171 }
172 audio_sink_ = sink;
173}
174
175void MediaTransportPair::LoopbackMediaTransport::SetReceiveVideoSink(
176 MediaTransportVideoSinkInterface* sink) {
177 rtc::CritScope lock(&sink_lock_);
178 if (sink) {
179 RTC_CHECK(video_sink_ == nullptr);
180 }
181 video_sink_ = sink;
182}
183
Niels Möller46879152019-01-07 15:54:47 +0100184void MediaTransportPair::LoopbackMediaTransport::AddTargetTransferRateObserver(
185 TargetTransferRateObserver* observer) {
186 RTC_CHECK(observer);
187 {
188 rtc::CritScope cs(&sink_lock_);
189 RTC_CHECK(std::find(target_transfer_rate_observers_.begin(),
190 target_transfer_rate_observers_.end(),
191 observer) == target_transfer_rate_observers_.end());
192 target_transfer_rate_observers_.push_back(observer);
193 }
194 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
195 RTC_DCHECK_RUN_ON(thread_);
196 const DataRate kBitrate = DataRate::kbps(300);
197 const Timestamp now = Timestamp::us(rtc::TimeMicros());
198
199 TargetTransferRate transfer_rate;
200 transfer_rate.at_time = now;
201 transfer_rate.target_rate = kBitrate;
202 transfer_rate.network_estimate.at_time = now;
203 transfer_rate.network_estimate.round_trip_time = TimeDelta::ms(20);
204 transfer_rate.network_estimate.bwe_period = TimeDelta::seconds(3);
205 transfer_rate.network_estimate.bandwidth = kBitrate;
206
207 rtc::CritScope cs(&sink_lock_);
208
209 for (auto* o : target_transfer_rate_observers_) {
210 o->OnTargetTransferRate(transfer_rate);
211 }
212 });
213}
214
215void MediaTransportPair::LoopbackMediaTransport::
216 RemoveTargetTransferRateObserver(TargetTransferRateObserver* observer) {
217 rtc::CritScope cs(&sink_lock_);
218 auto it = std::find(target_transfer_rate_observers_.begin(),
219 target_transfer_rate_observers_.end(), observer);
220 if (it == target_transfer_rate_observers_.end()) {
221 RTC_LOG(LS_WARNING)
222 << "Attempt to remove an unknown TargetTransferRate observer";
223 return;
224 }
225 target_transfer_rate_observers_.erase(it);
226}
227
228void MediaTransportPair::LoopbackMediaTransport::AddRttObserver(
229 MediaTransportRttObserver* observer) {
230 RTC_CHECK(observer);
231 {
232 rtc::CritScope cs(&sink_lock_);
233 RTC_CHECK(std::find(rtt_observers_.begin(), rtt_observers_.end(),
234 observer) == rtt_observers_.end());
235 rtt_observers_.push_back(observer);
236 }
237 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
238 RTC_DCHECK_RUN_ON(thread_);
239
240 rtc::CritScope cs(&sink_lock_);
241 for (auto* o : rtt_observers_) {
242 o->OnRttUpdated(20);
243 }
244 });
245}
246
247void MediaTransportPair::LoopbackMediaTransport::RemoveRttObserver(
248 MediaTransportRttObserver* observer) {
249 rtc::CritScope cs(&sink_lock_);
250 auto it = std::find(rtt_observers_.begin(), rtt_observers_.end(), observer);
251 if (it == rtt_observers_.end()) {
252 RTC_LOG(LS_WARNING) << "Attempt to remove an unknown RTT observer";
253 return;
254 }
255 rtt_observers_.erase(it);
256}
257
Niels Möllere0446cb2018-11-30 09:35:52 +0100258void MediaTransportPair::LoopbackMediaTransport::SetMediaTransportStateCallback(
259 MediaTransportStateCallback* callback) {
260 rtc::CritScope lock(&sink_lock_);
261 state_callback_ = callback;
262 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
263 RTC_DCHECK_RUN_ON(thread_);
264 OnStateChanged();
265 });
266}
267
268RTCError MediaTransportPair::LoopbackMediaTransport::SendData(
269 int channel_id,
270 const SendDataParams& params,
271 const rtc::CopyOnWriteBuffer& buffer) {
272 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
273 [this, channel_id, params, buffer] {
274 other_->OnData(channel_id, params.type, buffer);
275 });
276 return RTCError::OK();
277}
278
279RTCError MediaTransportPair::LoopbackMediaTransport::CloseChannel(
280 int channel_id) {
281 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
282 other_->OnRemoteCloseChannel(channel_id);
283 rtc::CritScope lock(&sink_lock_);
284 if (data_sink_) {
285 data_sink_->OnChannelClosed(channel_id);
286 }
287 });
288 return RTCError::OK();
289}
290
291void MediaTransportPair::LoopbackMediaTransport::SetDataSink(
292 DataChannelSink* sink) {
293 rtc::CritScope lock(&sink_lock_);
294 data_sink_ = sink;
295}
296void MediaTransportPair::LoopbackMediaTransport::SetState(
297 MediaTransportState state) {
298 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
299 RTC_DCHECK_RUN_ON(thread_);
300 state_ = state;
301 OnStateChanged();
302 });
303}
304
305void MediaTransportPair::LoopbackMediaTransport::FlushAsyncInvokes() {
306 invoker_.Flush(thread_);
307}
308
309MediaTransportPair::Stats
310MediaTransportPair::LoopbackMediaTransport::GetStats() {
311 rtc::CritScope lock(&stats_lock_);
312 return stats_;
313}
314
315void MediaTransportPair::LoopbackMediaTransport::OnData(
316 uint64_t channel_id,
317 MediaTransportEncodedAudioFrame frame) {
318 {
319 rtc::CritScope lock(&sink_lock_);
320 if (audio_sink_) {
321 audio_sink_->OnData(channel_id, frame);
322 }
323 }
324 {
325 rtc::CritScope lock(&stats_lock_);
326 ++stats_.received_audio_frames;
327 }
328}
329
330void MediaTransportPair::LoopbackMediaTransport::OnData(
331 uint64_t channel_id,
332 MediaTransportEncodedVideoFrame frame) {
333 {
334 rtc::CritScope lock(&sink_lock_);
335 if (video_sink_) {
336 video_sink_->OnData(channel_id, frame);
337 }
338 }
339 {
340 rtc::CritScope lock(&stats_lock_);
341 ++stats_.received_video_frames;
342 }
343}
344
345void MediaTransportPair::LoopbackMediaTransport::OnData(
346 int channel_id,
347 DataMessageType type,
348 const rtc::CopyOnWriteBuffer& buffer) {
349 rtc::CritScope lock(&sink_lock_);
350 if (data_sink_) {
351 data_sink_->OnDataReceived(channel_id, type, buffer);
352 }
353}
354
Niels Möller1c7f5f62018-12-10 11:06:02 +0100355void MediaTransportPair::LoopbackMediaTransport::OnKeyFrameRequested(
356 int channel_id) {
357 rtc::CritScope lock(&sink_lock_);
358 if (key_frame_callback_) {
359 key_frame_callback_->OnKeyFrameRequested(channel_id);
360 }
361}
362
Niels Möllere0446cb2018-11-30 09:35:52 +0100363void MediaTransportPair::LoopbackMediaTransport::OnRemoteCloseChannel(
364 int channel_id) {
365 rtc::CritScope lock(&sink_lock_);
366 if (data_sink_) {
367 data_sink_->OnChannelClosing(channel_id);
368 data_sink_->OnChannelClosed(channel_id);
369 }
370}
371
372void MediaTransportPair::LoopbackMediaTransport::OnStateChanged() {
373 rtc::CritScope lock(&sink_lock_);
374 if (state_callback_) {
375 state_callback_->OnStateChanged(state_);
376 }
377}
Piotr (Peter) Slatala48c54932019-01-28 06:50:38 -0800378
379void MediaTransportPair::LoopbackMediaTransport::SetAllocatedBitrateLimits(
380 const MediaTransportAllocatedBitrateLimits& limits) {}
381
Niels Möllere0446cb2018-11-30 09:35:52 +0100382} // namespace webrtc