blob: d1351c593575238c77b7088af13c1e735eda8ddc [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "api/test/loopback_media_transport.h"
12
Niels Möllerd5696fb2018-11-28 15:34:37 +010013#include <algorithm>
Bjorn Mellem273d0292018-11-01 16:42:44 -070014#include <memory>
Niels Möller2e47f7c2018-10-16 10:41:42 +020015#include <vector>
16
Niels Möller2e47f7c2018-10-16 10:41:42 +020017#include "test/gmock.h"
18
19namespace webrtc {
20
21namespace {
22
23class MockMediaTransportAudioSinkInterface
24 : public MediaTransportAudioSinkInterface {
25 public:
26 MOCK_METHOD2(OnData, void(uint64_t, MediaTransportEncodedAudioFrame));
27};
28
Niels Möllerd5696fb2018-11-28 15:34:37 +010029class MockMediaTransportVideoSinkInterface
30 : public MediaTransportVideoSinkInterface {
31 public:
32 MOCK_METHOD2(OnData, void(uint64_t, MediaTransportEncodedVideoFrame));
Niels Möller1c7f5f62018-12-10 11:06:02 +010033};
34
35class MockMediaTransportKeyFrameRequestCallback
36 : public MediaTransportKeyFrameRequestCallback {
37 public:
Niels Möllerd5696fb2018-11-28 15:34:37 +010038 MOCK_METHOD1(OnKeyFrameRequested, void(uint64_t));
39};
40
Bjorn Mellem273d0292018-11-01 16:42:44 -070041class MockDataChannelSink : public DataChannelSink {
42 public:
43 MOCK_METHOD3(OnDataReceived,
44 void(int, DataMessageType, const rtc::CopyOnWriteBuffer&));
45 MOCK_METHOD1(OnChannelClosing, void(int));
46 MOCK_METHOD1(OnChannelClosed, void(int));
47};
48
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080049class MockStateCallback : public MediaTransportStateCallback {
50 public:
51 MOCK_METHOD1(OnStateChanged, void(MediaTransportState));
52};
53
Niels Möller2e47f7c2018-10-16 10:41:42 +020054// Test only uses the sequence number.
55MediaTransportEncodedAudioFrame CreateAudioFrame(int sequence_number) {
56 static constexpr int kSamplingRateHz = 48000;
57 static constexpr int kStartingSampleIndex = 0;
58 static constexpr int kSamplesPerChannel = 480;
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010059 static constexpr int kPayloadType = 17;
Niels Möller2e47f7c2018-10-16 10:41:42 +020060
61 return MediaTransportEncodedAudioFrame(
62 kSamplingRateHz, kStartingSampleIndex, kSamplesPerChannel,
63 sequence_number, MediaTransportEncodedAudioFrame::FrameType::kSpeech,
64 kPayloadType, std::vector<uint8_t>(kSamplesPerChannel));
65}
66
Niels Möllerd5696fb2018-11-28 15:34:37 +010067MediaTransportEncodedVideoFrame CreateVideoFrame(
68 int frame_id,
69 const webrtc::EncodedImage& encoded_image) {
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010070 static constexpr int kPayloadType = 18;
Niels Möllerd5696fb2018-11-28 15:34:37 +010071 return MediaTransportEncodedVideoFrame(frame_id, /*referenced_frame_ids=*/{},
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010072 kPayloadType, encoded_image);
Niels Möllerd5696fb2018-11-28 15:34:37 +010073}
74
Niels Möller2e47f7c2018-10-16 10:41:42 +020075} // namespace
76
77TEST(LoopbackMediaTransport, AudioWithNoSinkSilentlyIgnored) {
Bjorn Mellem273d0292018-11-01 16:42:44 -070078 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
79 thread->Start();
80 MediaTransportPair transport_pair(thread.get());
Niels Möller2e47f7c2018-10-16 10:41:42 +020081 transport_pair.first()->SendAudioFrame(1, CreateAudioFrame(0));
82 transport_pair.second()->SendAudioFrame(2, CreateAudioFrame(0));
Bjorn Mellem273d0292018-11-01 16:42:44 -070083 transport_pair.FlushAsyncInvokes();
Niels Möller2e47f7c2018-10-16 10:41:42 +020084}
85
86TEST(LoopbackMediaTransport, AudioDeliveredToSink) {
Bjorn Mellem273d0292018-11-01 16:42:44 -070087 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
88 thread->Start();
89 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +020090 ::testing::StrictMock<MockMediaTransportAudioSinkInterface> sink;
Niels Möller2e47f7c2018-10-16 10:41:42 +020091 EXPECT_CALL(sink,
Mirko Bonadei6a489f22019-04-09 15:11:12 +020092 OnData(1, ::testing::Property(
Niels Möller2e47f7c2018-10-16 10:41:42 +020093 &MediaTransportEncodedAudioFrame::sequence_number,
Mirko Bonadei6a489f22019-04-09 15:11:12 +020094 ::testing::Eq(10))));
Niels Möller2e47f7c2018-10-16 10:41:42 +020095 transport_pair.second()->SetReceiveAudioSink(&sink);
96 transport_pair.first()->SendAudioFrame(1, CreateAudioFrame(10));
97
Bjorn Mellem273d0292018-11-01 16:42:44 -070098 transport_pair.FlushAsyncInvokes();
Niels Möller2e47f7c2018-10-16 10:41:42 +020099 transport_pair.second()->SetReceiveAudioSink(nullptr);
100}
101
Niels Möllerd5696fb2018-11-28 15:34:37 +0100102TEST(LoopbackMediaTransport, VideoDeliveredToSink) {
103 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
104 thread->Start();
105 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200106 ::testing::StrictMock<MockMediaTransportVideoSinkInterface> sink;
Niels Möller663844d2019-02-14 16:15:54 +0100107 constexpr uint8_t encoded_data[] = {1, 2, 3};
Niels Möllerd5696fb2018-11-28 15:34:37 +0100108 EncodedImage encoded_image;
Niels Möller4d504c72019-06-18 15:56:56 +0200109 encoded_image.SetEncodedData(
110 EncodedImageBuffer::Create(encoded_data, 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öller4d504c72019-06-18 15:56:56 +0200118 EXPECT_EQ(frame.encoded_image().data(), encoded_image.data());
Niels Möller77536a22019-01-15 08:50:01 +0100119 EXPECT_EQ(frame.encoded_image().size(), encoded_image.size());
Niels Möllerd5696fb2018-11-28 15:34:37 +0100120 }));
121
122 transport_pair.second()->SetReceiveVideoSink(&sink);
123 transport_pair.first()->SendVideoFrame(1,
124 CreateVideoFrame(10, encoded_image));
125
126 transport_pair.FlushAsyncInvokes();
127 transport_pair.second()->SetReceiveVideoSink(nullptr);
128}
129
Niels Möller1c7f5f62018-12-10 11:06:02 +0100130TEST(LoopbackMediaTransport, VideoKeyFrameRequestDeliveredToCallback) {
131 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
132 thread->Start();
133 MediaTransportPair transport_pair(thread.get());
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200134 ::testing::StrictMock<MockMediaTransportKeyFrameRequestCallback> callback1;
135 ::testing::StrictMock<MockMediaTransportKeyFrameRequestCallback> callback2;
Niels Möller1c7f5f62018-12-10 11:06:02 +0100136 const uint64_t kFirstChannelId = 1111;
137 const uint64_t kSecondChannelId = 2222;
138
139 EXPECT_CALL(callback1, OnKeyFrameRequested(kSecondChannelId));
140 EXPECT_CALL(callback2, OnKeyFrameRequested(kFirstChannelId));
141 transport_pair.first()->SetKeyFrameRequestCallback(&callback1);
142 transport_pair.second()->SetKeyFrameRequestCallback(&callback2);
143
144 transport_pair.first()->RequestKeyFrame(kFirstChannelId);
145 transport_pair.second()->RequestKeyFrame(kSecondChannelId);
146
147 transport_pair.FlushAsyncInvokes();
148}
149
Bjorn Mellem273d0292018-11-01 16:42:44 -0700150TEST(LoopbackMediaTransport, DataDeliveredToSink) {
151 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
152 thread->Start();
153 MediaTransportPair transport_pair(thread.get());
154
155 MockDataChannelSink sink;
156 transport_pair.first()->SetDataSink(&sink);
157
158 const int channel_id = 1;
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200159 EXPECT_CALL(
160 sink, OnDataReceived(
161 channel_id, DataMessageType::kText,
162 ::testing::Property<rtc::CopyOnWriteBuffer, const char*>(
163 &rtc::CopyOnWriteBuffer::cdata, ::testing::StrEq("foo"))));
Bjorn Mellem273d0292018-11-01 16:42:44 -0700164
165 SendDataParams params;
166 params.type = DataMessageType::kText;
167 rtc::CopyOnWriteBuffer buffer("foo");
168 transport_pair.second()->SendData(channel_id, params, buffer);
169
170 transport_pair.FlushAsyncInvokes();
171 transport_pair.first()->SetDataSink(nullptr);
172}
173
174TEST(LoopbackMediaTransport, CloseDeliveredToSink) {
175 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
176 thread->Start();
177 MediaTransportPair transport_pair(thread.get());
178
179 MockDataChannelSink first_sink;
180 transport_pair.first()->SetDataSink(&first_sink);
181
182 MockDataChannelSink second_sink;
183 transport_pair.second()->SetDataSink(&second_sink);
184
185 const int channel_id = 1;
186 {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200187 ::testing::InSequence s;
Bjorn Mellem273d0292018-11-01 16:42:44 -0700188 EXPECT_CALL(second_sink, OnChannelClosing(channel_id));
189 EXPECT_CALL(second_sink, OnChannelClosed(channel_id));
190 EXPECT_CALL(first_sink, OnChannelClosed(channel_id));
191 }
192
193 transport_pair.first()->CloseChannel(channel_id);
194
195 transport_pair.FlushAsyncInvokes();
196 transport_pair.first()->SetDataSink(nullptr);
197 transport_pair.second()->SetDataSink(nullptr);
198}
199
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800200TEST(LoopbackMediaTransport, InitialStateDeliveredWhenCallbackSet) {
201 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
202 thread->Start();
203 MediaTransportPair transport_pair(thread.get());
204
205 MockStateCallback state_callback;
206
207 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
208 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
209 transport_pair.FlushAsyncInvokes();
210}
211
212TEST(LoopbackMediaTransport, ChangedStateDeliveredWhenCallbackSet) {
213 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
214 thread->Start();
215 MediaTransportPair transport_pair(thread.get());
216
217 transport_pair.SetState(MediaTransportState::kWritable);
218 transport_pair.FlushAsyncInvokes();
219
220 MockStateCallback state_callback;
221
222 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
223 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
224 transport_pair.FlushAsyncInvokes();
225}
226
227TEST(LoopbackMediaTransport, StateChangeDeliveredToCallback) {
228 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
229 thread->Start();
230 MediaTransportPair transport_pair(thread.get());
231
232 MockStateCallback state_callback;
233
234 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
235 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
236 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
237 transport_pair.SetState(MediaTransportState::kWritable);
238 transport_pair.FlushAsyncInvokes();
239}
240
Niels Möller2e47f7c2018-10-16 10:41:42 +0200241} // namespace webrtc