blob: 40415e2797c38c13c55b36212f426cb743adb99c [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"
Niels Möller46879152019-01-07 15:54:47 +010014#include "rtc_base/timeutils.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
84 private:
85 MediaTransportInterface* wrapped_;
86};
87
88} // namespace
89
90WrapperMediaTransportFactory::WrapperMediaTransportFactory(
91 MediaTransportInterface* wrapped)
92 : wrapped_(wrapped) {}
93
94RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
95WrapperMediaTransportFactory::CreateMediaTransport(
96 rtc::PacketTransportInternal* packet_transport,
97 rtc::Thread* network_thread,
98 const MediaTransportSettings& settings) {
99 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
100}
101
102MediaTransportPair::LoopbackMediaTransport::LoopbackMediaTransport(
103 rtc::Thread* thread,
104 LoopbackMediaTransport* other)
105 : thread_(thread), other_(other) {}
106
107MediaTransportPair::LoopbackMediaTransport::~LoopbackMediaTransport() {
108 rtc::CritScope lock(&sink_lock_);
109 RTC_CHECK(audio_sink_ == nullptr);
110 RTC_CHECK(video_sink_ == nullptr);
111 RTC_CHECK(data_sink_ == nullptr);
Niels Möller46879152019-01-07 15:54:47 +0100112 RTC_CHECK(target_transfer_rate_observers_.empty());
113 RTC_CHECK(rtt_observers_.empty());
Niels Möllere0446cb2018-11-30 09:35:52 +0100114}
115
116RTCError MediaTransportPair::LoopbackMediaTransport::SendAudioFrame(
117 uint64_t channel_id,
118 MediaTransportEncodedAudioFrame frame) {
119 {
120 rtc::CritScope lock(&stats_lock_);
121 ++stats_.sent_audio_frames;
122 }
123 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id, frame] {
124 other_->OnData(channel_id, std::move(frame));
125 });
126 return RTCError::OK();
127}
128
129RTCError MediaTransportPair::LoopbackMediaTransport::SendVideoFrame(
130 uint64_t channel_id,
131 const MediaTransportEncodedVideoFrame& frame) {
132 {
133 rtc::CritScope lock(&stats_lock_);
134 ++stats_.sent_video_frames;
135 }
136 // Ensure that we own the referenced data.
137 MediaTransportEncodedVideoFrame frame_copy = frame;
138 frame_copy.Retain();
139 invoker_.AsyncInvoke<void>(
140 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy] {
141 other_->OnData(channel_id, std::move(frame_copy));
142 });
143 return RTCError::OK();
144}
145
Niels Möller1c7f5f62018-12-10 11:06:02 +0100146void MediaTransportPair::LoopbackMediaTransport::SetKeyFrameRequestCallback(
147 MediaTransportKeyFrameRequestCallback* callback) {
148 rtc::CritScope lock(&sink_lock_);
149 if (callback) {
150 RTC_CHECK(key_frame_callback_ == nullptr);
151 }
152 key_frame_callback_ = callback;
153}
154
Niels Möllere0446cb2018-11-30 09:35:52 +0100155RTCError MediaTransportPair::LoopbackMediaTransport::RequestKeyFrame(
156 uint64_t channel_id) {
Niels Möller1c7f5f62018-12-10 11:06:02 +0100157 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
158 other_->OnKeyFrameRequested(channel_id);
159 });
Niels Möllere0446cb2018-11-30 09:35:52 +0100160 return RTCError::OK();
161}
162
163void MediaTransportPair::LoopbackMediaTransport::SetReceiveAudioSink(
164 MediaTransportAudioSinkInterface* sink) {
165 rtc::CritScope lock(&sink_lock_);
166 if (sink) {
167 RTC_CHECK(audio_sink_ == nullptr);
168 }
169 audio_sink_ = sink;
170}
171
172void MediaTransportPair::LoopbackMediaTransport::SetReceiveVideoSink(
173 MediaTransportVideoSinkInterface* sink) {
174 rtc::CritScope lock(&sink_lock_);
175 if (sink) {
176 RTC_CHECK(video_sink_ == nullptr);
177 }
178 video_sink_ = sink;
179}
180
Niels Möller46879152019-01-07 15:54:47 +0100181void MediaTransportPair::LoopbackMediaTransport::AddTargetTransferRateObserver(
182 TargetTransferRateObserver* observer) {
183 RTC_CHECK(observer);
184 {
185 rtc::CritScope cs(&sink_lock_);
186 RTC_CHECK(std::find(target_transfer_rate_observers_.begin(),
187 target_transfer_rate_observers_.end(),
188 observer) == target_transfer_rate_observers_.end());
189 target_transfer_rate_observers_.push_back(observer);
190 }
191 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
192 RTC_DCHECK_RUN_ON(thread_);
193 const DataRate kBitrate = DataRate::kbps(300);
194 const Timestamp now = Timestamp::us(rtc::TimeMicros());
195
196 TargetTransferRate transfer_rate;
197 transfer_rate.at_time = now;
198 transfer_rate.target_rate = kBitrate;
199 transfer_rate.network_estimate.at_time = now;
200 transfer_rate.network_estimate.round_trip_time = TimeDelta::ms(20);
201 transfer_rate.network_estimate.bwe_period = TimeDelta::seconds(3);
202 transfer_rate.network_estimate.bandwidth = kBitrate;
203
204 rtc::CritScope cs(&sink_lock_);
205
206 for (auto* o : target_transfer_rate_observers_) {
207 o->OnTargetTransferRate(transfer_rate);
208 }
209 });
210}
211
212void MediaTransportPair::LoopbackMediaTransport::
213 RemoveTargetTransferRateObserver(TargetTransferRateObserver* observer) {
214 rtc::CritScope cs(&sink_lock_);
215 auto it = std::find(target_transfer_rate_observers_.begin(),
216 target_transfer_rate_observers_.end(), observer);
217 if (it == target_transfer_rate_observers_.end()) {
218 RTC_LOG(LS_WARNING)
219 << "Attempt to remove an unknown TargetTransferRate observer";
220 return;
221 }
222 target_transfer_rate_observers_.erase(it);
223}
224
225void MediaTransportPair::LoopbackMediaTransport::AddRttObserver(
226 MediaTransportRttObserver* observer) {
227 RTC_CHECK(observer);
228 {
229 rtc::CritScope cs(&sink_lock_);
230 RTC_CHECK(std::find(rtt_observers_.begin(), rtt_observers_.end(),
231 observer) == rtt_observers_.end());
232 rtt_observers_.push_back(observer);
233 }
234 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
235 RTC_DCHECK_RUN_ON(thread_);
236
237 rtc::CritScope cs(&sink_lock_);
238 for (auto* o : rtt_observers_) {
239 o->OnRttUpdated(20);
240 }
241 });
242}
243
244void MediaTransportPair::LoopbackMediaTransport::RemoveRttObserver(
245 MediaTransportRttObserver* observer) {
246 rtc::CritScope cs(&sink_lock_);
247 auto it = std::find(rtt_observers_.begin(), rtt_observers_.end(), observer);
248 if (it == rtt_observers_.end()) {
249 RTC_LOG(LS_WARNING) << "Attempt to remove an unknown RTT observer";
250 return;
251 }
252 rtt_observers_.erase(it);
253}
254
Niels Möllere0446cb2018-11-30 09:35:52 +0100255void MediaTransportPair::LoopbackMediaTransport::SetMediaTransportStateCallback(
256 MediaTransportStateCallback* callback) {
257 rtc::CritScope lock(&sink_lock_);
258 state_callback_ = callback;
259 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
260 RTC_DCHECK_RUN_ON(thread_);
261 OnStateChanged();
262 });
263}
264
265RTCError MediaTransportPair::LoopbackMediaTransport::SendData(
266 int channel_id,
267 const SendDataParams& params,
268 const rtc::CopyOnWriteBuffer& buffer) {
269 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
270 [this, channel_id, params, buffer] {
271 other_->OnData(channel_id, params.type, buffer);
272 });
273 return RTCError::OK();
274}
275
276RTCError MediaTransportPair::LoopbackMediaTransport::CloseChannel(
277 int channel_id) {
278 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
279 other_->OnRemoteCloseChannel(channel_id);
280 rtc::CritScope lock(&sink_lock_);
281 if (data_sink_) {
282 data_sink_->OnChannelClosed(channel_id);
283 }
284 });
285 return RTCError::OK();
286}
287
288void MediaTransportPair::LoopbackMediaTransport::SetDataSink(
289 DataChannelSink* sink) {
290 rtc::CritScope lock(&sink_lock_);
291 data_sink_ = sink;
292}
293void MediaTransportPair::LoopbackMediaTransport::SetState(
294 MediaTransportState state) {
295 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
296 RTC_DCHECK_RUN_ON(thread_);
297 state_ = state;
298 OnStateChanged();
299 });
300}
301
302void MediaTransportPair::LoopbackMediaTransport::FlushAsyncInvokes() {
303 invoker_.Flush(thread_);
304}
305
306MediaTransportPair::Stats
307MediaTransportPair::LoopbackMediaTransport::GetStats() {
308 rtc::CritScope lock(&stats_lock_);
309 return stats_;
310}
311
312void MediaTransportPair::LoopbackMediaTransport::OnData(
313 uint64_t channel_id,
314 MediaTransportEncodedAudioFrame frame) {
315 {
316 rtc::CritScope lock(&sink_lock_);
317 if (audio_sink_) {
318 audio_sink_->OnData(channel_id, frame);
319 }
320 }
321 {
322 rtc::CritScope lock(&stats_lock_);
323 ++stats_.received_audio_frames;
324 }
325}
326
327void MediaTransportPair::LoopbackMediaTransport::OnData(
328 uint64_t channel_id,
329 MediaTransportEncodedVideoFrame frame) {
330 {
331 rtc::CritScope lock(&sink_lock_);
332 if (video_sink_) {
333 video_sink_->OnData(channel_id, frame);
334 }
335 }
336 {
337 rtc::CritScope lock(&stats_lock_);
338 ++stats_.received_video_frames;
339 }
340}
341
342void MediaTransportPair::LoopbackMediaTransport::OnData(
343 int channel_id,
344 DataMessageType type,
345 const rtc::CopyOnWriteBuffer& buffer) {
346 rtc::CritScope lock(&sink_lock_);
347 if (data_sink_) {
348 data_sink_->OnDataReceived(channel_id, type, buffer);
349 }
350}
351
Niels Möller1c7f5f62018-12-10 11:06:02 +0100352void MediaTransportPair::LoopbackMediaTransport::OnKeyFrameRequested(
353 int channel_id) {
354 rtc::CritScope lock(&sink_lock_);
355 if (key_frame_callback_) {
356 key_frame_callback_->OnKeyFrameRequested(channel_id);
357 }
358}
359
Niels Möllere0446cb2018-11-30 09:35:52 +0100360void MediaTransportPair::LoopbackMediaTransport::OnRemoteCloseChannel(
361 int channel_id) {
362 rtc::CritScope lock(&sink_lock_);
363 if (data_sink_) {
364 data_sink_->OnChannelClosing(channel_id);
365 data_sink_->OnChannelClosed(channel_id);
366 }
367}
368
369void MediaTransportPair::LoopbackMediaTransport::OnStateChanged() {
370 rtc::CritScope lock(&sink_lock_);
371 if (state_callback_) {
372 state_callback_->OnStateChanged(state_);
373 }
374}
375} // namespace webrtc