blob: 8e510e67b9141d7495f80fa7228a636f3a141474 [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öller663844d2019-02-14 16:15:54 +0100108 encoded_image.Allocate(sizeof(encoded_data));
109 memcpy(encoded_image.data(), encoded_data, sizeof(encoded_data));
Niels Möller77536a22019-01-15 08:50:01 +0100110 encoded_image.set_size(sizeof(encoded_data));
Niels Möllerd5696fb2018-11-28 15:34:37 +0100111
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200112 EXPECT_CALL(sink, OnData(1, ::testing::Property(
Niels Möllerd5696fb2018-11-28 15:34:37 +0100113 &MediaTransportEncodedVideoFrame::frame_id,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200114 ::testing::Eq(10))))
115 .WillOnce(::testing::Invoke(
Niels Möllerd5696fb2018-11-28 15:34:37 +0100116 [&encoded_image](int frame_id,
117 const MediaTransportEncodedVideoFrame& frame) {
Niels Möller77536a22019-01-15 08:50:01 +0100118 EXPECT_NE(frame.encoded_image().data(), encoded_image.data());
119 EXPECT_EQ(frame.encoded_image().size(), encoded_image.size());
120 EXPECT_EQ(0,
121 memcmp(frame.encoded_image().data(), encoded_image.data(),
122 std::min(frame.encoded_image().size(),
123 encoded_image.size())));
Niels Möllerd5696fb2018-11-28 15:34:37 +0100124 }));
125
126 transport_pair.second()->SetReceiveVideoSink(&sink);
127 transport_pair.first()->SendVideoFrame(1,
128 CreateVideoFrame(10, encoded_image));
129
130 transport_pair.FlushAsyncInvokes();
131 transport_pair.second()->SetReceiveVideoSink(nullptr);
132}
133
Niels Möller1c7f5f62018-12-10 11:06:02 +0100134TEST(LoopbackMediaTransport, VideoKeyFrameRequestDeliveredToCallback) {
135 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
136 thread->Start();
137 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200138 ::testing::StrictMock<MockMediaTransportKeyFrameRequestCallback> callback1;
139 ::testing::StrictMock<MockMediaTransportKeyFrameRequestCallback> callback2;
Niels Möller1c7f5f62018-12-10 11:06:02 +0100140 const uint64_t kFirstChannelId = 1111;
141 const uint64_t kSecondChannelId = 2222;
142
143 EXPECT_CALL(callback1, OnKeyFrameRequested(kSecondChannelId));
144 EXPECT_CALL(callback2, OnKeyFrameRequested(kFirstChannelId));
145 transport_pair.first()->SetKeyFrameRequestCallback(&callback1);
146 transport_pair.second()->SetKeyFrameRequestCallback(&callback2);
147
148 transport_pair.first()->RequestKeyFrame(kFirstChannelId);
149 transport_pair.second()->RequestKeyFrame(kSecondChannelId);
150
151 transport_pair.FlushAsyncInvokes();
152}
153
Bjorn Mellem273d0292018-11-01 16:42:44 -0700154TEST(LoopbackMediaTransport, DataDeliveredToSink) {
155 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
156 thread->Start();
157 MediaTransportPair transport_pair(thread.get());
158
159 MockDataChannelSink sink;
160 transport_pair.first()->SetDataSink(&sink);
161
162 const int channel_id = 1;
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200163 EXPECT_CALL(
164 sink, OnDataReceived(
165 channel_id, DataMessageType::kText,
166 ::testing::Property<rtc::CopyOnWriteBuffer, const char*>(
167 &rtc::CopyOnWriteBuffer::cdata, ::testing::StrEq("foo"))));
Bjorn Mellem273d0292018-11-01 16:42:44 -0700168
169 SendDataParams params;
170 params.type = DataMessageType::kText;
171 rtc::CopyOnWriteBuffer buffer("foo");
172 transport_pair.second()->SendData(channel_id, params, buffer);
173
174 transport_pair.FlushAsyncInvokes();
175 transport_pair.first()->SetDataSink(nullptr);
176}
177
178TEST(LoopbackMediaTransport, CloseDeliveredToSink) {
179 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
180 thread->Start();
181 MediaTransportPair transport_pair(thread.get());
182
183 MockDataChannelSink first_sink;
184 transport_pair.first()->SetDataSink(&first_sink);
185
186 MockDataChannelSink second_sink;
187 transport_pair.second()->SetDataSink(&second_sink);
188
189 const int channel_id = 1;
190 {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200191 ::testing::InSequence s;
Bjorn Mellem273d0292018-11-01 16:42:44 -0700192 EXPECT_CALL(second_sink, OnChannelClosing(channel_id));
193 EXPECT_CALL(second_sink, OnChannelClosed(channel_id));
194 EXPECT_CALL(first_sink, OnChannelClosed(channel_id));
195 }
196
197 transport_pair.first()->CloseChannel(channel_id);
198
199 transport_pair.FlushAsyncInvokes();
200 transport_pair.first()->SetDataSink(nullptr);
201 transport_pair.second()->SetDataSink(nullptr);
202}
203
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800204TEST(LoopbackMediaTransport, InitialStateDeliveredWhenCallbackSet) {
205 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
206 thread->Start();
207 MediaTransportPair transport_pair(thread.get());
208
209 MockStateCallback state_callback;
210
211 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
212 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
213 transport_pair.FlushAsyncInvokes();
214}
215
216TEST(LoopbackMediaTransport, ChangedStateDeliveredWhenCallbackSet) {
217 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
218 thread->Start();
219 MediaTransportPair transport_pair(thread.get());
220
221 transport_pair.SetState(MediaTransportState::kWritable);
222 transport_pair.FlushAsyncInvokes();
223
224 MockStateCallback state_callback;
225
226 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
227 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
228 transport_pair.FlushAsyncInvokes();
229}
230
231TEST(LoopbackMediaTransport, StateChangeDeliveredToCallback) {
232 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
233 thread->Start();
234 MediaTransportPair transport_pair(thread.get());
235
236 MockStateCallback state_callback;
237
238 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
239 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
240 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
241 transport_pair.SetState(MediaTransportState::kWritable);
242 transport_pair.FlushAsyncInvokes();
243}
244
Niels Möller2e47f7c2018-10-16 10:41:42 +0200245} // namespace webrtc