blob: afd544f9402f0d0c3276f62391fba8ab53529526 [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
Niels Möllerd5696fb2018-11-28 15:34:37 +010011#include <algorithm>
Bjorn Mellem273d0292018-11-01 16:42:44 -070012#include <memory>
Niels Möller2e47f7c2018-10-16 10:41:42 +020013#include <vector>
14
15#include "api/test/loopback_media_transport.h"
16#include "test/gmock.h"
17
18namespace webrtc {
19
20namespace {
21
22class MockMediaTransportAudioSinkInterface
23 : public MediaTransportAudioSinkInterface {
24 public:
25 MOCK_METHOD2(OnData, void(uint64_t, MediaTransportEncodedAudioFrame));
26};
27
Niels Möllerd5696fb2018-11-28 15:34:37 +010028class MockMediaTransportVideoSinkInterface
29 : public MediaTransportVideoSinkInterface {
30 public:
31 MOCK_METHOD2(OnData, void(uint64_t, MediaTransportEncodedVideoFrame));
Niels Möller1c7f5f62018-12-10 11:06:02 +010032};
33
34class MockMediaTransportKeyFrameRequestCallback
35 : public MediaTransportKeyFrameRequestCallback {
36 public:
Niels Möllerd5696fb2018-11-28 15:34:37 +010037 MOCK_METHOD1(OnKeyFrameRequested, void(uint64_t));
38};
39
Bjorn Mellem273d0292018-11-01 16:42:44 -070040class MockDataChannelSink : public DataChannelSink {
41 public:
42 MOCK_METHOD3(OnDataReceived,
43 void(int, DataMessageType, const rtc::CopyOnWriteBuffer&));
44 MOCK_METHOD1(OnChannelClosing, void(int));
45 MOCK_METHOD1(OnChannelClosed, void(int));
46};
47
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080048class MockStateCallback : public MediaTransportStateCallback {
49 public:
50 MOCK_METHOD1(OnStateChanged, void(MediaTransportState));
51};
52
Niels Möller2e47f7c2018-10-16 10:41:42 +020053// Test only uses the sequence number.
54MediaTransportEncodedAudioFrame CreateAudioFrame(int sequence_number) {
55 static constexpr int kSamplingRateHz = 48000;
56 static constexpr int kStartingSampleIndex = 0;
57 static constexpr int kSamplesPerChannel = 480;
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010058 static constexpr int kPayloadType = 17;
Niels Möller2e47f7c2018-10-16 10:41:42 +020059
60 return MediaTransportEncodedAudioFrame(
61 kSamplingRateHz, kStartingSampleIndex, kSamplesPerChannel,
62 sequence_number, MediaTransportEncodedAudioFrame::FrameType::kSpeech,
63 kPayloadType, std::vector<uint8_t>(kSamplesPerChannel));
64}
65
Niels Möllerd5696fb2018-11-28 15:34:37 +010066MediaTransportEncodedVideoFrame CreateVideoFrame(
67 int frame_id,
68 const webrtc::EncodedImage& encoded_image) {
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010069 static constexpr int kPayloadType = 18;
Niels Möllerd5696fb2018-11-28 15:34:37 +010070 return MediaTransportEncodedVideoFrame(frame_id, /*referenced_frame_ids=*/{},
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010071 kPayloadType, encoded_image);
Niels Möllerd5696fb2018-11-28 15:34:37 +010072}
73
Niels Möller2e47f7c2018-10-16 10:41:42 +020074} // namespace
75
76TEST(LoopbackMediaTransport, AudioWithNoSinkSilentlyIgnored) {
Bjorn Mellem273d0292018-11-01 16:42:44 -070077 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
78 thread->Start();
79 MediaTransportPair transport_pair(thread.get());
Niels Möller2e47f7c2018-10-16 10:41:42 +020080 transport_pair.first()->SendAudioFrame(1, CreateAudioFrame(0));
81 transport_pair.second()->SendAudioFrame(2, CreateAudioFrame(0));
Bjorn Mellem273d0292018-11-01 16:42:44 -070082 transport_pair.FlushAsyncInvokes();
Niels Möller2e47f7c2018-10-16 10:41:42 +020083}
84
85TEST(LoopbackMediaTransport, AudioDeliveredToSink) {
Bjorn Mellem273d0292018-11-01 16:42:44 -070086 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
87 thread->Start();
88 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +020089 ::testing::StrictMock<MockMediaTransportAudioSinkInterface> sink;
Niels Möller2e47f7c2018-10-16 10:41:42 +020090 EXPECT_CALL(sink,
Mirko Bonadei6a489f22019-04-09 15:11:12 +020091 OnData(1, ::testing::Property(
Niels Möller2e47f7c2018-10-16 10:41:42 +020092 &MediaTransportEncodedAudioFrame::sequence_number,
Mirko Bonadei6a489f22019-04-09 15:11:12 +020093 ::testing::Eq(10))));
Niels Möller2e47f7c2018-10-16 10:41:42 +020094 transport_pair.second()->SetReceiveAudioSink(&sink);
95 transport_pair.first()->SendAudioFrame(1, CreateAudioFrame(10));
96
Bjorn Mellem273d0292018-11-01 16:42:44 -070097 transport_pair.FlushAsyncInvokes();
Niels Möller2e47f7c2018-10-16 10:41:42 +020098 transport_pair.second()->SetReceiveAudioSink(nullptr);
99}
100
Niels Möllerd5696fb2018-11-28 15:34:37 +0100101TEST(LoopbackMediaTransport, VideoDeliveredToSink) {
102 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
103 thread->Start();
104 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200105 ::testing::StrictMock<MockMediaTransportVideoSinkInterface> sink;
Niels Möller663844d2019-02-14 16:15:54 +0100106 constexpr uint8_t encoded_data[] = {1, 2, 3};
Niels Möllerd5696fb2018-11-28 15:34:37 +0100107 EncodedImage encoded_image;
Niels Möller4d504c72019-06-18 15:56:56 +0200108 encoded_image.SetEncodedData(
109 EncodedImageBuffer::Create(encoded_data, sizeof(encoded_data)));
Niels Möllerd5696fb2018-11-28 15:34:37 +0100110
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200111 EXPECT_CALL(sink, OnData(1, ::testing::Property(
Niels Möllerd5696fb2018-11-28 15:34:37 +0100112 &MediaTransportEncodedVideoFrame::frame_id,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200113 ::testing::Eq(10))))
114 .WillOnce(::testing::Invoke(
Niels Möllerd5696fb2018-11-28 15:34:37 +0100115 [&encoded_image](int frame_id,
116 const MediaTransportEncodedVideoFrame& frame) {
Niels Möller4d504c72019-06-18 15:56:56 +0200117 EXPECT_EQ(frame.encoded_image().data(), encoded_image.data());
Niels Möller77536a22019-01-15 08:50:01 +0100118 EXPECT_EQ(frame.encoded_image().size(), encoded_image.size());
Niels Möllerd5696fb2018-11-28 15:34:37 +0100119 }));
120
121 transport_pair.second()->SetReceiveVideoSink(&sink);
122 transport_pair.first()->SendVideoFrame(1,
123 CreateVideoFrame(10, encoded_image));
124
125 transport_pair.FlushAsyncInvokes();
126 transport_pair.second()->SetReceiveVideoSink(nullptr);
127}
128
Niels Möller1c7f5f62018-12-10 11:06:02 +0100129TEST(LoopbackMediaTransport, VideoKeyFrameRequestDeliveredToCallback) {
130 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
131 thread->Start();
132 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200133 ::testing::StrictMock<MockMediaTransportKeyFrameRequestCallback> callback1;
134 ::testing::StrictMock<MockMediaTransportKeyFrameRequestCallback> callback2;
Niels Möller1c7f5f62018-12-10 11:06:02 +0100135 const uint64_t kFirstChannelId = 1111;
136 const uint64_t kSecondChannelId = 2222;
137
138 EXPECT_CALL(callback1, OnKeyFrameRequested(kSecondChannelId));
139 EXPECT_CALL(callback2, OnKeyFrameRequested(kFirstChannelId));
140 transport_pair.first()->SetKeyFrameRequestCallback(&callback1);
141 transport_pair.second()->SetKeyFrameRequestCallback(&callback2);
142
143 transport_pair.first()->RequestKeyFrame(kFirstChannelId);
144 transport_pair.second()->RequestKeyFrame(kSecondChannelId);
145
146 transport_pair.FlushAsyncInvokes();
147}
148
Bjorn Mellem273d0292018-11-01 16:42:44 -0700149TEST(LoopbackMediaTransport, DataDeliveredToSink) {
150 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
151 thread->Start();
152 MediaTransportPair transport_pair(thread.get());
153
154 MockDataChannelSink sink;
155 transport_pair.first()->SetDataSink(&sink);
156
157 const int channel_id = 1;
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200158 EXPECT_CALL(
159 sink, OnDataReceived(
160 channel_id, DataMessageType::kText,
161 ::testing::Property<rtc::CopyOnWriteBuffer, const char*>(
162 &rtc::CopyOnWriteBuffer::cdata, ::testing::StrEq("foo"))));
Bjorn Mellem273d0292018-11-01 16:42:44 -0700163
164 SendDataParams params;
165 params.type = DataMessageType::kText;
166 rtc::CopyOnWriteBuffer buffer("foo");
167 transport_pair.second()->SendData(channel_id, params, buffer);
168
169 transport_pair.FlushAsyncInvokes();
170 transport_pair.first()->SetDataSink(nullptr);
171}
172
173TEST(LoopbackMediaTransport, CloseDeliveredToSink) {
174 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
175 thread->Start();
176 MediaTransportPair transport_pair(thread.get());
177
178 MockDataChannelSink first_sink;
179 transport_pair.first()->SetDataSink(&first_sink);
180
181 MockDataChannelSink second_sink;
182 transport_pair.second()->SetDataSink(&second_sink);
183
184 const int channel_id = 1;
185 {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200186 ::testing::InSequence s;
Bjorn Mellem273d0292018-11-01 16:42:44 -0700187 EXPECT_CALL(second_sink, OnChannelClosing(channel_id));
188 EXPECT_CALL(second_sink, OnChannelClosed(channel_id));
189 EXPECT_CALL(first_sink, OnChannelClosed(channel_id));
190 }
191
192 transport_pair.first()->CloseChannel(channel_id);
193
194 transport_pair.FlushAsyncInvokes();
195 transport_pair.first()->SetDataSink(nullptr);
196 transport_pair.second()->SetDataSink(nullptr);
197}
198
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800199TEST(LoopbackMediaTransport, InitialStateDeliveredWhenCallbackSet) {
200 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
201 thread->Start();
202 MediaTransportPair transport_pair(thread.get());
203
204 MockStateCallback state_callback;
205
206 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
207 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
208 transport_pair.FlushAsyncInvokes();
209}
210
211TEST(LoopbackMediaTransport, ChangedStateDeliveredWhenCallbackSet) {
212 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
213 thread->Start();
214 MediaTransportPair transport_pair(thread.get());
215
216 transport_pair.SetState(MediaTransportState::kWritable);
217 transport_pair.FlushAsyncInvokes();
218
219 MockStateCallback state_callback;
220
221 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
222 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
223 transport_pair.FlushAsyncInvokes();
224}
225
226TEST(LoopbackMediaTransport, StateChangeDeliveredToCallback) {
227 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
228 thread->Start();
229 MediaTransportPair transport_pair(thread.get());
230
231 MockStateCallback state_callback;
232
233 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
234 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
235 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
236 transport_pair.SetState(MediaTransportState::kWritable);
237 transport_pair.FlushAsyncInvokes();
238}
239
Niels Möller2e47f7c2018-10-16 10:41:42 +0200240} // namespace webrtc