blob: dbb674db8330090c182f46656b27c6f8375c3506 [file] [log] [blame]
Niels Möller2e47f7c2018-10-16 10:41:42 +02001/*
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#ifndef API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_
12#define API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_
13
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080014#include <memory>
Niels Möller2e47f7c2018-10-16 10:41:42 +020015#include <utility>
16
17#include "api/media_transport_interface.h"
Bjorn Mellem273d0292018-11-01 16:42:44 -070018#include "rtc_base/asyncinvoker.h"
19#include "rtc_base/criticalsection.h"
20#include "rtc_base/thread.h"
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080021#include "rtc_base/thread_checker.h"
Niels Möller2e47f7c2018-10-16 10:41:42 +020022
23namespace webrtc {
24
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080025// Wrapper used to hand out unique_ptrs to loopback media transports without
26// ownership changes.
27class WrapperMediaTransport : public MediaTransportInterface {
28 public:
29 explicit WrapperMediaTransport(MediaTransportInterface* wrapped)
30 : wrapped_(wrapped) {}
31
32 RTCError SendAudioFrame(uint64_t channel_id,
33 MediaTransportEncodedAudioFrame frame) override {
34 return wrapped_->SendAudioFrame(channel_id, std::move(frame));
35 }
36
37 RTCError SendVideoFrame(
38 uint64_t channel_id,
39 const MediaTransportEncodedVideoFrame& frame) override {
40 return wrapped_->SendVideoFrame(channel_id, frame);
41 }
42
43 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
55 void SetTargetTransferRateObserver(
56 webrtc::TargetTransferRateObserver* observer) override {
57 wrapped_->SetTargetTransferRateObserver(observer);
58 }
59
60 void SetMediaTransportStateCallback(
61 MediaTransportStateCallback* callback) override {
62 wrapped_->SetMediaTransportStateCallback(callback);
63 }
64
65 RTCError SendData(int channel_id,
66 const SendDataParams& params,
67 const rtc::CopyOnWriteBuffer& buffer) override {
68 return wrapped_->SendData(channel_id, params, buffer);
69 }
70
71 RTCError CloseChannel(int channel_id) override {
72 return wrapped_->CloseChannel(channel_id);
73 }
74
75 void SetDataSink(DataChannelSink* sink) override {
76 wrapped_->SetDataSink(sink);
77 }
78
79 private:
80 MediaTransportInterface* wrapped_;
81};
82
83class WrapperMediaTransportFactory : public MediaTransportFactory {
84 public:
85 explicit WrapperMediaTransportFactory(MediaTransportInterface* wrapped)
86 : wrapped_(wrapped) {}
87
88 RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
89 rtc::PacketTransportInternal* packet_transport,
90 rtc::Thread* network_thread,
91 const MediaTransportSettings& settings) override {
92 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
93 }
94
95 private:
96 MediaTransportInterface* wrapped_;
97};
98
Niels Möller2e47f7c2018-10-16 10:41:42 +020099// Contains two MediaTransportsInterfaces that are connected to each other.
100// Currently supports audio only.
101class MediaTransportPair {
102 public:
Niels Möllerc68d2822018-11-20 14:52:05 +0100103 struct Stats {
104 int sent_audio_frames = 0;
105 int received_audio_frames = 0;
106 };
107
Bjorn Mellem273d0292018-11-01 16:42:44 -0700108 explicit MediaTransportPair(rtc::Thread* thread)
109 : first_(thread, &second_), second_(thread, &first_) {}
Niels Möller2e47f7c2018-10-16 10:41:42 +0200110
111 // Ownership stays with MediaTransportPair
Bjorn Mellem273d0292018-11-01 16:42:44 -0700112 MediaTransportInterface* first() { return &first_; }
113 MediaTransportInterface* second() { return &second_; }
114
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800115 std::unique_ptr<MediaTransportFactory> first_factory() {
116 return absl::make_unique<WrapperMediaTransportFactory>(&first_);
117 }
118
119 std::unique_ptr<MediaTransportFactory> second_factory() {
120 return absl::make_unique<WrapperMediaTransportFactory>(&second_);
121 }
122
123 void SetState(MediaTransportState state) {
124 first_.SetState(state);
125 second_.SetState(state);
126 }
127
Bjorn Mellem273d0292018-11-01 16:42:44 -0700128 void FlushAsyncInvokes() {
129 first_.FlushAsyncInvokes();
130 second_.FlushAsyncInvokes();
131 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200132
Niels Möllerc68d2822018-11-20 14:52:05 +0100133 Stats FirstStats() { return first_.GetStats(); }
134 Stats SecondStats() { return second_.GetStats(); }
135
Niels Möller2e47f7c2018-10-16 10:41:42 +0200136 private:
137 class LoopbackMediaTransport : public MediaTransportInterface {
138 public:
Bjorn Mellem273d0292018-11-01 16:42:44 -0700139 LoopbackMediaTransport(rtc::Thread* thread, LoopbackMediaTransport* other)
140 : thread_(thread), other_(other) {}
141
142 ~LoopbackMediaTransport() {
143 rtc::CritScope lock(&sink_lock_);
144 RTC_CHECK(sink_ == nullptr);
145 RTC_CHECK(data_sink_ == nullptr);
146 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200147
148 RTCError SendAudioFrame(uint64_t channel_id,
149 MediaTransportEncodedAudioFrame frame) override {
Niels Möllerc68d2822018-11-20 14:52:05 +0100150 {
151 rtc::CritScope lock(&stats_lock_);
152 ++stats_.sent_audio_frames;
153 }
Bjorn Mellem273d0292018-11-01 16:42:44 -0700154 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
155 [this, channel_id, frame] {
156 other_->OnData(channel_id, std::move(frame));
157 });
Niels Möller2e47f7c2018-10-16 10:41:42 +0200158 return RTCError::OK();
159 };
160
161 RTCError SendVideoFrame(
162 uint64_t channel_id,
163 const MediaTransportEncodedVideoFrame& frame) override {
164 return RTCError::OK();
165 }
166
167 RTCError RequestKeyFrame(uint64_t channel_id) override {
168 return RTCError::OK();
169 }
170
171 void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700172 rtc::CritScope lock(&sink_lock_);
Niels Möller2e47f7c2018-10-16 10:41:42 +0200173 if (sink) {
174 RTC_CHECK(sink_ == nullptr);
175 }
176 sink_ = sink;
177 }
178
179 void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {}
180
Piotr (Peter) Slatala6b9d8232018-10-26 07:59:46 -0700181 void SetTargetTransferRateObserver(
182 webrtc::TargetTransferRateObserver* observer) override {}
183
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700184 void SetMediaTransportStateCallback(
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800185 MediaTransportStateCallback* callback) override {
186 rtc::CritScope lock(&sink_lock_);
187 state_callback_ = callback;
188 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
189 RTC_DCHECK_RUN_ON(thread_);
190 OnStateChanged();
191 });
192 }
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700193
194 RTCError SendData(int channel_id,
195 const SendDataParams& params,
196 const rtc::CopyOnWriteBuffer& buffer) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700197 invoker_.AsyncInvoke<void>(
198 RTC_FROM_HERE, thread_, [this, channel_id, params, buffer] {
199 other_->OnData(channel_id, params.type, buffer);
200 });
201 return RTCError::OK();
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700202 }
203
204 RTCError CloseChannel(int channel_id) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700205 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
206 other_->OnRemoteCloseChannel(channel_id);
207 rtc::CritScope lock(&sink_lock_);
208 if (data_sink_) {
209 data_sink_->OnChannelClosed(channel_id);
210 }
211 });
212 return RTCError::OK();
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700213 }
214
Bjorn Mellem273d0292018-11-01 16:42:44 -0700215 void SetDataSink(DataChannelSink* sink) override {
216 rtc::CritScope lock(&sink_lock_);
217 data_sink_ = sink;
218 }
219
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800220 void SetState(MediaTransportState state) {
221 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
222 RTC_DCHECK_RUN_ON(thread_);
223 state_ = state;
224 OnStateChanged();
225 });
226 }
227
Bjorn Mellem273d0292018-11-01 16:42:44 -0700228 void FlushAsyncInvokes() { invoker_.Flush(thread_); }
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700229
Niels Möllerc68d2822018-11-20 14:52:05 +0100230 Stats GetStats() {
231 rtc::CritScope lock(&stats_lock_);
232 return stats_;
233 }
234
Niels Möller2e47f7c2018-10-16 10:41:42 +0200235 private:
236 void OnData(uint64_t channel_id, MediaTransportEncodedAudioFrame frame) {
Niels Möllerc68d2822018-11-20 14:52:05 +0100237 {
238 rtc::CritScope lock(&sink_lock_);
239 if (sink_) {
240 sink_->OnData(channel_id, frame);
241 }
242 }
243 {
244 rtc::CritScope lock(&stats_lock_);
245 ++stats_.received_audio_frames;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200246 }
247 }
248
Bjorn Mellem273d0292018-11-01 16:42:44 -0700249 void OnData(int channel_id,
250 DataMessageType type,
251 const rtc::CopyOnWriteBuffer& buffer) {
252 rtc::CritScope lock(&sink_lock_);
253 if (data_sink_) {
254 data_sink_->OnDataReceived(channel_id, type, buffer);
255 }
256 }
257
258 void OnRemoteCloseChannel(int channel_id) {
259 rtc::CritScope lock(&sink_lock_);
260 if (data_sink_) {
261 data_sink_->OnChannelClosing(channel_id);
262 data_sink_->OnChannelClosed(channel_id);
263 }
264 }
265
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800266 void OnStateChanged() RTC_RUN_ON(thread_) {
267 rtc::CritScope lock(&sink_lock_);
268 if (state_callback_) {
269 state_callback_->OnStateChanged(state_);
270 }
271 }
272
Bjorn Mellem273d0292018-11-01 16:42:44 -0700273 rtc::Thread* const thread_;
274 rtc::CriticalSection sink_lock_;
Niels Möllerc68d2822018-11-20 14:52:05 +0100275 rtc::CriticalSection stats_lock_;
Bjorn Mellem273d0292018-11-01 16:42:44 -0700276
277 MediaTransportAudioSinkInterface* sink_ RTC_GUARDED_BY(sink_lock_) =
278 nullptr;
279 DataChannelSink* data_sink_ RTC_GUARDED_BY(sink_lock_) = nullptr;
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800280 MediaTransportStateCallback* state_callback_ RTC_GUARDED_BY(sink_lock_) =
281 nullptr;
282
283 MediaTransportState state_ RTC_GUARDED_BY(thread_) =
284 MediaTransportState::kPending;
285
Bjorn Mellem273d0292018-11-01 16:42:44 -0700286 LoopbackMediaTransport* const other_;
287
Niels Möllerc68d2822018-11-20 14:52:05 +0100288 Stats stats_ RTC_GUARDED_BY(stats_lock_);
289
Bjorn Mellem273d0292018-11-01 16:42:44 -0700290 rtc::AsyncInvoker invoker_;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200291 };
292
Bjorn Mellem273d0292018-11-01 16:42:44 -0700293 LoopbackMediaTransport first_;
294 LoopbackMediaTransport second_;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200295};
296
297} // namespace webrtc
298
299#endif // API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_