blob: 48255b135e7508cab00496630a537fdc379b473c [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
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080055 void SetMediaTransportStateCallback(
56 MediaTransportStateCallback* callback) override {
57 wrapped_->SetMediaTransportStateCallback(callback);
58 }
59
60 RTCError SendData(int channel_id,
61 const SendDataParams& params,
62 const rtc::CopyOnWriteBuffer& buffer) override {
63 return wrapped_->SendData(channel_id, params, buffer);
64 }
65
66 RTCError CloseChannel(int channel_id) override {
67 return wrapped_->CloseChannel(channel_id);
68 }
69
70 void SetDataSink(DataChannelSink* sink) override {
71 wrapped_->SetDataSink(sink);
72 }
73
74 private:
75 MediaTransportInterface* wrapped_;
76};
77
78class WrapperMediaTransportFactory : public MediaTransportFactory {
79 public:
80 explicit WrapperMediaTransportFactory(MediaTransportInterface* wrapped)
81 : wrapped_(wrapped) {}
82
83 RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
84 rtc::PacketTransportInternal* packet_transport,
85 rtc::Thread* network_thread,
86 const MediaTransportSettings& settings) override {
87 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
88 }
89
90 private:
91 MediaTransportInterface* wrapped_;
92};
93
Niels Möller2e47f7c2018-10-16 10:41:42 +020094// Contains two MediaTransportsInterfaces that are connected to each other.
95// Currently supports audio only.
96class MediaTransportPair {
97 public:
Niels Möllerc68d2822018-11-20 14:52:05 +010098 struct Stats {
99 int sent_audio_frames = 0;
100 int received_audio_frames = 0;
101 };
102
Bjorn Mellem273d0292018-11-01 16:42:44 -0700103 explicit MediaTransportPair(rtc::Thread* thread)
104 : first_(thread, &second_), second_(thread, &first_) {}
Niels Möller2e47f7c2018-10-16 10:41:42 +0200105
106 // Ownership stays with MediaTransportPair
Bjorn Mellem273d0292018-11-01 16:42:44 -0700107 MediaTransportInterface* first() { return &first_; }
108 MediaTransportInterface* second() { return &second_; }
109
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800110 std::unique_ptr<MediaTransportFactory> first_factory() {
111 return absl::make_unique<WrapperMediaTransportFactory>(&first_);
112 }
113
114 std::unique_ptr<MediaTransportFactory> second_factory() {
115 return absl::make_unique<WrapperMediaTransportFactory>(&second_);
116 }
117
118 void SetState(MediaTransportState state) {
119 first_.SetState(state);
120 second_.SetState(state);
121 }
122
Bjorn Mellem273d0292018-11-01 16:42:44 -0700123 void FlushAsyncInvokes() {
124 first_.FlushAsyncInvokes();
125 second_.FlushAsyncInvokes();
126 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200127
Niels Möllerc68d2822018-11-20 14:52:05 +0100128 Stats FirstStats() { return first_.GetStats(); }
129 Stats SecondStats() { return second_.GetStats(); }
130
Niels Möller2e47f7c2018-10-16 10:41:42 +0200131 private:
132 class LoopbackMediaTransport : public MediaTransportInterface {
133 public:
Bjorn Mellem273d0292018-11-01 16:42:44 -0700134 LoopbackMediaTransport(rtc::Thread* thread, LoopbackMediaTransport* other)
135 : thread_(thread), other_(other) {}
136
137 ~LoopbackMediaTransport() {
138 rtc::CritScope lock(&sink_lock_);
139 RTC_CHECK(sink_ == nullptr);
140 RTC_CHECK(data_sink_ == nullptr);
141 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200142
143 RTCError SendAudioFrame(uint64_t channel_id,
144 MediaTransportEncodedAudioFrame frame) override {
Niels Möllerc68d2822018-11-20 14:52:05 +0100145 {
146 rtc::CritScope lock(&stats_lock_);
147 ++stats_.sent_audio_frames;
148 }
Bjorn Mellem273d0292018-11-01 16:42:44 -0700149 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
150 [this, channel_id, frame] {
151 other_->OnData(channel_id, std::move(frame));
152 });
Niels Möller2e47f7c2018-10-16 10:41:42 +0200153 return RTCError::OK();
154 };
155
156 RTCError SendVideoFrame(
157 uint64_t channel_id,
158 const MediaTransportEncodedVideoFrame& frame) override {
159 return RTCError::OK();
160 }
161
162 RTCError RequestKeyFrame(uint64_t channel_id) override {
163 return RTCError::OK();
164 }
165
166 void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700167 rtc::CritScope lock(&sink_lock_);
Niels Möller2e47f7c2018-10-16 10:41:42 +0200168 if (sink) {
169 RTC_CHECK(sink_ == nullptr);
170 }
171 sink_ = sink;
172 }
173
174 void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {}
175
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700176 void SetMediaTransportStateCallback(
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800177 MediaTransportStateCallback* callback) override {
178 rtc::CritScope lock(&sink_lock_);
179 state_callback_ = callback;
180 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
181 RTC_DCHECK_RUN_ON(thread_);
182 OnStateChanged();
183 });
184 }
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700185
186 RTCError SendData(int channel_id,
187 const SendDataParams& params,
188 const rtc::CopyOnWriteBuffer& buffer) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700189 invoker_.AsyncInvoke<void>(
190 RTC_FROM_HERE, thread_, [this, channel_id, params, buffer] {
191 other_->OnData(channel_id, params.type, buffer);
192 });
193 return RTCError::OK();
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700194 }
195
196 RTCError CloseChannel(int channel_id) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700197 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
198 other_->OnRemoteCloseChannel(channel_id);
199 rtc::CritScope lock(&sink_lock_);
200 if (data_sink_) {
201 data_sink_->OnChannelClosed(channel_id);
202 }
203 });
204 return RTCError::OK();
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700205 }
206
Bjorn Mellem273d0292018-11-01 16:42:44 -0700207 void SetDataSink(DataChannelSink* sink) override {
208 rtc::CritScope lock(&sink_lock_);
209 data_sink_ = sink;
210 }
211
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800212 void SetState(MediaTransportState state) {
213 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
214 RTC_DCHECK_RUN_ON(thread_);
215 state_ = state;
216 OnStateChanged();
217 });
218 }
219
Bjorn Mellem273d0292018-11-01 16:42:44 -0700220 void FlushAsyncInvokes() { invoker_.Flush(thread_); }
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700221
Niels Möllerc68d2822018-11-20 14:52:05 +0100222 Stats GetStats() {
223 rtc::CritScope lock(&stats_lock_);
224 return stats_;
225 }
226
Niels Möller2e47f7c2018-10-16 10:41:42 +0200227 private:
228 void OnData(uint64_t channel_id, MediaTransportEncodedAudioFrame frame) {
Niels Möllerc68d2822018-11-20 14:52:05 +0100229 {
230 rtc::CritScope lock(&sink_lock_);
231 if (sink_) {
232 sink_->OnData(channel_id, frame);
233 }
234 }
235 {
236 rtc::CritScope lock(&stats_lock_);
237 ++stats_.received_audio_frames;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200238 }
239 }
240
Bjorn Mellem273d0292018-11-01 16:42:44 -0700241 void OnData(int channel_id,
242 DataMessageType type,
243 const rtc::CopyOnWriteBuffer& buffer) {
244 rtc::CritScope lock(&sink_lock_);
245 if (data_sink_) {
246 data_sink_->OnDataReceived(channel_id, type, buffer);
247 }
248 }
249
250 void OnRemoteCloseChannel(int channel_id) {
251 rtc::CritScope lock(&sink_lock_);
252 if (data_sink_) {
253 data_sink_->OnChannelClosing(channel_id);
254 data_sink_->OnChannelClosed(channel_id);
255 }
256 }
257
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800258 void OnStateChanged() RTC_RUN_ON(thread_) {
259 rtc::CritScope lock(&sink_lock_);
260 if (state_callback_) {
261 state_callback_->OnStateChanged(state_);
262 }
263 }
264
Bjorn Mellem273d0292018-11-01 16:42:44 -0700265 rtc::Thread* const thread_;
266 rtc::CriticalSection sink_lock_;
Niels Möllerc68d2822018-11-20 14:52:05 +0100267 rtc::CriticalSection stats_lock_;
Bjorn Mellem273d0292018-11-01 16:42:44 -0700268
269 MediaTransportAudioSinkInterface* sink_ RTC_GUARDED_BY(sink_lock_) =
270 nullptr;
271 DataChannelSink* data_sink_ RTC_GUARDED_BY(sink_lock_) = nullptr;
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800272 MediaTransportStateCallback* state_callback_ RTC_GUARDED_BY(sink_lock_) =
273 nullptr;
274
275 MediaTransportState state_ RTC_GUARDED_BY(thread_) =
276 MediaTransportState::kPending;
277
Bjorn Mellem273d0292018-11-01 16:42:44 -0700278 LoopbackMediaTransport* const other_;
279
Niels Möllerc68d2822018-11-20 14:52:05 +0100280 Stats stats_ RTC_GUARDED_BY(stats_lock_);
281
Bjorn Mellem273d0292018-11-01 16:42:44 -0700282 rtc::AsyncInvoker invoker_;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200283 };
284
Bjorn Mellem273d0292018-11-01 16:42:44 -0700285 LoopbackMediaTransport first_;
286 LoopbackMediaTransport second_;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200287};
288
289} // namespace webrtc
290
291#endif // API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_