blob: a1b13ecffe89b65e9b99e99a49d8c20727dd0bb3 [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));
32 MOCK_METHOD1(OnKeyFrameRequested, void(uint64_t));
33};
34
Bjorn Mellem273d0292018-11-01 16:42:44 -070035class MockDataChannelSink : public DataChannelSink {
36 public:
37 MOCK_METHOD3(OnDataReceived,
38 void(int, DataMessageType, const rtc::CopyOnWriteBuffer&));
39 MOCK_METHOD1(OnChannelClosing, void(int));
40 MOCK_METHOD1(OnChannelClosed, void(int));
41};
42
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080043class MockStateCallback : public MediaTransportStateCallback {
44 public:
45 MOCK_METHOD1(OnStateChanged, void(MediaTransportState));
46};
47
Niels Möller2e47f7c2018-10-16 10:41:42 +020048// Test only uses the sequence number.
49MediaTransportEncodedAudioFrame CreateAudioFrame(int sequence_number) {
50 static constexpr int kSamplingRateHz = 48000;
51 static constexpr int kStartingSampleIndex = 0;
52 static constexpr int kSamplesPerChannel = 480;
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010053 static constexpr int kPayloadType = 17;
Niels Möller2e47f7c2018-10-16 10:41:42 +020054
55 return MediaTransportEncodedAudioFrame(
56 kSamplingRateHz, kStartingSampleIndex, kSamplesPerChannel,
57 sequence_number, MediaTransportEncodedAudioFrame::FrameType::kSpeech,
58 kPayloadType, std::vector<uint8_t>(kSamplesPerChannel));
59}
60
Niels Möllerd5696fb2018-11-28 15:34:37 +010061MediaTransportEncodedVideoFrame CreateVideoFrame(
62 int frame_id,
63 const webrtc::EncodedImage& encoded_image) {
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010064 static constexpr int kPayloadType = 18;
Niels Möllerd5696fb2018-11-28 15:34:37 +010065 return MediaTransportEncodedVideoFrame(frame_id, /*referenced_frame_ids=*/{},
Niels Möllerd8a1b7a2018-12-06 13:00:27 +010066 kPayloadType, encoded_image);
Niels Möllerd5696fb2018-11-28 15:34:37 +010067}
68
Niels Möller2e47f7c2018-10-16 10:41:42 +020069} // namespace
70
71TEST(LoopbackMediaTransport, AudioWithNoSinkSilentlyIgnored) {
Bjorn Mellem273d0292018-11-01 16:42:44 -070072 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
73 thread->Start();
74 MediaTransportPair transport_pair(thread.get());
Niels Möller2e47f7c2018-10-16 10:41:42 +020075 transport_pair.first()->SendAudioFrame(1, CreateAudioFrame(0));
76 transport_pair.second()->SendAudioFrame(2, CreateAudioFrame(0));
Bjorn Mellem273d0292018-11-01 16:42:44 -070077 transport_pair.FlushAsyncInvokes();
Niels Möller2e47f7c2018-10-16 10:41:42 +020078}
79
80TEST(LoopbackMediaTransport, AudioDeliveredToSink) {
Bjorn Mellem273d0292018-11-01 16:42:44 -070081 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
82 thread->Start();
83 MediaTransportPair transport_pair(thread.get());
Niels Möller2e47f7c2018-10-16 10:41:42 +020084 testing::StrictMock<MockMediaTransportAudioSinkInterface> sink;
85 EXPECT_CALL(sink,
86 OnData(1, testing::Property(
87 &MediaTransportEncodedAudioFrame::sequence_number,
88 testing::Eq(10))));
89 transport_pair.second()->SetReceiveAudioSink(&sink);
90 transport_pair.first()->SendAudioFrame(1, CreateAudioFrame(10));
91
Bjorn Mellem273d0292018-11-01 16:42:44 -070092 transport_pair.FlushAsyncInvokes();
Niels Möller2e47f7c2018-10-16 10:41:42 +020093 transport_pair.second()->SetReceiveAudioSink(nullptr);
94}
95
Niels Möllerd5696fb2018-11-28 15:34:37 +010096TEST(LoopbackMediaTransport, VideoDeliveredToSink) {
97 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
98 thread->Start();
99 MediaTransportPair transport_pair(thread.get());
100 testing::StrictMock<MockMediaTransportVideoSinkInterface> sink;
101 uint8_t encoded_data[] = {1, 2, 3};
102 EncodedImage encoded_image;
103 encoded_image._buffer = encoded_data;
104 encoded_image._length = sizeof(encoded_data);
105
106 EXPECT_CALL(sink, OnData(1, testing::Property(
107 &MediaTransportEncodedVideoFrame::frame_id,
108 testing::Eq(10))))
109 .WillOnce(testing::Invoke(
110 [&encoded_image](int frame_id,
111 const MediaTransportEncodedVideoFrame& frame) {
112 EXPECT_NE(frame.encoded_image()._buffer, encoded_image._buffer);
113 EXPECT_EQ(frame.encoded_image()._length, encoded_image._length);
114 EXPECT_EQ(
115 0, memcmp(frame.encoded_image()._buffer, encoded_image._buffer,
116 std::min(frame.encoded_image()._length,
117 encoded_image._length)));
118 }));
119
120 transport_pair.second()->SetReceiveVideoSink(&sink);
121 transport_pair.first()->SendVideoFrame(1,
122 CreateVideoFrame(10, encoded_image));
123
124 transport_pair.FlushAsyncInvokes();
125 transport_pair.second()->SetReceiveVideoSink(nullptr);
126}
127
Bjorn Mellem273d0292018-11-01 16:42:44 -0700128TEST(LoopbackMediaTransport, DataDeliveredToSink) {
129 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
130 thread->Start();
131 MediaTransportPair transport_pair(thread.get());
132
133 MockDataChannelSink sink;
134 transport_pair.first()->SetDataSink(&sink);
135
136 const int channel_id = 1;
137 EXPECT_CALL(sink,
138 OnDataReceived(
139 channel_id, DataMessageType::kText,
140 testing::Property<rtc::CopyOnWriteBuffer, const char*>(
141 &rtc::CopyOnWriteBuffer::cdata, testing::StrEq("foo"))));
142
143 SendDataParams params;
144 params.type = DataMessageType::kText;
145 rtc::CopyOnWriteBuffer buffer("foo");
146 transport_pair.second()->SendData(channel_id, params, buffer);
147
148 transport_pair.FlushAsyncInvokes();
149 transport_pair.first()->SetDataSink(nullptr);
150}
151
152TEST(LoopbackMediaTransport, CloseDeliveredToSink) {
153 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
154 thread->Start();
155 MediaTransportPair transport_pair(thread.get());
156
157 MockDataChannelSink first_sink;
158 transport_pair.first()->SetDataSink(&first_sink);
159
160 MockDataChannelSink second_sink;
161 transport_pair.second()->SetDataSink(&second_sink);
162
163 const int channel_id = 1;
164 {
165 testing::InSequence s;
166 EXPECT_CALL(second_sink, OnChannelClosing(channel_id));
167 EXPECT_CALL(second_sink, OnChannelClosed(channel_id));
168 EXPECT_CALL(first_sink, OnChannelClosed(channel_id));
169 }
170
171 transport_pair.first()->CloseChannel(channel_id);
172
173 transport_pair.FlushAsyncInvokes();
174 transport_pair.first()->SetDataSink(nullptr);
175 transport_pair.second()->SetDataSink(nullptr);
176}
177
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800178TEST(LoopbackMediaTransport, InitialStateDeliveredWhenCallbackSet) {
179 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
180 thread->Start();
181 MediaTransportPair transport_pair(thread.get());
182
183 MockStateCallback state_callback;
184
185 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
186 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
187 transport_pair.FlushAsyncInvokes();
188}
189
190TEST(LoopbackMediaTransport, ChangedStateDeliveredWhenCallbackSet) {
191 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
192 thread->Start();
193 MediaTransportPair transport_pair(thread.get());
194
195 transport_pair.SetState(MediaTransportState::kWritable);
196 transport_pair.FlushAsyncInvokes();
197
198 MockStateCallback state_callback;
199
200 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
201 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
202 transport_pair.FlushAsyncInvokes();
203}
204
205TEST(LoopbackMediaTransport, StateChangeDeliveredToCallback) {
206 std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
207 thread->Start();
208 MediaTransportPair transport_pair(thread.get());
209
210 MockStateCallback state_callback;
211
212 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
213 EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
214 transport_pair.first()->SetMediaTransportStateCallback(&state_callback);
215 transport_pair.SetState(MediaTransportState::kWritable);
216 transport_pair.FlushAsyncInvokes();
217}
218
Niels Möller2e47f7c2018-10-16 10:41:42 +0200219} // namespace webrtc