blob: 609481367b8de85a7770b6811ec495603dadbe44 [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
37 RTCError RequestKeyFrame(uint64_t channel_id) override {
38 return wrapped_->RequestKeyFrame(channel_id);
39 }
40
41 void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {
42 wrapped_->SetReceiveAudioSink(sink);
43 }
44
45 void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {
46 wrapped_->SetReceiveVideoSink(sink);
47 }
48
49 void SetMediaTransportStateCallback(
50 MediaTransportStateCallback* callback) override {
51 wrapped_->SetMediaTransportStateCallback(callback);
52 }
53
54 RTCError SendData(int channel_id,
55 const SendDataParams& params,
56 const rtc::CopyOnWriteBuffer& buffer) override {
57 return wrapped_->SendData(channel_id, params, buffer);
58 }
59
60 RTCError CloseChannel(int channel_id) override {
61 return wrapped_->CloseChannel(channel_id);
62 }
63
64 void SetDataSink(DataChannelSink* sink) override {
65 wrapped_->SetDataSink(sink);
66 }
67
68 private:
69 MediaTransportInterface* wrapped_;
70};
71
72} // namespace
73
74WrapperMediaTransportFactory::WrapperMediaTransportFactory(
75 MediaTransportInterface* wrapped)
76 : wrapped_(wrapped) {}
77
78RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
79WrapperMediaTransportFactory::CreateMediaTransport(
80 rtc::PacketTransportInternal* packet_transport,
81 rtc::Thread* network_thread,
82 const MediaTransportSettings& settings) {
83 return {absl::make_unique<WrapperMediaTransport>(wrapped_)};
84}
85
86MediaTransportPair::LoopbackMediaTransport::LoopbackMediaTransport(
87 rtc::Thread* thread,
88 LoopbackMediaTransport* other)
89 : thread_(thread), other_(other) {}
90
91MediaTransportPair::LoopbackMediaTransport::~LoopbackMediaTransport() {
92 rtc::CritScope lock(&sink_lock_);
93 RTC_CHECK(audio_sink_ == nullptr);
94 RTC_CHECK(video_sink_ == nullptr);
95 RTC_CHECK(data_sink_ == nullptr);
96}
97
98RTCError MediaTransportPair::LoopbackMediaTransport::SendAudioFrame(
99 uint64_t channel_id,
100 MediaTransportEncodedAudioFrame frame) {
101 {
102 rtc::CritScope lock(&stats_lock_);
103 ++stats_.sent_audio_frames;
104 }
105 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id, frame] {
106 other_->OnData(channel_id, std::move(frame));
107 });
108 return RTCError::OK();
109}
110
111RTCError MediaTransportPair::LoopbackMediaTransport::SendVideoFrame(
112 uint64_t channel_id,
113 const MediaTransportEncodedVideoFrame& frame) {
114 {
115 rtc::CritScope lock(&stats_lock_);
116 ++stats_.sent_video_frames;
117 }
118 // Ensure that we own the referenced data.
119 MediaTransportEncodedVideoFrame frame_copy = frame;
120 frame_copy.Retain();
121 invoker_.AsyncInvoke<void>(
122 RTC_FROM_HERE, thread_, [this, channel_id, frame_copy] {
123 other_->OnData(channel_id, std::move(frame_copy));
124 });
125 return RTCError::OK();
126}
127
128RTCError MediaTransportPair::LoopbackMediaTransport::RequestKeyFrame(
129 uint64_t channel_id) {
130 return RTCError::OK();
131}
132
133void MediaTransportPair::LoopbackMediaTransport::SetReceiveAudioSink(
134 MediaTransportAudioSinkInterface* sink) {
135 rtc::CritScope lock(&sink_lock_);
136 if (sink) {
137 RTC_CHECK(audio_sink_ == nullptr);
138 }
139 audio_sink_ = sink;
140}
141
142void MediaTransportPair::LoopbackMediaTransport::SetReceiveVideoSink(
143 MediaTransportVideoSinkInterface* sink) {
144 rtc::CritScope lock(&sink_lock_);
145 if (sink) {
146 RTC_CHECK(video_sink_ == nullptr);
147 }
148 video_sink_ = sink;
149}
150
151void MediaTransportPair::LoopbackMediaTransport::SetMediaTransportStateCallback(
152 MediaTransportStateCallback* callback) {
153 rtc::CritScope lock(&sink_lock_);
154 state_callback_ = callback;
155 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this] {
156 RTC_DCHECK_RUN_ON(thread_);
157 OnStateChanged();
158 });
159}
160
161RTCError MediaTransportPair::LoopbackMediaTransport::SendData(
162 int channel_id,
163 const SendDataParams& params,
164 const rtc::CopyOnWriteBuffer& buffer) {
165 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
166 [this, channel_id, params, buffer] {
167 other_->OnData(channel_id, params.type, buffer);
168 });
169 return RTCError::OK();
170}
171
172RTCError MediaTransportPair::LoopbackMediaTransport::CloseChannel(
173 int channel_id) {
174 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
175 other_->OnRemoteCloseChannel(channel_id);
176 rtc::CritScope lock(&sink_lock_);
177 if (data_sink_) {
178 data_sink_->OnChannelClosed(channel_id);
179 }
180 });
181 return RTCError::OK();
182}
183
184void MediaTransportPair::LoopbackMediaTransport::SetDataSink(
185 DataChannelSink* sink) {
186 rtc::CritScope lock(&sink_lock_);
187 data_sink_ = sink;
188}
189void MediaTransportPair::LoopbackMediaTransport::SetState(
190 MediaTransportState state) {
191 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
192 RTC_DCHECK_RUN_ON(thread_);
193 state_ = state;
194 OnStateChanged();
195 });
196}
197
198void MediaTransportPair::LoopbackMediaTransport::FlushAsyncInvokes() {
199 invoker_.Flush(thread_);
200}
201
202MediaTransportPair::Stats
203MediaTransportPair::LoopbackMediaTransport::GetStats() {
204 rtc::CritScope lock(&stats_lock_);
205 return stats_;
206}
207
208void MediaTransportPair::LoopbackMediaTransport::OnData(
209 uint64_t channel_id,
210 MediaTransportEncodedAudioFrame frame) {
211 {
212 rtc::CritScope lock(&sink_lock_);
213 if (audio_sink_) {
214 audio_sink_->OnData(channel_id, frame);
215 }
216 }
217 {
218 rtc::CritScope lock(&stats_lock_);
219 ++stats_.received_audio_frames;
220 }
221}
222
223void MediaTransportPair::LoopbackMediaTransport::OnData(
224 uint64_t channel_id,
225 MediaTransportEncodedVideoFrame frame) {
226 {
227 rtc::CritScope lock(&sink_lock_);
228 if (video_sink_) {
229 video_sink_->OnData(channel_id, frame);
230 }
231 }
232 {
233 rtc::CritScope lock(&stats_lock_);
234 ++stats_.received_video_frames;
235 }
236}
237
238void MediaTransportPair::LoopbackMediaTransport::OnData(
239 int channel_id,
240 DataMessageType type,
241 const rtc::CopyOnWriteBuffer& buffer) {
242 rtc::CritScope lock(&sink_lock_);
243 if (data_sink_) {
244 data_sink_->OnDataReceived(channel_id, type, buffer);
245 }
246}
247
248void MediaTransportPair::LoopbackMediaTransport::OnRemoteCloseChannel(
249 int channel_id) {
250 rtc::CritScope lock(&sink_lock_);
251 if (data_sink_) {
252 data_sink_->OnChannelClosing(channel_id);
253 data_sink_->OnChannelClosed(channel_id);
254 }
255}
256
257void MediaTransportPair::LoopbackMediaTransport::OnStateChanged() {
258 rtc::CritScope lock(&sink_lock_);
259 if (state_callback_) {
260 state_callback_->OnStateChanged(state_);
261 }
262}
263} // namespace webrtc