blob: 01a4f76ca766183ba12564515ae661009998b535 [file] [log] [blame]
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00009 */
henrike@webrtc.org28e20752013-07-10 00:45:36 +000010
kjellandera96e2d72016-02-04 23:52:28 -080011#ifndef WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ // NOLINT
12#define WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000013
kwiberg686a8ef2016-02-26 03:00:35 -080014#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000015#include <string>
16#include <vector>
17
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000018#include "webrtc/base/bytebuffer.h"
19#include "webrtc/base/gunit.h"
20#include "webrtc/base/timeutils.h"
Fredrik Solenberg709ed672015-09-15 12:26:33 +020021#include "webrtc/call.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/media/base/fakenetworkinterface.h"
23#include "webrtc/media/base/fakevideocapturer.h"
24#include "webrtc/media/base/fakevideorenderer.h"
25#include "webrtc/media/base/mediachannel.h"
26#include "webrtc/media/base/streamparams.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010027#include "webrtc/media/engine/fakewebrtccall.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029#define EXPECT_FRAME_WAIT(c, w, h, t) \
30 EXPECT_EQ_WAIT((c), renderer_.num_rendered_frames(), (t)); \
31 EXPECT_EQ((w), renderer_.width()); \
32 EXPECT_EQ((h), renderer_.height()); \
33 EXPECT_EQ(0, renderer_.errors()); \
34
35#define EXPECT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
36 EXPECT_EQ_WAIT((c), (r).num_rendered_frames(), (t)); \
37 EXPECT_EQ((w), (r).width()); \
38 EXPECT_EQ((h), (r).height()); \
39 EXPECT_EQ(0, (r).errors()); \
40
wu@webrtc.org9caf2762013-12-11 18:25:07 +000041#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
42 EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
43 (w) == (r).width() && \
44 (h) == (r).height(), (t)); \
Peter Boström0c4e06b2015-10-07 12:23:21 +020045 EXPECT_EQ(0, (r).errors());
wu@webrtc.org9caf2762013-12-11 18:25:07 +000046
Peter Boström0c4e06b2015-10-07 12:23:21 +020047static const uint32_t kTimeout = 5000U;
48static const uint32_t kDefaultReceiveSsrc = 0;
49static const uint32_t kSsrc = 1234u;
50static const uint32_t kRtxSsrc = 4321u;
51static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052
53inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) {
54 return a.width == w && a.height == h && a.framerate == fps;
55}
56
57inline bool IsEqualCodec(const cricket::VideoCodec& a,
58 const cricket::VideoCodec& b) {
59 return a.id == b.id && a.name == b.name &&
60 IsEqualRes(a, b.width, b.height, b.framerate);
61}
62
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000063namespace std {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
65 s << "{" << c.name << "(" << c.id << "), "
66 << c.width << "x" << c.height << "x" << c.framerate << "}";
67 return s;
68}
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000069} // namespace std
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070
71inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000072 return static_cast<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073 cricket::VideoFormat::FpsToInterval(codec.framerate) /
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000074 rtc::kNumNanosecsPerMillisec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075}
76
77// Fake video engine that makes it possible to test enabling and disabling
78// capturer (checking that the engine state is updated and that the capturer
79// is indeed capturing) without having to create a channel. It also makes it
80// possible to test that the media processors are indeed being called when
81// registered.
82template<class T>
83class VideoEngineOverride : public T {
84 public:
Fredrik Solenberg709ed672015-09-15 12:26:33 +020085 VideoEngineOverride() : T() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 }
87 virtual ~VideoEngineOverride() {
88 }
89 bool is_camera_on() const { return T::GetVideoCapturer()->IsRunning(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090
Peter Boström0c4e06b2015-10-07 12:23:21 +020091 void TriggerMediaFrame(uint32_t ssrc,
92 cricket::VideoFrame* frame,
93 bool* drop_frame) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 T::SignalMediaFrame(ssrc, frame, drop_frame);
95 }
96};
97
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098template<class E, class C>
99class VideoMediaChannelTest : public testing::Test,
100 public sigslot::has_slots<> {
101 protected:
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200102 VideoMediaChannelTest<E, C>()
103 : call_(webrtc::Call::Create(webrtc::Call::Config())) {}
104
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 virtual cricket::VideoCodec DefaultCodec() = 0;
106
107 virtual cricket::StreamParams DefaultSendStreamParams() {
108 return cricket::StreamParams::CreateLegacy(kSsrc);
109 }
110
111 virtual void SetUp() {
Fredrik Solenberg9a416bd2015-05-22 09:04:09 +0200112 engine_.Init();
nisse51542be2016-02-12 02:27:06 -0800113 channel_.reset(engine_.CreateChannel(call_.get(), cricket::MediaConfig(),
114 cricket::VideoOptions()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115 EXPECT_TRUE(channel_.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116 network_interface_.SetDestination(channel_.get());
117 channel_->SetInterface(&network_interface_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118 media_error_ = cricket::VideoMediaChannel::ERROR_NONE;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200119 cricket::VideoRecvParameters parameters;
120 parameters.codecs = engine_.codecs();
121 channel_->SetRecvParameters(parameters);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122 EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams()));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000123 video_capturer_.reset(CreateFakeVideoCapturer());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000124 cricket::VideoFormat format(640, 480,
125 cricket::VideoFormat::FpsToInterval(30),
126 cricket::FOURCC_I420);
127 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
128 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 }
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000130
131 virtual cricket::FakeVideoCapturer* CreateFakeVideoCapturer() {
132 return new cricket::FakeVideoCapturer();
133 }
134
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000135 // Utility method to setup an additional stream to send and receive video.
136 // Used to test send and recv between two streams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137 void SetUpSecondStream() {
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000138 SetUpSecondStreamWithNoRecv();
139 // Setup recv for second stream.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000140 EXPECT_TRUE(channel_->AddRecvStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000141 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000142 // Make the second renderer available for use by a new stream.
nisse08582ff2016-02-04 01:24:52 -0800143 EXPECT_TRUE(channel_->SetSink(kSsrc + 2, &renderer2_));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000144 }
145 // Setup an additional stream just to send video. Defer add recv stream.
146 // This is required if you want to test unsignalled recv of video rtp packets.
147 void SetUpSecondStreamWithNoRecv() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 // SetUp() already added kSsrc make sure duplicate SSRCs cant be added.
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000149 EXPECT_TRUE(channel_->AddRecvStream(
150 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800151 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152 EXPECT_FALSE(channel_->AddSendStream(
153 cricket::StreamParams::CreateLegacy(kSsrc)));
154 EXPECT_TRUE(channel_->AddSendStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000155 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000156 // We dont add recv for the second stream.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000157
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000158 // Setup the receive and renderer for second stream after send.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000159 video_capturer_2_.reset(CreateFakeVideoCapturer());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000160 cricket::VideoFormat format(640, 480,
161 cricket::VideoFormat::FpsToInterval(30),
162 cricket::FOURCC_I420);
163 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
164
165 EXPECT_TRUE(channel_->SetCapturer(kSsrc + 2, video_capturer_2_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000166 }
167 virtual void TearDown() {
168 channel_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000170 bool SetDefaultCodec() {
171 return SetOneCodec(DefaultCodec());
172 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000173
174 bool SetOneCodec(int pt, const char* name, int w, int h, int fr) {
175 return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0));
176 }
177 bool SetOneCodec(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000178 cricket::VideoFormat capture_format(codec.width, codec.height,
179 cricket::VideoFormat::FpsToInterval(codec.framerate),
180 cricket::FOURCC_I420);
181
182 if (video_capturer_) {
183 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format));
184 }
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000185 if (video_capturer_2_) {
186 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format));
187 }
188
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 bool sending = channel_->sending();
190 bool success = SetSend(false);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200191 if (success) {
192 cricket::VideoSendParameters parameters;
193 parameters.codecs.push_back(codec);
194 success = channel_->SetSendParameters(parameters);
195 }
196 if (success) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000197 success = SetSend(sending);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200198 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199 return success;
200 }
201 bool SetSend(bool send) {
202 return channel_->SetSend(send);
203 }
204 int DrainOutgoingPackets() {
205 int packets = 0;
206 do {
207 packets = NumRtpPackets();
208 // 100 ms should be long enough.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000209 rtc::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000210 } while (NumRtpPackets() > packets);
211 return NumRtpPackets();
212 }
213 bool SendFrame() {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000214 if (video_capturer_2_) {
215 video_capturer_2_->CaptureFrame();
216 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000217 return video_capturer_.get() &&
218 video_capturer_->CaptureFrame();
219 }
220 bool WaitAndSendFrame(int wait_ms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000221 bool ret = rtc::Thread::Current()->ProcessMessages(wait_ms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 ret &= SendFrame();
223 return ret;
224 }
225 // Sends frames and waits for the decoder to be fully initialized.
226 // Returns the number of frames that were sent.
227 int WaitForDecoder() {
228#if defined(HAVE_OPENMAX)
229 // Send enough frames for the OpenMAX decoder to continue processing, and
230 // return the number of frames sent.
231 // Send frames for a full kTimeout's worth of 15fps video.
232 int frame_count = 0;
233 while (frame_count < static_cast<int>(kTimeout) / 66) {
234 EXPECT_TRUE(WaitAndSendFrame(66));
235 ++frame_count;
236 }
237 return frame_count;
238#else
239 return 0;
240#endif
241 }
242 bool SendCustomVideoFrame(int w, int h) {
243 if (!video_capturer_.get()) return false;
244 return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420);
245 }
246 int NumRtpBytes() {
247 return network_interface_.NumRtpBytes();
248 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200249 int NumRtpBytes(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000250 return network_interface_.NumRtpBytes(ssrc);
251 }
252 int NumRtpPackets() {
253 return network_interface_.NumRtpPackets();
254 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200255 int NumRtpPackets(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 return network_interface_.NumRtpPackets(ssrc);
257 }
258 int NumSentSsrcs() {
259 return network_interface_.NumSentSsrcs();
260 }
jbaucheec21bd2016-03-20 06:15:43 -0700261 const rtc::CopyOnWriteBuffer* GetRtpPacket(int index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 return network_interface_.GetRtpPacket(index);
263 }
264 int NumRtcpPackets() {
265 return network_interface_.NumRtcpPackets();
266 }
jbaucheec21bd2016-03-20 06:15:43 -0700267 const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000268 return network_interface_.GetRtcpPacket(index);
269 }
jbaucheec21bd2016-03-20 06:15:43 -0700270 static int GetPayloadType(const rtc::CopyOnWriteBuffer* p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271 int pt = -1;
272 ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
273 return pt;
274 }
jbaucheec21bd2016-03-20 06:15:43 -0700275 static bool ParseRtpPacket(const rtc::CopyOnWriteBuffer* p,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200276 bool* x,
277 int* pt,
278 int* seqnum,
279 uint32_t* tstamp,
280 uint32_t* ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 std::string* payload) {
jbauchf1f87202016-03-30 06:43:37 -0700282 rtc::ByteBufferReader buf(p->data<char>(), p->size());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200283 uint8_t u08 = 0;
284 uint16_t u16 = 0;
285 uint32_t u32 = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286
287 // Read X and CC fields.
288 if (!buf.ReadUInt8(&u08)) return false;
289 bool extension = ((u08 & 0x10) != 0);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200290 uint8_t cc = (u08 & 0x0F);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000291 if (x) *x = extension;
292
293 // Read PT field.
294 if (!buf.ReadUInt8(&u08)) return false;
295 if (pt) *pt = (u08 & 0x7F);
296
297 // Read Sequence Number field.
298 if (!buf.ReadUInt16(&u16)) return false;
299 if (seqnum) *seqnum = u16;
300
301 // Read Timestamp field.
302 if (!buf.ReadUInt32(&u32)) return false;
303 if (tstamp) *tstamp = u32;
304
305 // Read SSRC field.
306 if (!buf.ReadUInt32(&u32)) return false;
307 if (ssrc) *ssrc = u32;
308
309 // Skip CSRCs.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200310 for (uint8_t i = 0; i < cc; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 if (!buf.ReadUInt32(&u32)) return false;
312 }
313
314 // Skip extension header.
315 if (extension) {
316 // Read Profile-specific extension header ID
317 if (!buf.ReadUInt16(&u16)) return false;
318
319 // Read Extension header length
320 if (!buf.ReadUInt16(&u16)) return false;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200321 uint16_t ext_header_len = u16;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322
323 // Read Extension header
Peter Boström0c4e06b2015-10-07 12:23:21 +0200324 for (uint16_t i = 0; i < ext_header_len; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325 if (!buf.ReadUInt32(&u32)) return false;
326 }
327 }
328
329 if (payload) {
330 return buf.ReadString(payload, buf.Length());
331 }
332 return true;
333 }
334
335 // Parse all RTCP packet, from start_index to stop_index, and count how many
336 // FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count
337 // and return true.
338 bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
339 int count = 0;
340 for (int i = start_index; i < stop_index; ++i) {
jbaucheec21bd2016-03-20 06:15:43 -0700341 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtcpPacket(i));
jbauchf1f87202016-03-30 06:43:37 -0700342 rtc::ByteBufferReader buf(p->data<char>(), p->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000343 size_t total_len = 0;
344 // The packet may be a compound RTCP packet.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000345 while (total_len < p->size()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 // Read FMT, type and length.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200347 uint8_t fmt = 0;
348 uint8_t type = 0;
349 uint16_t length = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000350 if (!buf.ReadUInt8(&fmt)) return false;
351 fmt &= 0x1F;
352 if (!buf.ReadUInt8(&type)) return false;
353 if (!buf.ReadUInt16(&length)) return false;
354 buf.Consume(length * 4); // Skip RTCP data.
355 total_len += (length + 1) * 4;
356 if ((192 == type) || ((206 == type) && (4 == fmt))) {
357 ++count;
358 }
359 }
360 }
361
362 if (fir_count) {
363 *fir_count = count;
364 }
365 return true;
366 }
367
Peter Boström0c4e06b2015-10-07 12:23:21 +0200368 void OnVideoChannelError(uint32_t ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000369 cricket::VideoMediaChannel::Error error) {
370 media_error_ = error;
371 }
372
373 // Test that SetSend works.
374 void SetSend() {
375 EXPECT_FALSE(channel_->sending());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000376 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000377 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
378 EXPECT_FALSE(channel_->sending());
379 EXPECT_TRUE(SetSend(true));
380 EXPECT_TRUE(channel_->sending());
381 EXPECT_TRUE(SendFrame());
382 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
383 EXPECT_TRUE(SetSend(false));
384 EXPECT_FALSE(channel_->sending());
385 }
386 // Test that SetSend fails without codecs being set.
387 void SetSendWithoutCodecs() {
388 EXPECT_FALSE(channel_->sending());
389 EXPECT_FALSE(SetSend(true));
390 EXPECT_FALSE(channel_->sending());
391 }
392 // Test that we properly set the send and recv buffer sizes by the time
393 // SetSend is called.
394 void SetSendSetsTransportBufferSizes() {
395 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
396 EXPECT_TRUE(SetSend(true));
buildbot@webrtc.orgae694ef2014-10-28 17:37:17 +0000397 EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000398 EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size());
399 }
400 // Tests that we can send frames and the right payload type is used.
401 void Send(const cricket::VideoCodec& codec) {
402 EXPECT_TRUE(SetOneCodec(codec));
403 EXPECT_TRUE(SetSend(true));
404 EXPECT_TRUE(SendFrame());
405 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
jbaucheec21bd2016-03-20 06:15:43 -0700406 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
408 }
409 // Tests that we can send and receive frames.
410 void SendAndReceive(const cricket::VideoCodec& codec) {
411 EXPECT_TRUE(SetOneCodec(codec));
412 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800413 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000414 EXPECT_EQ(0, renderer_.num_rendered_frames());
415 EXPECT_TRUE(SendFrame());
416 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
jbaucheec21bd2016-03-20 06:15:43 -0700417 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
419 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000420 void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec,
421 int duration_sec, int fps) {
422 EXPECT_TRUE(SetOneCodec(codec));
423 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800424 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000425 EXPECT_EQ(0, renderer_.num_rendered_frames());
426 for (int i = 0; i < duration_sec; ++i) {
427 for (int frame = 1; frame <= fps; ++frame) {
428 EXPECT_TRUE(WaitAndSendFrame(1000 / fps));
429 EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout);
430 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000431 }
jbaucheec21bd2016-03-20 06:15:43 -0700432 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000433 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
434 }
435
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000436 // Test that stats work properly for a 1-1 call.
437 void GetStats() {
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000438 const int kDurationSec = 3;
439 const int kFps = 10;
440 SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps);
441
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000443 EXPECT_TRUE(channel_->GetStats(&info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444
445 ASSERT_EQ(1U, info.senders.size());
446 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000447 // For webrtc, bytes_sent does not include the RTP header length.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 EXPECT_GT(info.senders[0].bytes_sent, 0);
449 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
450 EXPECT_EQ(0.0, info.senders[0].fraction_lost);
451 EXPECT_EQ(0, info.senders[0].firs_rcvd);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000452 EXPECT_EQ(0, info.senders[0].plis_rcvd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453 EXPECT_EQ(0, info.senders[0].nacks_rcvd);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000454 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
455 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 EXPECT_GT(info.senders[0].framerate_input, 0);
457 EXPECT_GT(info.senders[0].framerate_sent, 0);
458
459 ASSERT_EQ(1U, info.receivers.size());
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000460 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
461 EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
462 EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000463 EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
464 EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
465 EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
466 EXPECT_EQ(0, info.receivers[0].packets_lost);
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000467 // TODO(asapersson): Not set for webrtc. Handle missing stats.
468 // EXPECT_EQ(0, info.receivers[0].packets_concealed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000469 EXPECT_EQ(0, info.receivers[0].firs_sent);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000470 EXPECT_EQ(0, info.receivers[0].plis_sent);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471 EXPECT_EQ(0, info.receivers[0].nacks_sent);
472 EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width);
473 EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height);
474 EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
475 EXPECT_GT(info.receivers[0].framerate_decoded, 0);
476 EXPECT_GT(info.receivers[0].framerate_output, 0);
477 }
Stefan Holmer586b19b2015-09-18 11:14:31 +0200478
479 cricket::VideoSenderInfo GetSenderStats(size_t i) {
480 cricket::VideoMediaInfo info;
481 EXPECT_TRUE(channel_->GetStats(&info));
482 return info.senders[i];
483 }
484
485 cricket::VideoReceiverInfo GetReceiverStats(size_t i) {
486 cricket::VideoMediaInfo info;
487 EXPECT_TRUE(channel_->GetStats(&info));
488 return info.receivers[i];
489 }
490
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 // Test that stats work properly for a conf call with multiple recv streams.
492 void GetStatsMultipleRecvStreams() {
493 cricket::FakeVideoRenderer renderer1, renderer2;
494 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200495 cricket::VideoSendParameters parameters;
496 parameters.codecs.push_back(DefaultCodec());
nisse4b4dc862016-02-17 05:25:36 -0800497 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200498 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 EXPECT_TRUE(SetSend(true));
500 EXPECT_TRUE(channel_->AddRecvStream(
501 cricket::StreamParams::CreateLegacy(1)));
502 EXPECT_TRUE(channel_->AddRecvStream(
503 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800504 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
505 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000506 EXPECT_EQ(0, renderer1.num_rendered_frames());
507 EXPECT_EQ(0, renderer2.num_rendered_frames());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200508 std::vector<uint32_t> ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509 ssrcs.push_back(1);
510 ssrcs.push_back(2);
511 network_interface_.SetConferenceMode(true, ssrcs);
512 EXPECT_TRUE(SendFrame());
513 EXPECT_FRAME_ON_RENDERER_WAIT(
514 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
515 EXPECT_FRAME_ON_RENDERER_WAIT(
516 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200517
518 EXPECT_TRUE(channel_->SetSend(false));
519
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000521 EXPECT_TRUE(channel_->GetStats(&info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522 ASSERT_EQ(1U, info.senders.size());
523 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000524 // For webrtc, bytes_sent does not include the RTP header length.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200525 EXPECT_GT(GetSenderStats(0).bytes_sent, 0);
526 EXPECT_EQ_WAIT(NumRtpPackets(), GetSenderStats(0).packets_sent, kTimeout);
527 EXPECT_EQ(DefaultCodec().width, GetSenderStats(0).send_frame_width);
528 EXPECT_EQ(DefaultCodec().height, GetSenderStats(0).send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000529
530 ASSERT_EQ(2U, info.receivers.size());
531 for (size_t i = 0; i < info.receivers.size(); ++i) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200532 EXPECT_EQ(1U, GetReceiverStats(i).ssrcs().size());
533 EXPECT_EQ(i + 1, GetReceiverStats(i).ssrcs()[0]);
534 EXPECT_EQ_WAIT(NumRtpBytes(), GetReceiverStats(i).bytes_rcvd, kTimeout);
535 EXPECT_EQ_WAIT(NumRtpPackets(), GetReceiverStats(i).packets_rcvd,
536 kTimeout);
537 EXPECT_EQ(DefaultCodec().width, GetReceiverStats(i).frame_width);
538 EXPECT_EQ(DefaultCodec().height, GetReceiverStats(i).frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539 }
540 }
541 // Test that stats work properly for a conf call with multiple send streams.
542 void GetStatsMultipleSendStreams() {
543 // Normal setup; note that we set the SSRC explicitly to ensure that
544 // it will come first in the senders map.
545 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200546 cricket::VideoSendParameters parameters;
547 parameters.codecs.push_back(DefaultCodec());
nisse4b4dc862016-02-17 05:25:36 -0800548 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200549 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000550 EXPECT_TRUE(channel_->AddRecvStream(
buildbot@webrtc.org99f63082014-07-18 23:31:30 +0000551 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800552 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000553 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554 EXPECT_TRUE(SendFrame());
555 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
556 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
557
558 // Add an additional capturer, and hook up a renderer to receive it.
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000559 cricket::FakeVideoRenderer renderer2;
kwiberg686a8ef2016-02-26 03:00:35 -0800560 std::unique_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000561 CreateFakeVideoCapturer());
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000562 const int kTestWidth = 160;
563 const int kTestHeight = 120;
564 cricket::VideoFormat format(kTestWidth, kTestHeight,
565 cricket::VideoFormat::FpsToInterval(5),
566 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000567 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
568 EXPECT_TRUE(channel_->AddSendStream(
569 cricket::StreamParams::CreateLegacy(5678)));
570 EXPECT_TRUE(channel_->SetCapturer(5678, capturer.get()));
571 EXPECT_TRUE(channel_->AddRecvStream(
572 cricket::StreamParams::CreateLegacy(5678)));
nisse08582ff2016-02-04 01:24:52 -0800573 EXPECT_TRUE(channel_->SetSink(5678, &renderer2));
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000574 EXPECT_TRUE(capturer->CaptureCustomFrame(
575 kTestWidth, kTestHeight, cricket::FOURCC_I420));
576 EXPECT_FRAME_ON_RENDERER_WAIT(
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000577 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000579 // Get stats, and make sure they are correct for two senders. We wait until
580 // the number of expected packets have been sent to avoid races where we
581 // check stats before it has been updated.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 cricket::VideoMediaInfo info;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200583 for (uint32_t i = 0; i < kTimeout; ++i) {
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000584 rtc::Thread::Current()->ProcessMessages(1);
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000585 EXPECT_TRUE(channel_->GetStats(&info));
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000586 ASSERT_EQ(2U, info.senders.size());
587 if (info.senders[0].packets_sent + info.senders[1].packets_sent ==
588 NumRtpPackets()) {
589 // Stats have been updated for both sent frames, expectations can be
590 // checked now.
591 break;
592 }
593 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000594 EXPECT_EQ(NumRtpPackets(),
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000595 info.senders[0].packets_sent + info.senders[1].packets_sent)
596 << "Timed out while waiting for packet counts for all sent packets.";
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000597 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
598 EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000599 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
600 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000601 EXPECT_EQ(1U, info.senders[1].ssrcs().size());
602 EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000603 EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width);
604 EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000605 // The capturer must be unregistered here as it runs out of it's scope next.
606 EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
607 }
608
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000609 // Test that we can set the bandwidth.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610 void SetSendBandwidth() {
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200611 cricket::VideoSendParameters parameters;
612 parameters.codecs.push_back(DefaultCodec());
613 parameters.max_bandwidth_bps = -1; // <= 0 means unlimited.
614 EXPECT_TRUE(channel_->SetSendParameters(parameters));
615 parameters.max_bandwidth_bps = 128 * 1024;
616 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000617 }
618 // Test that we can set the SSRC for the default send source.
619 void SetSendSsrc() {
620 EXPECT_TRUE(SetDefaultCodec());
621 EXPECT_TRUE(SetSend(true));
622 EXPECT_TRUE(SendFrame());
623 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200624 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -0700625 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
627 EXPECT_EQ(kSsrc, ssrc);
Peter Boström718b6c72015-11-11 16:19:33 +0000628 // Packets are being paced out, so these can mismatch between the first and
629 // second call to NumRtpPackets until pending packets are paced out.
630 EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
631 EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632 EXPECT_EQ(1, NumSentSsrcs());
633 EXPECT_EQ(0, NumRtpPackets(kSsrc - 1));
634 EXPECT_EQ(0, NumRtpBytes(kSsrc - 1));
635 }
636 // Test that we can set the SSRC even after codecs are set.
637 void SetSendSsrcAfterSetCodecs() {
638 // Remove stream added in Setup.
639 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
640 EXPECT_TRUE(SetDefaultCodec());
641 EXPECT_TRUE(channel_->AddSendStream(
642 cricket::StreamParams::CreateLegacy(999)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000643 EXPECT_TRUE(channel_->SetCapturer(999u, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000644 EXPECT_TRUE(SetSend(true));
645 EXPECT_TRUE(WaitAndSendFrame(0));
646 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200647 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -0700648 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
650 EXPECT_EQ(999u, ssrc);
Peter Boström718b6c72015-11-11 16:19:33 +0000651 // Packets are being paced out, so these can mismatch between the first and
652 // second call to NumRtpPackets until pending packets are paced out.
653 EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
654 EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 EXPECT_EQ(1, NumSentSsrcs());
656 EXPECT_EQ(0, NumRtpPackets(kSsrc));
657 EXPECT_EQ(0, NumRtpBytes(kSsrc));
658 }
659 // Test that we can set the default video renderer before and after
660 // media is received.
nisse08582ff2016-02-04 01:24:52 -0800661 void SetSink() {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200662 uint8_t data1[] = {
663 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664
jbaucheec21bd2016-03-20 06:15:43 -0700665 rtc::CopyOnWriteBuffer packet1(data1, sizeof(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000666 rtc::SetBE32(packet1.data() + 8, kSsrc);
nisse08582ff2016-02-04 01:24:52 -0800667 channel_->SetSink(kDefaultReceiveSsrc, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 EXPECT_TRUE(SetDefaultCodec());
669 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000671 channel_->OnPacketReceived(&packet1, rtc::PacketTime());
nisse08582ff2016-02-04 01:24:52 -0800672 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 EXPECT_TRUE(SendFrame());
674 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
675 }
676
677 // Tests empty StreamParams is rejected.
678 void RejectEmptyStreamParams() {
679 // Remove the send stream that was added during Setup.
680 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
681
682 cricket::StreamParams empty;
683 EXPECT_FALSE(channel_->AddSendStream(empty));
684 EXPECT_TRUE(channel_->AddSendStream(
685 cricket::StreamParams::CreateLegacy(789u)));
686 }
687
688 // Tests setting up and configuring a send stream.
689 void AddRemoveSendStreams() {
690 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
691 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800692 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 EXPECT_TRUE(SendFrame());
694 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200695 EXPECT_GT(NumRtpPackets(), 0);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200696 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000697 size_t last_packet = NumRtpPackets() - 1;
jbaucheec21bd2016-03-20 06:15:43 -0700698 std::unique_ptr<const rtc::CopyOnWriteBuffer>
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000699 p(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
701 EXPECT_EQ(kSsrc, ssrc);
702
703 // Remove the send stream that was added during Setup.
704 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
705 int rtp_packets = NumRtpPackets();
706
707 EXPECT_TRUE(channel_->AddSendStream(
708 cricket::StreamParams::CreateLegacy(789u)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000709 EXPECT_TRUE(channel_->SetCapturer(789u, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 EXPECT_EQ(rtp_packets, NumRtpPackets());
711 // Wait 30ms to guarantee the engine does not drop the frame.
712 EXPECT_TRUE(WaitAndSendFrame(30));
713 EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
714
715 last_packet = NumRtpPackets() - 1;
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000716 p.reset(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
718 EXPECT_EQ(789u, ssrc);
719 }
720
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000721 // Tests the behavior of incoming streams in a conference scenario.
722 void SimulateConference() {
723 cricket::FakeVideoRenderer renderer1, renderer2;
724 EXPECT_TRUE(SetDefaultCodec());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200725 cricket::VideoSendParameters parameters;
726 parameters.codecs.push_back(DefaultCodec());
nisse4b4dc862016-02-17 05:25:36 -0800727 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200728 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 EXPECT_TRUE(channel_->AddRecvStream(
731 cricket::StreamParams::CreateLegacy(1)));
732 EXPECT_TRUE(channel_->AddRecvStream(
733 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800734 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
735 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736 EXPECT_EQ(0, renderer1.num_rendered_frames());
737 EXPECT_EQ(0, renderer2.num_rendered_frames());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200738 std::vector<uint32_t> ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000739 ssrcs.push_back(1);
740 ssrcs.push_back(2);
741 network_interface_.SetConferenceMode(true, ssrcs);
742 EXPECT_TRUE(SendFrame());
743 EXPECT_FRAME_ON_RENDERER_WAIT(
744 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
745 EXPECT_FRAME_ON_RENDERER_WAIT(
746 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
747
jbaucheec21bd2016-03-20 06:15:43 -0700748 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000749 EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
750 EXPECT_EQ(DefaultCodec().width, renderer1.width());
751 EXPECT_EQ(DefaultCodec().height, renderer1.height());
752 EXPECT_EQ(DefaultCodec().width, renderer2.width());
753 EXPECT_EQ(DefaultCodec().height, renderer2.height());
754 EXPECT_TRUE(channel_->RemoveRecvStream(2));
755 EXPECT_TRUE(channel_->RemoveRecvStream(1));
756 }
757
758 // Tests that we can add and remove capturers and frames are sent out properly
759 void AddRemoveCapturer() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000760 cricket::VideoCodec codec = DefaultCodec();
761 codec.width = 320;
762 codec.height = 240;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 const int time_between_send = TimeBetweenSend(codec);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000764 EXPECT_TRUE(SetOneCodec(codec));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000765 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800766 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000767 EXPECT_EQ(0, renderer_.num_rendered_frames());
768 EXPECT_TRUE(SendFrame());
769 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
kwiberg686a8ef2016-02-26 03:00:35 -0800770 std::unique_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000771 CreateFakeVideoCapturer());
Niels Möller60653ba2016-03-02 11:41:36 +0100772
773 // TODO(nisse): This testcase fails if we don't configure
774 // screencast. It's unclear why, I see nothing obvious in this
775 // test which is related to screencast logic.
776 cricket::VideoOptions video_options;
777 video_options.is_screencast = rtc::Optional<bool>(true);
778 channel_->SetVideoSend(kSsrc, true, &video_options);
779
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000780 cricket::VideoFormat format(480, 360,
781 cricket::VideoFormat::FpsToInterval(30),
782 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
784 // All capturers start generating frames with the same timestamp. ViE does
785 // not allow the same timestamp to be used. Capture one frame before
786 // associating the capturer with the channel.
787 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
788 cricket::FOURCC_I420));
789
790 int captured_frames = 1;
791 for (int iterations = 0; iterations < 2; ++iterations) {
792 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000793 rtc::Thread::Current()->ProcessMessages(time_between_send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
795 cricket::FOURCC_I420));
796 ++captured_frames;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000797 // Wait until frame of right size is captured.
798 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
799 format.width == renderer_.width() &&
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000800 format.height == renderer_.height() &&
801 !renderer_.black_frame(), kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000802 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
803 EXPECT_EQ(format.width, renderer_.width());
804 EXPECT_EQ(format.height, renderer_.height());
805 captured_frames = renderer_.num_rendered_frames() + 1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000806 EXPECT_FALSE(renderer_.black_frame());
807 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000808 // Make sure a black frame is generated within the specified timeout.
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000809 // The black frame should be the resolution of the previous frame to
810 // prevent expensive encoder reconfigurations.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000811 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000812 format.width == renderer_.width() &&
813 format.height == renderer_.height() &&
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000814 renderer_.black_frame(), kTimeout);
815 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000816 EXPECT_EQ(format.width, renderer_.width());
817 EXPECT_EQ(format.height, renderer_.height());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818 EXPECT_TRUE(renderer_.black_frame());
819
820 // The black frame has the same timestamp as the next frame since it's
821 // timestamp is set to the last frame's timestamp + interval. WebRTC will
822 // not render a frame with the same timestamp so capture another frame
823 // with the frame capturer to increment the next frame's timestamp.
824 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
825 cricket::FOURCC_I420));
826 }
827 }
828
829 // Tests that if RemoveCapturer is called without a capturer ever being
830 // added, the plugin shouldn't crash (and no black frame should be sent).
831 void RemoveCapturerWithoutAdd() {
832 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
833 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800834 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 EXPECT_EQ(0, renderer_.num_rendered_frames());
836 EXPECT_TRUE(SendFrame());
837 EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000838 // Wait for one frame so they don't get dropped because we send frames too
839 // tightly.
840 rtc::Thread::Current()->ProcessMessages(30);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000841 // Remove the capturer.
842 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000843 // Wait for one black frame for removing the capturer.
844 EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
845
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000846 // No capturer was added, so this RemoveCapturer should
847 // fail.
848 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000849 rtc::Thread::Current()->ProcessMessages(300);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000850 // Verify no more frames were sent.
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000851 EXPECT_EQ(2, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000852 }
853
854 // Tests that we can add and remove capturer as unique sources.
855 void AddRemoveCapturerMultipleSources() {
856 // WebRTC implementation will drop frames if pushed to quickly. Wait the
857 // interval time to avoid that.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000858 // WebRTC implementation will drop frames if pushed to quickly. Wait the
859 // interval time to avoid that.
860 // Set up the stream associated with the engine.
861 EXPECT_TRUE(channel_->AddRecvStream(
862 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800863 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 cricket::VideoFormat capture_format; // default format
865 capture_format.interval = cricket::VideoFormat::FpsToInterval(30);
866 // Set up additional stream 1.
867 cricket::FakeVideoRenderer renderer1;
nisse08582ff2016-02-04 01:24:52 -0800868 EXPECT_FALSE(channel_->SetSink(1, &renderer1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000869 EXPECT_TRUE(channel_->AddRecvStream(
870 cricket::StreamParams::CreateLegacy(1)));
nisse08582ff2016-02-04 01:24:52 -0800871 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000872 EXPECT_TRUE(channel_->AddSendStream(
873 cricket::StreamParams::CreateLegacy(1)));
kwiberg686a8ef2016-02-26 03:00:35 -0800874 std::unique_ptr<cricket::FakeVideoCapturer> capturer1(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000875 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876 EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format));
877 // Set up additional stream 2.
878 cricket::FakeVideoRenderer renderer2;
nisse08582ff2016-02-04 01:24:52 -0800879 EXPECT_FALSE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000880 EXPECT_TRUE(channel_->AddRecvStream(
881 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800882 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000883 EXPECT_TRUE(channel_->AddSendStream(
884 cricket::StreamParams::CreateLegacy(2)));
kwiberg686a8ef2016-02-26 03:00:35 -0800885 std::unique_ptr<cricket::FakeVideoCapturer> capturer2(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000886 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000887 EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
888 // State for all the streams.
889 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
890 // A limitation in the lmi implementation requires that SetCapturer() is
891 // called after SetOneCodec().
892 // TODO(hellner): this seems like an unnecessary constraint, fix it.
893 EXPECT_TRUE(channel_->SetCapturer(1, capturer1.get()));
894 EXPECT_TRUE(channel_->SetCapturer(2, capturer2.get()));
895 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000896 // Test capturer associated with engine.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000897 const int kTestWidth = 160;
898 const int kTestHeight = 120;
899 EXPECT_TRUE(capturer1->CaptureCustomFrame(
900 kTestWidth, kTestHeight, cricket::FOURCC_I420));
901 EXPECT_FRAME_ON_RENDERER_WAIT(
902 renderer1, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000903 // Capture a frame with additional capturer2, frames should be received
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000904 EXPECT_TRUE(capturer2->CaptureCustomFrame(
905 kTestWidth, kTestHeight, cricket::FOURCC_I420));
906 EXPECT_FRAME_ON_RENDERER_WAIT(
907 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000908 // Successfully remove the capturer.
909 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
910 // Fail to re-remove the capturer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
912 // The capturers must be unregistered here as it runs out of it's scope
913 // next.
914 EXPECT_TRUE(channel_->SetCapturer(1, NULL));
915 EXPECT_TRUE(channel_->SetCapturer(2, NULL));
916 }
917
918 void HighAspectHighHeightCapturer() {
919 const int kWidth = 80;
920 const int kHeight = 10000;
921 const int kScaledWidth = 20;
922 const int kScaledHeight = 2500;
923
924 cricket::VideoCodec codec(DefaultCodec());
925 EXPECT_TRUE(SetOneCodec(codec));
926 EXPECT_TRUE(SetSend(true));
927
928 cricket::FakeVideoRenderer renderer;
929 EXPECT_TRUE(channel_->AddRecvStream(
930 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800931 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000932 EXPECT_EQ(0, renderer.num_rendered_frames());
933
934 EXPECT_TRUE(SendFrame());
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000935 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
936 renderer, 1, codec.width, codec.height, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937
938 // Registering an external capturer is currently the same as screen casting
939 // (update the test when this changes).
kwiberg686a8ef2016-02-26 03:00:35 -0800940 std::unique_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000941 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942 const std::vector<cricket::VideoFormat>* formats =
943 capturer->GetSupportedFormats();
944 cricket::VideoFormat capture_format = (*formats)[0];
945 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format));
946 // Capture frame to not get same frame timestamps as previous capturer.
947 capturer->CaptureFrame();
948 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000949 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
951 cricket::FOURCC_ARGB));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000952 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
953 renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000954 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
955 }
956
957 // Tests that we can adapt video resolution with 16:10 aspect ratio properly.
958 void AdaptResolution16x10() {
nisse08582ff2016-02-04 01:24:52 -0800959 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960 cricket::VideoCodec codec(DefaultCodec());
961 codec.width = 640;
962 codec.height = 400;
963 SendAndReceive(codec);
964 codec.width /= 2;
965 codec.height /= 2;
966 // Adapt the resolution.
967 EXPECT_TRUE(SetOneCodec(codec));
968 EXPECT_TRUE(WaitAndSendFrame(30));
969 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
970 }
971 // Tests that we can adapt video resolution with 4:3 aspect ratio properly.
972 void AdaptResolution4x3() {
nisse08582ff2016-02-04 01:24:52 -0800973 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974 cricket::VideoCodec codec(DefaultCodec());
975 codec.width = 640;
976 codec.height = 400;
977 SendAndReceive(codec);
978 codec.width /= 2;
979 codec.height /= 2;
980 // Adapt the resolution.
981 EXPECT_TRUE(SetOneCodec(codec));
982 EXPECT_TRUE(WaitAndSendFrame(30));
983 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
984 }
985 // Tests that we can drop all frames properly.
986 void AdaptDropAllFrames() {
987 // Set the channel codec's resolution to 0, which will require the adapter
988 // to drop all frames.
989 cricket::VideoCodec codec(DefaultCodec());
990 codec.width = codec.height = codec.framerate = 0;
991 EXPECT_TRUE(SetOneCodec(codec));
992 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800993 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994 EXPECT_EQ(0, renderer_.num_rendered_frames());
995 EXPECT_TRUE(SendFrame());
996 EXPECT_TRUE(SendFrame());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000997 rtc::Thread::Current()->ProcessMessages(500);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000998 EXPECT_EQ(0, renderer_.num_rendered_frames());
999 }
1000 // Tests that we can reduce the frame rate on demand properly.
1001 // TODO(fbarchard): This test is flakey on pulse. Fix and re-enable
1002 void AdaptFramerate() {
1003 cricket::VideoCodec codec(DefaultCodec());
1004 int frame_count = 0;
1005 // The capturer runs at 30 fps. The channel requires 30 fps.
1006 EXPECT_TRUE(SetOneCodec(codec));
1007 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001008 EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1009 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1010 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1011 frame_count += 2;
1012 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
jbaucheec21bd2016-03-20 06:15:43 -07001013 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
1015
1016 // The channel requires 15 fps.
1017 codec.framerate = 15;
1018 EXPECT_TRUE(SetOneCodec(codec));
1019 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1020 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1021 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1022 frame_count += 2;
1023 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1024
1025 // The channel requires 10 fps.
1026 codec.framerate = 10;
1027 EXPECT_TRUE(SetOneCodec(codec));
1028 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1029 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1030 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1031 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1032 frame_count += 2;
1033 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1034
1035 // The channel requires 8 fps. The adapter adapts to 10 fps, which is the
1036 // closest factor of 30.
1037 codec.framerate = 8;
1038 EXPECT_TRUE(SetOneCodec(codec));
1039 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1040 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1041 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1042 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1043 frame_count += 2;
1044 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1045 }
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001046 // Tests that adapted frames won't be upscaled to a higher resolution.
1047 void SendsLowerResolutionOnSmallerFrames() {
1048 cricket::VideoCodec codec = DefaultCodec();
1049 codec.width = 320;
1050 codec.height = 240;
1051 EXPECT_TRUE(SetOneCodec(codec));
1052 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -08001053 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001054 EXPECT_EQ(0, renderer_.num_rendered_frames());
1055 EXPECT_TRUE(SendFrame());
1056 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
1057
1058 // Check that we send smaller frames at the new resolution.
pbos@webrtc.orgebee4012014-09-03 15:52:02 +00001059 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(33));
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001060 EXPECT_TRUE(video_capturer_->CaptureCustomFrame(
1061 codec.width / 2, codec.height / 2, cricket::FOURCC_I420));
1062 EXPECT_FRAME_WAIT(2, codec.width / 2, codec.height / 2, kTimeout);
1063 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001064
1065 // Tests that we can mute and unmute the channel properly.
1066 void MuteStream() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001067 EXPECT_TRUE(SetDefaultCodec());
1068 cricket::FakeVideoCapturer video_capturer;
1069 video_capturer.Start(
1070 cricket::VideoFormat(
1071 640, 480,
1072 cricket::VideoFormat::FpsToInterval(30),
1073 cricket::FOURCC_I420));
1074 EXPECT_TRUE(channel_->SetCapturer(kSsrc, &video_capturer));
1075 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -08001076 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
buildbot@webrtc.org99f63082014-07-18 23:31:30 +00001077 EXPECT_EQ(0, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001078 // Mute the channel and expect black output frame.
buildbot@webrtc.org99f63082014-07-18 23:31:30 +00001079 int frame_count = 0;
solenbergdfc8f4f2015-10-01 02:31:10 -07001080 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001081 EXPECT_TRUE(video_capturer.CaptureFrame());
1082 ++frame_count;
1083 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1084 EXPECT_TRUE(renderer_.black_frame());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001085 // Unmute the channel and expect non-black output frame.
solenbergdfc8f4f2015-10-01 02:31:10 -07001086 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001087 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001088 EXPECT_TRUE(video_capturer.CaptureFrame());
1089 ++frame_count;
1090 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1091 EXPECT_FALSE(renderer_.black_frame());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001092 // Test that we can also Mute using the correct send stream SSRC.
solenbergdfc8f4f2015-10-01 02:31:10 -07001093 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001094 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001095 EXPECT_TRUE(video_capturer.CaptureFrame());
1096 ++frame_count;
1097 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1098 EXPECT_TRUE(renderer_.black_frame());
solenbergdfc8f4f2015-10-01 02:31:10 -07001099 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001100 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 EXPECT_TRUE(video_capturer.CaptureFrame());
1102 ++frame_count;
1103 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1104 EXPECT_FALSE(renderer_.black_frame());
pbos@webrtc.orgef8bb8d2014-08-13 21:36:18 +00001105 // Test that muting an existing stream succeeds even if it's muted.
solenbergdfc8f4f2015-10-01 02:31:10 -07001106 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
1107 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
pbos@webrtc.orgef8bb8d2014-08-13 21:36:18 +00001108 // Test that unmuting an existing stream succeeds even if it's not muted.
solenbergdfc8f4f2015-10-01 02:31:10 -07001109 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
1110 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001111 // Test that muting an invalid stream fails.
solenbergdfc8f4f2015-10-01 02:31:10 -07001112 EXPECT_FALSE(channel_->SetVideoSend(kSsrc+1, false, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001113 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1114 }
1115
1116 // Test that multiple send streams can be created and deleted properly.
1117 void MultipleSendStreams() {
1118 // Remove stream added in Setup. I.e. remove stream corresponding to default
1119 // channel.
1120 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1121 const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]);
1122 for (unsigned int i = 0; i < kSsrcsSize; ++i) {
1123 EXPECT_TRUE(channel_->AddSendStream(
1124 cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
1125 }
1126 // Delete one of the non default channel streams, let the destructor delete
1127 // the remaining ones.
1128 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1129 // Stream should already be deleted.
1130 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1131 }
1132
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001133 // Two streams one channel tests.
1134
1135 // Tests that we can send and receive frames.
1136 void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) {
1137 SetUpSecondStream();
1138 // Test sending and receiving on first stream.
1139 SendAndReceive(codec);
1140 // Test sending and receiving on second stream.
1141 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +02001142 EXPECT_GT(NumRtpPackets(), 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001143 EXPECT_EQ(1, renderer2_.num_rendered_frames());
1144 }
1145
kwiberg686a8ef2016-02-26 03:00:35 -08001146 const std::unique_ptr<webrtc::Call> call_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001147 VideoEngineOverride<E> engine_;
kwiberg686a8ef2016-02-26 03:00:35 -08001148 std::unique_ptr<cricket::FakeVideoCapturer> video_capturer_;
1149 std::unique_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
1150 std::unique_ptr<C> channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 cricket::FakeNetworkInterface network_interface_;
1152 cricket::FakeVideoRenderer renderer_;
1153 cricket::VideoMediaChannel::Error media_error_;
1154
1155 // Used by test cases where 2 streams are run on the same channel.
1156 cricket::FakeVideoRenderer renderer2_;
1157};
1158
kjellandera96e2d72016-02-04 23:52:28 -08001159#endif // WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT