blob: 8fbaea53d2fcf990df02fc8731cd7d83a773f819 [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"
14
15namespace webrtc {
16
17namespace {
18
19// Wrapper used to hand out unique_ptrs to loopback media transports without
20// ownership changes.
21class WrapperMediaTransport : public MediaTransportInterface {
22 public:
23 explicit WrapperMediaTransport(MediaTransportInterface* wrapped)
24 : wrapped_(wrapped) {}
25
26 RTCError SendAudioFrame(uint64_t channel_id,
27 MediaTransportEncodedAudioFrame frame) override {
28 return wrapped_->SendAudioFrame(channel_id, std::move(frame));
29 }
30
31 RTCError SendVideoFrame(
32 uint64_t channel_id,
33 const MediaTransportEncodedVideoFrame& frame) override {
34 return wrapped_->SendVideoFrame(channel_id, frame);
35 }
36
Niels Möller1c7f5f62018-12-10 11:06:02 +010037 void SetKeyFrameRequestCallback(
38 MediaTransportKeyFrameRequestCallback* callback) override {
39 wrapped_->SetKeyFrameRequestCallback(callback);
40 }
41
Niels Möllere0446cb2018-11-30 09:35:52 +010042 RTCError RequestKeyFrame(uint64_t channel_id) override {
43 return wrapped_->RequestKeyFrame(channel_id);
44 }
45
46 void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {
47 wrapped_->SetReceiveAudioSink(sink);
48 }
49
50 void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {
51 wrapped_->SetReceiveVideoSink(sink);
52 }
53
54 void SetMediaTransportStateCallback(
55 MediaTransportStateCallback* callback) override {
56 wrapped_->SetMediaTransportStateCallback(callback);
57 }
58
59 RTCError SendData(int channel_id,
60 const SendDataParams& params,
61 const rtc::CopyOnWriteBuffer& buffer) override {
62 return wrapped_->SendData(channel_id, params, buffer);
63 }
64
65 RTCError CloseChannel(int channel_id) override {
66 return wrapped_->CloseChannel(channel_id);
67 }
68
69 void SetDataSink(DataChannelSink* sink) override {
70 wrapped_->SetDataSink(sink);
71 }
72
73 private:
74 MediaTransportInterface* wrapped_;
75};
76
77} // namespace
78
79WrapperMediaTransportFactory::WrapperMediaTransportFactory(
80 MediaTransportInterface* wrapped)
81 : wrapped_(wrapped) {}
82
83RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
84WrapperMediaTransportFactory::CreateMediaTransport(
85 rtc::PacketTransportInternal* packet_transport,
86 rtc::Thread* network_thread,
87 const MediaTransportSettings& settings) {
88 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
89}
90
91MediaTransportPair::LoopbackMediaTransport::LoopbackMediaTransport(
92 rtc::Thread* thread,
93 LoopbackMediaTransport* other)
94 : thread_(thread), other_(other) {}
95
96MediaTransportPair::LoopbackMediaTransport::~LoopbackMediaTransport() {
97 rtc::CritScope lock(&sink_lock_);
98 RTC_CHECK(audio_sink_ == nullptr);
99 RTC_CHECK(video_sink_ == nullptr);
100 RTC_CHECK(data_sink_ == nullptr);
101}
102
103RTCError MediaTransportPair::LoopbackMediaTransport::SendAudioFrame(
104 uint64_t channel_id,
105 MediaTransportEncodedAudioFrame frame) {
106 {
107 rtc::CritScope lock(&stats_lock_);
108 ++stats_.sent_audio_frames;
109 }
110 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id, frame] {
111 other_->OnData(channel_id, std::move(frame));
112 });
113 return RTCError::OK();
114}
115
116RTCError MediaTransportPair::LoopbackMediaTransport::SendVideoFrame(
117 uint64_t channel_id,
118 const MediaTransportEncodedVideoFrame& frame) {
119 {
120 rtc::CritScope lock(&stats_lock_);
121 ++stats_.sent_video_frames;
122 }
123 // Ensure that we own the referenced data.
124 MediaTransportEncodedVideoFrame frame_copy = frame;
125 frame_copy.Retain();
126 invoker_.AsyncInvoke<void>(
127 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy] {
128 other_->OnData(channel_id, std::move(frame_copy));
129 });
130 return RTCError::OK();
131}
132
Niels Möller1c7f5f62018-12-10 11:06:02 +0100133void MediaTransportPair::LoopbackMediaTransport::SetKeyFrameRequestCallback(
134 MediaTransportKeyFrameRequestCallback* callback) {
135 rtc::CritScope lock(&sink_lock_);
136 if (callback) {
137 RTC_CHECK(key_frame_callback_ == nullptr);
138 }
139 key_frame_callback_ = callback;
140}
141
Niels Möllere0446cb2018-11-30 09:35:52 +0100142RTCError MediaTransportPair::LoopbackMediaTransport::RequestKeyFrame(
143 uint64_t channel_id) {
Niels Möller1c7f5f62018-12-10 11:06:02 +0100144 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
145 other_->OnKeyFrameRequested(channel_id);
146 });
Niels Möllere0446cb2018-11-30 09:35:52 +0100147 return RTCError::OK();
148}
149
150void MediaTransportPair::LoopbackMediaTransport::SetReceiveAudioSink(
151 MediaTransportAudioSinkInterface* sink) {
152 rtc::CritScope lock(&sink_lock_);
153 if (sink) {
154 RTC_CHECK(audio_sink_ == nullptr);
155 }
156 audio_sink_ = sink;
157}
158
159void MediaTransportPair::LoopbackMediaTransport::SetReceiveVideoSink(
160 MediaTransportVideoSinkInterface* sink) {
161 rtc::CritScope lock(&sink_lock_);
162 if (sink) {
163 RTC_CHECK(video_sink_ == nullptr);
164 }
165 video_sink_ = sink;
166}
167
168void MediaTransportPair::LoopbackMediaTransport::SetMediaTransportStateCallback(
169 MediaTransportStateCallback* callback) {
170 rtc::CritScope lock(&sink_lock_);
171 state_callback_ = callback;
172 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
173 RTC_DCHECK_RUN_ON(thread_);
174 OnStateChanged();
175 });
176}
177
178RTCError MediaTransportPair::LoopbackMediaTransport::SendData(
179 int channel_id,
180 const SendDataParams& params,
181 const rtc::CopyOnWriteBuffer& buffer) {
182 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
183 [this, channel_id, params, buffer] {
184 other_->OnData(channel_id, params.type, buffer);
185 });
186 return RTCError::OK();
187}
188
189RTCError MediaTransportPair::LoopbackMediaTransport::CloseChannel(
190 int channel_id) {
191 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
192 other_->OnRemoteCloseChannel(channel_id);
193 rtc::CritScope lock(&sink_lock_);
194 if (data_sink_) {
195 data_sink_->OnChannelClosed(channel_id);
196 }
197 });
198 return RTCError::OK();
199}
200
201void MediaTransportPair::LoopbackMediaTransport::SetDataSink(
202 DataChannelSink* sink) {
203 rtc::CritScope lock(&sink_lock_);
204 data_sink_ = sink;
205}
206void MediaTransportPair::LoopbackMediaTransport::SetState(
207 MediaTransportState state) {
208 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
209 RTC_DCHECK_RUN_ON(thread_);
210 state_ = state;
211 OnStateChanged();
212 });
213}
214
215void MediaTransportPair::LoopbackMediaTransport::FlushAsyncInvokes() {
216 invoker_.Flush(thread_);
217}
218
219MediaTransportPair::Stats
220MediaTransportPair::LoopbackMediaTransport::GetStats() {
221 rtc::CritScope lock(&stats_lock_);
222 return stats_;
223}
224
225void MediaTransportPair::LoopbackMediaTransport::OnData(
226 uint64_t channel_id,
227 MediaTransportEncodedAudioFrame frame) {
228 {
229 rtc::CritScope lock(&sink_lock_);
230 if (audio_sink_) {
231 audio_sink_->OnData(channel_id, frame);
232 }
233 }
234 {
235 rtc::CritScope lock(&stats_lock_);
236 ++stats_.received_audio_frames;
237 }
238}
239
240void MediaTransportPair::LoopbackMediaTransport::OnData(
241 uint64_t channel_id,
242 MediaTransportEncodedVideoFrame frame) {
243 {
244 rtc::CritScope lock(&sink_lock_);
245 if (video_sink_) {
246 video_sink_->OnData(channel_id, frame);
247 }
248 }
249 {
250 rtc::CritScope lock(&stats_lock_);
251 ++stats_.received_video_frames;
252 }
253}
254
255void MediaTransportPair::LoopbackMediaTransport::OnData(
256 int channel_id,
257 DataMessageType type,
258 const rtc::CopyOnWriteBuffer& buffer) {
259 rtc::CritScope lock(&sink_lock_);
260 if (data_sink_) {
261 data_sink_->OnDataReceived(channel_id, type, buffer);
262 }
263}
264
Niels Möller1c7f5f62018-12-10 11:06:02 +0100265void MediaTransportPair::LoopbackMediaTransport::OnKeyFrameRequested(
266 int channel_id) {
267 rtc::CritScope lock(&sink_lock_);
268 if (key_frame_callback_) {
269 key_frame_callback_->OnKeyFrameRequested(channel_id);
270 }
271}
272
Niels Möllere0446cb2018-11-30 09:35:52 +0100273void MediaTransportPair::LoopbackMediaTransport::OnRemoteCloseChannel(
274 int channel_id) {
275 rtc::CritScope lock(&sink_lock_);
276 if (data_sink_) {
277 data_sink_->OnChannelClosing(channel_id);
278 data_sink_->OnChannelClosed(channel_id);
279 }
280}
281
282void MediaTransportPair::LoopbackMediaTransport::OnStateChanged() {
283 rtc::CritScope lock(&sink_lock_);
284 if (state_callback_) {
285 state_callback_->OnStateChanged(state_);
286 }
287}
288} // namespace webrtc