blob: 26207890f3c9627df1821b53fd487b0ca7ced6f4 [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;
Niels Möllerd5696fb2018-11-28 15:34:37 +0100101 int sent_video_frames = 0;
102 int received_video_frames = 0;
Niels Möllerc68d2822018-11-20 14:52:05 +0100103 };
104
Bjorn Mellem273d0292018-11-01 16:42:44 -0700105 explicit MediaTransportPair(rtc::Thread* thread)
106 : first_(thread, &second_), second_(thread, &first_) {}
Niels Möller2e47f7c2018-10-16 10:41:42 +0200107
108 // Ownership stays with MediaTransportPair
Bjorn Mellem273d0292018-11-01 16:42:44 -0700109 MediaTransportInterface* first() { return &first_; }
110 MediaTransportInterface* second() { return &second_; }
111
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800112 std::unique_ptr<MediaTransportFactory> first_factory() {
113 return absl::make_unique<WrapperMediaTransportFactory>(&first_);
114 }
115
116 std::unique_ptr<MediaTransportFactory> second_factory() {
117 return absl::make_unique<WrapperMediaTransportFactory>(&second_);
118 }
119
120 void SetState(MediaTransportState state) {
121 first_.SetState(state);
122 second_.SetState(state);
123 }
124
Bjorn Mellem273d0292018-11-01 16:42:44 -0700125 void FlushAsyncInvokes() {
126 first_.FlushAsyncInvokes();
127 second_.FlushAsyncInvokes();
128 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200129
Niels Möllerc68d2822018-11-20 14:52:05 +0100130 Stats FirstStats() { return first_.GetStats(); }
131 Stats SecondStats() { return second_.GetStats(); }
132
Niels Möller2e47f7c2018-10-16 10:41:42 +0200133 private:
134 class LoopbackMediaTransport : public MediaTransportInterface {
135 public:
Bjorn Mellem273d0292018-11-01 16:42:44 -0700136 LoopbackMediaTransport(rtc::Thread* thread, LoopbackMediaTransport* other)
137 : thread_(thread), other_(other) {}
138
139 ~LoopbackMediaTransport() {
140 rtc::CritScope lock(&sink_lock_);
Niels Möllerd5696fb2018-11-28 15:34:37 +0100141 RTC_CHECK(audio_sink_ == nullptr);
142 RTC_CHECK(video_sink_ == nullptr);
Bjorn Mellem273d0292018-11-01 16:42:44 -0700143 RTC_CHECK(data_sink_ == nullptr);
144 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200145
146 RTCError SendAudioFrame(uint64_t channel_id,
147 MediaTransportEncodedAudioFrame frame) override {
Niels Möllerc68d2822018-11-20 14:52:05 +0100148 {
149 rtc::CritScope lock(&stats_lock_);
150 ++stats_.sent_audio_frames;
151 }
Bjorn Mellem273d0292018-11-01 16:42:44 -0700152 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
153 [this, channel_id, frame] {
154 other_->OnData(channel_id, std::move(frame));
155 });
Niels Möller2e47f7c2018-10-16 10:41:42 +0200156 return RTCError::OK();
157 };
158
159 RTCError SendVideoFrame(
160 uint64_t channel_id,
161 const MediaTransportEncodedVideoFrame& frame) override {
Niels Möllerd5696fb2018-11-28 15:34:37 +0100162 {
163 rtc::CritScope lock(&stats_lock_);
164 ++stats_.sent_video_frames;
165 }
166 // Ensure that we own the referenced data.
167 MediaTransportEncodedVideoFrame frame_copy = frame;
168 frame_copy.Retain();
169 invoker_.AsyncInvoke<void>(
170 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy] {
171 other_->OnData(channel_id, std::move(frame_copy));
172 });
Niels Möller2e47f7c2018-10-16 10:41:42 +0200173 return RTCError::OK();
174 }
175
176 RTCError RequestKeyFrame(uint64_t channel_id) override {
177 return RTCError::OK();
178 }
179
180 void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700181 rtc::CritScope lock(&sink_lock_);
Niels Möller2e47f7c2018-10-16 10:41:42 +0200182 if (sink) {
Niels Möllerd5696fb2018-11-28 15:34:37 +0100183 RTC_CHECK(audio_sink_ == nullptr);
Niels Möller2e47f7c2018-10-16 10:41:42 +0200184 }
Niels Möllerd5696fb2018-11-28 15:34:37 +0100185 audio_sink_ = sink;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200186 }
187
Niels Möllerd5696fb2018-11-28 15:34:37 +0100188 void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {
189 rtc::CritScope lock(&sink_lock_);
190 if (sink) {
191 RTC_CHECK(video_sink_ == nullptr);
192 }
193 video_sink_ = sink;
194 }
Niels Möller2e47f7c2018-10-16 10:41:42 +0200195
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700196 void SetMediaTransportStateCallback(
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800197 MediaTransportStateCallback* callback) override {
198 rtc::CritScope lock(&sink_lock_);
199 state_callback_ = callback;
200 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
201 RTC_DCHECK_RUN_ON(thread_);
202 OnStateChanged();
203 });
204 }
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700205
206 RTCError SendData(int channel_id,
207 const SendDataParams& params,
208 const rtc::CopyOnWriteBuffer& buffer) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700209 invoker_.AsyncInvoke<void>(
210 RTC_FROM_HERE, thread_, [this, channel_id, params, buffer] {
211 other_->OnData(channel_id, params.type, buffer);
212 });
213 return RTCError::OK();
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700214 }
215
216 RTCError CloseChannel(int channel_id) override {
Bjorn Mellem273d0292018-11-01 16:42:44 -0700217 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
218 other_->OnRemoteCloseChannel(channel_id);
219 rtc::CritScope lock(&sink_lock_);
220 if (data_sink_) {
221 data_sink_->OnChannelClosed(channel_id);
222 }
223 });
224 return RTCError::OK();
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700225 }
226
Bjorn Mellem273d0292018-11-01 16:42:44 -0700227 void SetDataSink(DataChannelSink* sink) override {
228 rtc::CritScope lock(&sink_lock_);
229 data_sink_ = sink;
230 }
231
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800232 void SetState(MediaTransportState state) {
233 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
234 RTC_DCHECK_RUN_ON(thread_);
235 state_ = state;
236 OnStateChanged();
237 });
238 }
239
Bjorn Mellem273d0292018-11-01 16:42:44 -0700240 void FlushAsyncInvokes() { invoker_.Flush(thread_); }
Bjorn Mellemeb2c6412018-10-31 15:25:32 -0700241
Niels Möllerc68d2822018-11-20 14:52:05 +0100242 Stats GetStats() {
243 rtc::CritScope lock(&stats_lock_);
244 return stats_;
245 }
246
Niels Möller2e47f7c2018-10-16 10:41:42 +0200247 private:
248 void OnData(uint64_t channel_id, MediaTransportEncodedAudioFrame frame) {
Niels Möllerc68d2822018-11-20 14:52:05 +0100249 {
250 rtc::CritScope lock(&sink_lock_);
Niels Möllerd5696fb2018-11-28 15:34:37 +0100251 if (audio_sink_) {
252 audio_sink_->OnData(channel_id, frame);
Niels Möllerc68d2822018-11-20 14:52:05 +0100253 }
254 }
255 {
256 rtc::CritScope lock(&stats_lock_);
257 ++stats_.received_audio_frames;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200258 }
259 }
260
Niels Möllerd5696fb2018-11-28 15:34:37 +0100261 void OnData(uint64_t channel_id, MediaTransportEncodedVideoFrame frame) {
262 {
263 rtc::CritScope lock(&sink_lock_);
264 if (video_sink_) {
265 video_sink_->OnData(channel_id, frame);
266 }
267 }
268 {
269 rtc::CritScope lock(&stats_lock_);
270 ++stats_.received_video_frames;
271 }
272 }
273
Bjorn Mellem273d0292018-11-01 16:42:44 -0700274 void OnData(int channel_id,
275 DataMessageType type,
276 const rtc::CopyOnWriteBuffer& buffer) {
277 rtc::CritScope lock(&sink_lock_);
278 if (data_sink_) {
279 data_sink_->OnDataReceived(channel_id, type, buffer);
280 }
281 }
282
283 void OnRemoteCloseChannel(int channel_id) {
284 rtc::CritScope lock(&sink_lock_);
285 if (data_sink_) {
286 data_sink_->OnChannelClosing(channel_id);
287 data_sink_->OnChannelClosed(channel_id);
288 }
289 }
290
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800291 void OnStateChanged() RTC_RUN_ON(thread_) {
292 rtc::CritScope lock(&sink_lock_);
293 if (state_callback_) {
294 state_callback_->OnStateChanged(state_);
295 }
296 }
297
Bjorn Mellem273d0292018-11-01 16:42:44 -0700298 rtc::Thread* const thread_;
299 rtc::CriticalSection sink_lock_;
Niels Möllerc68d2822018-11-20 14:52:05 +0100300 rtc::CriticalSection stats_lock_;
Bjorn Mellem273d0292018-11-01 16:42:44 -0700301
Niels Möllerd5696fb2018-11-28 15:34:37 +0100302 MediaTransportAudioSinkInterface* audio_sink_ RTC_GUARDED_BY(sink_lock_) =
303 nullptr;
304 MediaTransportVideoSinkInterface* video_sink_ RTC_GUARDED_BY(sink_lock_) =
Bjorn Mellem273d0292018-11-01 16:42:44 -0700305 nullptr;
306 DataChannelSink* data_sink_ RTC_GUARDED_BY(sink_lock_) = nullptr;
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800307 MediaTransportStateCallback* state_callback_ RTC_GUARDED_BY(sink_lock_) =
308 nullptr;
309
310 MediaTransportState state_ RTC_GUARDED_BY(thread_) =
311 MediaTransportState::kPending;
312
Bjorn Mellem273d0292018-11-01 16:42:44 -0700313 LoopbackMediaTransport* const other_;
314
Niels Möllerc68d2822018-11-20 14:52:05 +0100315 Stats stats_ RTC_GUARDED_BY(stats_lock_);
316
Bjorn Mellem273d0292018-11-01 16:42:44 -0700317 rtc::AsyncInvoker invoker_;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200318 };
319
Bjorn Mellem273d0292018-11-01 16:42:44 -0700320 LoopbackMediaTransport first_;
321 LoopbackMediaTransport second_;
Niels Möller2e47f7c2018-10-16 10:41:42 +0200322};
323
324} // namespace webrtc
325
326#endif // API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_