blob: 2541c4acd3d02a21ddaec08b00938eed186c5b82 [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
14#include <string>
15#include <vector>
16
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000017#include "webrtc/base/bytebuffer.h"
18#include "webrtc/base/gunit.h"
19#include "webrtc/base/timeutils.h"
Fredrik Solenberg709ed672015-09-15 12:26:33 +020020#include "webrtc/call.h"
kjellandera96e2d72016-02-04 23:52:28 -080021#include "webrtc/media/base/fakenetworkinterface.h"
22#include "webrtc/media/base/fakevideocapturer.h"
23#include "webrtc/media/base/fakevideorenderer.h"
24#include "webrtc/media/base/mediachannel.h"
25#include "webrtc/media/base/streamparams.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010026#include "webrtc/media/engine/fakewebrtccall.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028#define EXPECT_FRAME_WAIT(c, w, h, t) \
29 EXPECT_EQ_WAIT((c), renderer_.num_rendered_frames(), (t)); \
30 EXPECT_EQ((w), renderer_.width()); \
31 EXPECT_EQ((h), renderer_.height()); \
32 EXPECT_EQ(0, renderer_.errors()); \
33
34#define EXPECT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
35 EXPECT_EQ_WAIT((c), (r).num_rendered_frames(), (t)); \
36 EXPECT_EQ((w), (r).width()); \
37 EXPECT_EQ((h), (r).height()); \
38 EXPECT_EQ(0, (r).errors()); \
39
wu@webrtc.org9caf2762013-12-11 18:25:07 +000040#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
41 EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
42 (w) == (r).width() && \
43 (h) == (r).height(), (t)); \
Peter Boström0c4e06b2015-10-07 12:23:21 +020044 EXPECT_EQ(0, (r).errors());
wu@webrtc.org9caf2762013-12-11 18:25:07 +000045
Peter Boström0c4e06b2015-10-07 12:23:21 +020046static const uint32_t kTimeout = 5000U;
47static const uint32_t kDefaultReceiveSsrc = 0;
48static const uint32_t kSsrc = 1234u;
49static const uint32_t kRtxSsrc = 4321u;
50static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051
52inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) {
53 return a.width == w && a.height == h && a.framerate == fps;
54}
55
56inline bool IsEqualCodec(const cricket::VideoCodec& a,
57 const cricket::VideoCodec& b) {
58 return a.id == b.id && a.name == b.name &&
59 IsEqualRes(a, b.width, b.height, b.framerate);
60}
61
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000062namespace std {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
64 s << "{" << c.name << "(" << c.id << "), "
65 << c.width << "x" << c.height << "x" << c.framerate << "}";
66 return s;
67}
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000068} // namespace std
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069
70inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000071 return static_cast<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072 cricket::VideoFormat::FpsToInterval(codec.framerate) /
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000073 rtc::kNumNanosecsPerMillisec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074}
75
76// Fake video engine that makes it possible to test enabling and disabling
77// capturer (checking that the engine state is updated and that the capturer
78// is indeed capturing) without having to create a channel. It also makes it
79// possible to test that the media processors are indeed being called when
80// registered.
81template<class T>
82class VideoEngineOverride : public T {
83 public:
Fredrik Solenberg709ed672015-09-15 12:26:33 +020084 VideoEngineOverride() : T() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085 }
86 virtual ~VideoEngineOverride() {
87 }
88 bool is_camera_on() const { return T::GetVideoCapturer()->IsRunning(); }
perkj162c3392016-02-11 02:56:35 -080089 void set_has_senders(bool has_senders) {
90 cricket::VideoCapturer* video_capturer = T::GetVideoCapturer();
91 if (has_senders) {
92 video_capturer->SignalVideoFrame.connect(this,
93 &VideoEngineOverride<T>::OnLocalFrame);
94 } else {
95 video_capturer->SignalVideoFrame.disconnect(this);
96 }
97 }
98 void OnLocalFrame(cricket::VideoCapturer*,
99 const cricket::VideoFrame*) {
100 }
101 void OnLocalFrameFormat(cricket::VideoCapturer*,
102 const cricket::VideoFormat*) {
103 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104
Peter Boström0c4e06b2015-10-07 12:23:21 +0200105 void TriggerMediaFrame(uint32_t ssrc,
106 cricket::VideoFrame* frame,
107 bool* drop_frame) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108 T::SignalMediaFrame(ssrc, frame, drop_frame);
109 }
110};
111
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112template<class E, class C>
113class VideoMediaChannelTest : public testing::Test,
114 public sigslot::has_slots<> {
115 protected:
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200116 VideoMediaChannelTest<E, C>()
117 : call_(webrtc::Call::Create(webrtc::Call::Config())) {}
118
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 virtual cricket::VideoCodec DefaultCodec() = 0;
120
121 virtual cricket::StreamParams DefaultSendStreamParams() {
122 return cricket::StreamParams::CreateLegacy(kSsrc);
123 }
124
125 virtual void SetUp() {
126 cricket::Device device("test", "device");
Fredrik Solenberg9a416bd2015-05-22 09:04:09 +0200127 engine_.Init();
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200128 channel_.reset(
129 engine_.CreateChannel(call_.get(), cricket::VideoOptions()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130 EXPECT_TRUE(channel_.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131 network_interface_.SetDestination(channel_.get());
132 channel_->SetInterface(&network_interface_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 media_error_ = cricket::VideoMediaChannel::ERROR_NONE;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200134 cricket::VideoRecvParameters parameters;
135 parameters.codecs = engine_.codecs();
136 channel_->SetRecvParameters(parameters);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137 EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams()));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000138 video_capturer_.reset(CreateFakeVideoCapturer());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000139 cricket::VideoFormat format(640, 480,
140 cricket::VideoFormat::FpsToInterval(30),
141 cricket::FOURCC_I420);
142 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
143 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000144 }
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000145
146 virtual cricket::FakeVideoCapturer* CreateFakeVideoCapturer() {
147 return new cricket::FakeVideoCapturer();
148 }
149
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000150 // Utility method to setup an additional stream to send and receive video.
151 // Used to test send and recv between two streams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152 void SetUpSecondStream() {
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000153 SetUpSecondStreamWithNoRecv();
154 // Setup recv for second stream.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 EXPECT_TRUE(channel_->AddRecvStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000156 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000157 // Make the second renderer available for use by a new stream.
nisse08582ff2016-02-04 01:24:52 -0800158 EXPECT_TRUE(channel_->SetSink(kSsrc + 2, &renderer2_));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000159 }
160 // Setup an additional stream just to send video. Defer add recv stream.
161 // This is required if you want to test unsignalled recv of video rtp packets.
162 void SetUpSecondStreamWithNoRecv() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163 // SetUp() already added kSsrc make sure duplicate SSRCs cant be added.
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000164 EXPECT_TRUE(channel_->AddRecvStream(
165 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800166 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 EXPECT_FALSE(channel_->AddSendStream(
168 cricket::StreamParams::CreateLegacy(kSsrc)));
169 EXPECT_TRUE(channel_->AddSendStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000170 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000171 // We dont add recv for the second stream.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000172
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000173 // Setup the receive and renderer for second stream after send.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000174 video_capturer_2_.reset(CreateFakeVideoCapturer());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000175 cricket::VideoFormat format(640, 480,
176 cricket::VideoFormat::FpsToInterval(30),
177 cricket::FOURCC_I420);
178 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
179
180 EXPECT_TRUE(channel_->SetCapturer(kSsrc + 2, video_capturer_2_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181 }
182 virtual void TearDown() {
183 channel_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000184 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000185 bool SetDefaultCodec() {
186 return SetOneCodec(DefaultCodec());
187 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188
189 bool SetOneCodec(int pt, const char* name, int w, int h, int fr) {
190 return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0));
191 }
192 bool SetOneCodec(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000193 cricket::VideoFormat capture_format(codec.width, codec.height,
194 cricket::VideoFormat::FpsToInterval(codec.framerate),
195 cricket::FOURCC_I420);
196
197 if (video_capturer_) {
198 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format));
199 }
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000200 if (video_capturer_2_) {
201 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format));
202 }
203
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000204 bool sending = channel_->sending();
205 bool success = SetSend(false);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200206 if (success) {
207 cricket::VideoSendParameters parameters;
208 parameters.codecs.push_back(codec);
209 success = channel_->SetSendParameters(parameters);
210 }
211 if (success) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 success = SetSend(sending);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200213 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000214 return success;
215 }
216 bool SetSend(bool send) {
217 return channel_->SetSend(send);
218 }
219 int DrainOutgoingPackets() {
220 int packets = 0;
221 do {
222 packets = NumRtpPackets();
223 // 100 ms should be long enough.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000224 rtc::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000225 } while (NumRtpPackets() > packets);
226 return NumRtpPackets();
227 }
228 bool SendFrame() {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000229 if (video_capturer_2_) {
230 video_capturer_2_->CaptureFrame();
231 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000232 return video_capturer_.get() &&
233 video_capturer_->CaptureFrame();
234 }
235 bool WaitAndSendFrame(int wait_ms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000236 bool ret = rtc::Thread::Current()->ProcessMessages(wait_ms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000237 ret &= SendFrame();
238 return ret;
239 }
240 // Sends frames and waits for the decoder to be fully initialized.
241 // Returns the number of frames that were sent.
242 int WaitForDecoder() {
243#if defined(HAVE_OPENMAX)
244 // Send enough frames for the OpenMAX decoder to continue processing, and
245 // return the number of frames sent.
246 // Send frames for a full kTimeout's worth of 15fps video.
247 int frame_count = 0;
248 while (frame_count < static_cast<int>(kTimeout) / 66) {
249 EXPECT_TRUE(WaitAndSendFrame(66));
250 ++frame_count;
251 }
252 return frame_count;
253#else
254 return 0;
255#endif
256 }
257 bool SendCustomVideoFrame(int w, int h) {
258 if (!video_capturer_.get()) return false;
259 return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420);
260 }
261 int NumRtpBytes() {
262 return network_interface_.NumRtpBytes();
263 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200264 int NumRtpBytes(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265 return network_interface_.NumRtpBytes(ssrc);
266 }
267 int NumRtpPackets() {
268 return network_interface_.NumRtpPackets();
269 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200270 int NumRtpPackets(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271 return network_interface_.NumRtpPackets(ssrc);
272 }
273 int NumSentSsrcs() {
274 return network_interface_.NumSentSsrcs();
275 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000276 const rtc::Buffer* GetRtpPacket(int index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000277 return network_interface_.GetRtpPacket(index);
278 }
279 int NumRtcpPackets() {
280 return network_interface_.NumRtcpPackets();
281 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000282 const rtc::Buffer* GetRtcpPacket(int index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283 return network_interface_.GetRtcpPacket(index);
284 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000285 static int GetPayloadType(const rtc::Buffer* p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 int pt = -1;
287 ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
288 return pt;
289 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200290 static bool ParseRtpPacket(const rtc::Buffer* p,
291 bool* x,
292 int* pt,
293 int* seqnum,
294 uint32_t* tstamp,
295 uint32_t* ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 std::string* payload) {
Karl Wiberg94784372015-04-20 14:03:07 +0200297 rtc::ByteBuffer buf(*p);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200298 uint8_t u08 = 0;
299 uint16_t u16 = 0;
300 uint32_t u32 = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000301
302 // Read X and CC fields.
303 if (!buf.ReadUInt8(&u08)) return false;
304 bool extension = ((u08 & 0x10) != 0);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200305 uint8_t cc = (u08 & 0x0F);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306 if (x) *x = extension;
307
308 // Read PT field.
309 if (!buf.ReadUInt8(&u08)) return false;
310 if (pt) *pt = (u08 & 0x7F);
311
312 // Read Sequence Number field.
313 if (!buf.ReadUInt16(&u16)) return false;
314 if (seqnum) *seqnum = u16;
315
316 // Read Timestamp field.
317 if (!buf.ReadUInt32(&u32)) return false;
318 if (tstamp) *tstamp = u32;
319
320 // Read SSRC field.
321 if (!buf.ReadUInt32(&u32)) return false;
322 if (ssrc) *ssrc = u32;
323
324 // Skip CSRCs.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200325 for (uint8_t i = 0; i < cc; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326 if (!buf.ReadUInt32(&u32)) return false;
327 }
328
329 // Skip extension header.
330 if (extension) {
331 // Read Profile-specific extension header ID
332 if (!buf.ReadUInt16(&u16)) return false;
333
334 // Read Extension header length
335 if (!buf.ReadUInt16(&u16)) return false;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200336 uint16_t ext_header_len = u16;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000337
338 // Read Extension header
Peter Boström0c4e06b2015-10-07 12:23:21 +0200339 for (uint16_t i = 0; i < ext_header_len; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000340 if (!buf.ReadUInt32(&u32)) return false;
341 }
342 }
343
344 if (payload) {
345 return buf.ReadString(payload, buf.Length());
346 }
347 return true;
348 }
349
350 // Parse all RTCP packet, from start_index to stop_index, and count how many
351 // FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count
352 // and return true.
353 bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
354 int count = 0;
355 for (int i = start_index; i < stop_index; ++i) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000356 rtc::scoped_ptr<const rtc::Buffer> p(GetRtcpPacket(i));
Karl Wiberg94784372015-04-20 14:03:07 +0200357 rtc::ByteBuffer buf(*p);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000358 size_t total_len = 0;
359 // The packet may be a compound RTCP packet.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000360 while (total_len < p->size()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000361 // Read FMT, type and length.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200362 uint8_t fmt = 0;
363 uint8_t type = 0;
364 uint16_t length = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365 if (!buf.ReadUInt8(&fmt)) return false;
366 fmt &= 0x1F;
367 if (!buf.ReadUInt8(&type)) return false;
368 if (!buf.ReadUInt16(&length)) return false;
369 buf.Consume(length * 4); // Skip RTCP data.
370 total_len += (length + 1) * 4;
371 if ((192 == type) || ((206 == type) && (4 == fmt))) {
372 ++count;
373 }
374 }
375 }
376
377 if (fir_count) {
378 *fir_count = count;
379 }
380 return true;
381 }
382
Peter Boström0c4e06b2015-10-07 12:23:21 +0200383 void OnVideoChannelError(uint32_t ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 cricket::VideoMediaChannel::Error error) {
385 media_error_ = error;
386 }
387
388 // Test that SetSend works.
389 void SetSend() {
390 EXPECT_FALSE(channel_->sending());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000391 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000392 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
393 EXPECT_FALSE(channel_->sending());
394 EXPECT_TRUE(SetSend(true));
395 EXPECT_TRUE(channel_->sending());
396 EXPECT_TRUE(SendFrame());
397 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
398 EXPECT_TRUE(SetSend(false));
399 EXPECT_FALSE(channel_->sending());
400 }
401 // Test that SetSend fails without codecs being set.
402 void SetSendWithoutCodecs() {
403 EXPECT_FALSE(channel_->sending());
404 EXPECT_FALSE(SetSend(true));
405 EXPECT_FALSE(channel_->sending());
406 }
407 // Test that we properly set the send and recv buffer sizes by the time
408 // SetSend is called.
409 void SetSendSetsTransportBufferSizes() {
410 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
411 EXPECT_TRUE(SetSend(true));
buildbot@webrtc.orgae694ef2014-10-28 17:37:17 +0000412 EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000413 EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size());
414 }
415 // Tests that we can send frames and the right payload type is used.
416 void Send(const cricket::VideoCodec& codec) {
417 EXPECT_TRUE(SetOneCodec(codec));
418 EXPECT_TRUE(SetSend(true));
419 EXPECT_TRUE(SendFrame());
420 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000421 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000422 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
423 }
424 // Tests that we can send and receive frames.
425 void SendAndReceive(const cricket::VideoCodec& codec) {
426 EXPECT_TRUE(SetOneCodec(codec));
427 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800428 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000429 EXPECT_EQ(0, renderer_.num_rendered_frames());
430 EXPECT_TRUE(SendFrame());
431 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000432 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
434 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000435 void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec,
436 int duration_sec, int fps) {
437 EXPECT_TRUE(SetOneCodec(codec));
438 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800439 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000440 EXPECT_EQ(0, renderer_.num_rendered_frames());
441 for (int i = 0; i < duration_sec; ++i) {
442 for (int frame = 1; frame <= fps; ++frame) {
443 EXPECT_TRUE(WaitAndSendFrame(1000 / fps));
444 EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout);
445 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000446 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000447 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000448 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
449 }
450
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000451 // Test that stats work properly for a 1-1 call.
452 void GetStats() {
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000453 const int kDurationSec = 3;
454 const int kFps = 10;
455 SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps);
456
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000457 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000458 EXPECT_TRUE(channel_->GetStats(&info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000459
460 ASSERT_EQ(1U, info.senders.size());
461 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000462 // For webrtc, bytes_sent does not include the RTP header length.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000463 EXPECT_GT(info.senders[0].bytes_sent, 0);
464 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
465 EXPECT_EQ(0.0, info.senders[0].fraction_lost);
466 EXPECT_EQ(0, info.senders[0].firs_rcvd);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000467 EXPECT_EQ(0, info.senders[0].plis_rcvd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468 EXPECT_EQ(0, info.senders[0].nacks_rcvd);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000469 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
470 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471 EXPECT_GT(info.senders[0].framerate_input, 0);
472 EXPECT_GT(info.senders[0].framerate_sent, 0);
473
474 ASSERT_EQ(1U, info.receivers.size());
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000475 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
476 EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
477 EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000478 EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
479 EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
480 EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
481 EXPECT_EQ(0, info.receivers[0].packets_lost);
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000482 // TODO(asapersson): Not set for webrtc. Handle missing stats.
483 // EXPECT_EQ(0, info.receivers[0].packets_concealed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 EXPECT_EQ(0, info.receivers[0].firs_sent);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000485 EXPECT_EQ(0, info.receivers[0].plis_sent);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 EXPECT_EQ(0, info.receivers[0].nacks_sent);
487 EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width);
488 EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height);
489 EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
490 EXPECT_GT(info.receivers[0].framerate_decoded, 0);
491 EXPECT_GT(info.receivers[0].framerate_output, 0);
492 }
Stefan Holmer586b19b2015-09-18 11:14:31 +0200493
494 cricket::VideoSenderInfo GetSenderStats(size_t i) {
495 cricket::VideoMediaInfo info;
496 EXPECT_TRUE(channel_->GetStats(&info));
497 return info.senders[i];
498 }
499
500 cricket::VideoReceiverInfo GetReceiverStats(size_t i) {
501 cricket::VideoMediaInfo info;
502 EXPECT_TRUE(channel_->GetStats(&info));
503 return info.receivers[i];
504 }
505
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000506 // Test that stats work properly for a conf call with multiple recv streams.
507 void GetStatsMultipleRecvStreams() {
508 cricket::FakeVideoRenderer renderer1, renderer2;
509 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200510 cricket::VideoSendParameters parameters;
511 parameters.codecs.push_back(DefaultCodec());
Karl Wibergbe579832015-11-10 22:34:18 +0100512 parameters.options.conference_mode = rtc::Optional<bool>(true);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200513 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000514 EXPECT_TRUE(SetSend(true));
515 EXPECT_TRUE(channel_->AddRecvStream(
516 cricket::StreamParams::CreateLegacy(1)));
517 EXPECT_TRUE(channel_->AddRecvStream(
518 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800519 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
520 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521 EXPECT_EQ(0, renderer1.num_rendered_frames());
522 EXPECT_EQ(0, renderer2.num_rendered_frames());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200523 std::vector<uint32_t> ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524 ssrcs.push_back(1);
525 ssrcs.push_back(2);
526 network_interface_.SetConferenceMode(true, ssrcs);
527 EXPECT_TRUE(SendFrame());
528 EXPECT_FRAME_ON_RENDERER_WAIT(
529 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
530 EXPECT_FRAME_ON_RENDERER_WAIT(
531 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200532
533 EXPECT_TRUE(channel_->SetSend(false));
534
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000535 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000536 EXPECT_TRUE(channel_->GetStats(&info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000537 ASSERT_EQ(1U, info.senders.size());
538 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000539 // For webrtc, bytes_sent does not include the RTP header length.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200540 EXPECT_GT(GetSenderStats(0).bytes_sent, 0);
541 EXPECT_EQ_WAIT(NumRtpPackets(), GetSenderStats(0).packets_sent, kTimeout);
542 EXPECT_EQ(DefaultCodec().width, GetSenderStats(0).send_frame_width);
543 EXPECT_EQ(DefaultCodec().height, GetSenderStats(0).send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544
545 ASSERT_EQ(2U, info.receivers.size());
546 for (size_t i = 0; i < info.receivers.size(); ++i) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200547 EXPECT_EQ(1U, GetReceiverStats(i).ssrcs().size());
548 EXPECT_EQ(i + 1, GetReceiverStats(i).ssrcs()[0]);
549 EXPECT_EQ_WAIT(NumRtpBytes(), GetReceiverStats(i).bytes_rcvd, kTimeout);
550 EXPECT_EQ_WAIT(NumRtpPackets(), GetReceiverStats(i).packets_rcvd,
551 kTimeout);
552 EXPECT_EQ(DefaultCodec().width, GetReceiverStats(i).frame_width);
553 EXPECT_EQ(DefaultCodec().height, GetReceiverStats(i).frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554 }
555 }
556 // Test that stats work properly for a conf call with multiple send streams.
557 void GetStatsMultipleSendStreams() {
558 // Normal setup; note that we set the SSRC explicitly to ensure that
559 // it will come first in the senders map.
560 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200561 cricket::VideoSendParameters parameters;
562 parameters.codecs.push_back(DefaultCodec());
Karl Wibergbe579832015-11-10 22:34:18 +0100563 parameters.options.conference_mode = rtc::Optional<bool>(true);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200564 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000565 EXPECT_TRUE(channel_->AddRecvStream(
buildbot@webrtc.org99f63082014-07-18 23:31:30 +0000566 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800567 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000569 EXPECT_TRUE(SendFrame());
570 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
571 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
572
573 // Add an additional capturer, and hook up a renderer to receive it.
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000574 cricket::FakeVideoRenderer renderer2;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000575 rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000576 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000577 capturer->SetScreencast(true);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000578 const int kTestWidth = 160;
579 const int kTestHeight = 120;
580 cricket::VideoFormat format(kTestWidth, kTestHeight,
581 cricket::VideoFormat::FpsToInterval(5),
582 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
584 EXPECT_TRUE(channel_->AddSendStream(
585 cricket::StreamParams::CreateLegacy(5678)));
586 EXPECT_TRUE(channel_->SetCapturer(5678, capturer.get()));
587 EXPECT_TRUE(channel_->AddRecvStream(
588 cricket::StreamParams::CreateLegacy(5678)));
nisse08582ff2016-02-04 01:24:52 -0800589 EXPECT_TRUE(channel_->SetSink(5678, &renderer2));
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000590 EXPECT_TRUE(capturer->CaptureCustomFrame(
591 kTestWidth, kTestHeight, cricket::FOURCC_I420));
592 EXPECT_FRAME_ON_RENDERER_WAIT(
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000593 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000594
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000595 // Get stats, and make sure they are correct for two senders. We wait until
596 // the number of expected packets have been sent to avoid races where we
597 // check stats before it has been updated.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000598 cricket::VideoMediaInfo info;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200599 for (uint32_t i = 0; i < kTimeout; ++i) {
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000600 rtc::Thread::Current()->ProcessMessages(1);
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000601 EXPECT_TRUE(channel_->GetStats(&info));
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000602 ASSERT_EQ(2U, info.senders.size());
603 if (info.senders[0].packets_sent + info.senders[1].packets_sent ==
604 NumRtpPackets()) {
605 // Stats have been updated for both sent frames, expectations can be
606 // checked now.
607 break;
608 }
609 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610 EXPECT_EQ(NumRtpPackets(),
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000611 info.senders[0].packets_sent + info.senders[1].packets_sent)
612 << "Timed out while waiting for packet counts for all sent packets.";
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000613 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
614 EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000615 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
616 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000617 EXPECT_EQ(1U, info.senders[1].ssrcs().size());
618 EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000619 EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width);
620 EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621 // The capturer must be unregistered here as it runs out of it's scope next.
622 EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
623 }
624
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000625 // Test that we can set the bandwidth.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 void SetSendBandwidth() {
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200627 cricket::VideoSendParameters parameters;
628 parameters.codecs.push_back(DefaultCodec());
629 parameters.max_bandwidth_bps = -1; // <= 0 means unlimited.
630 EXPECT_TRUE(channel_->SetSendParameters(parameters));
631 parameters.max_bandwidth_bps = 128 * 1024;
632 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000633 }
634 // Test that we can set the SSRC for the default send source.
635 void SetSendSsrc() {
636 EXPECT_TRUE(SetDefaultCodec());
637 EXPECT_TRUE(SetSend(true));
638 EXPECT_TRUE(SendFrame());
639 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200640 uint32_t ssrc = 0;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000641 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000642 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
643 EXPECT_EQ(kSsrc, ssrc);
Peter Boström718b6c72015-11-11 16:19:33 +0000644 // Packets are being paced out, so these can mismatch between the first and
645 // second call to NumRtpPackets until pending packets are paced out.
646 EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
647 EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000648 EXPECT_EQ(1, NumSentSsrcs());
649 EXPECT_EQ(0, NumRtpPackets(kSsrc - 1));
650 EXPECT_EQ(0, NumRtpBytes(kSsrc - 1));
651 }
652 // Test that we can set the SSRC even after codecs are set.
653 void SetSendSsrcAfterSetCodecs() {
654 // Remove stream added in Setup.
655 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
656 EXPECT_TRUE(SetDefaultCodec());
657 EXPECT_TRUE(channel_->AddSendStream(
658 cricket::StreamParams::CreateLegacy(999)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000659 EXPECT_TRUE(channel_->SetCapturer(999u, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660 EXPECT_TRUE(SetSend(true));
661 EXPECT_TRUE(WaitAndSendFrame(0));
662 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200663 uint32_t ssrc = 0;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000664 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000665 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
666 EXPECT_EQ(999u, ssrc);
Peter Boström718b6c72015-11-11 16:19:33 +0000667 // Packets are being paced out, so these can mismatch between the first and
668 // second call to NumRtpPackets until pending packets are paced out.
669 EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
670 EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000671 EXPECT_EQ(1, NumSentSsrcs());
672 EXPECT_EQ(0, NumRtpPackets(kSsrc));
673 EXPECT_EQ(0, NumRtpBytes(kSsrc));
674 }
675 // Test that we can set the default video renderer before and after
676 // media is received.
nisse08582ff2016-02-04 01:24:52 -0800677 void SetSink() {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200678 uint8_t data1[] = {
679 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000681 rtc::Buffer packet1(data1, sizeof(data1));
682 rtc::SetBE32(packet1.data() + 8, kSsrc);
nisse08582ff2016-02-04 01:24:52 -0800683 channel_->SetSink(kDefaultReceiveSsrc, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 EXPECT_TRUE(SetDefaultCodec());
685 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000687 channel_->OnPacketReceived(&packet1, rtc::PacketTime());
nisse08582ff2016-02-04 01:24:52 -0800688 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 EXPECT_TRUE(SendFrame());
690 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
691 }
692
693 // Tests empty StreamParams is rejected.
694 void RejectEmptyStreamParams() {
695 // Remove the send stream that was added during Setup.
696 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
697
698 cricket::StreamParams empty;
699 EXPECT_FALSE(channel_->AddSendStream(empty));
700 EXPECT_TRUE(channel_->AddSendStream(
701 cricket::StreamParams::CreateLegacy(789u)));
702 }
703
704 // Tests setting up and configuring a send stream.
705 void AddRemoveSendStreams() {
706 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
707 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800708 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709 EXPECT_TRUE(SendFrame());
710 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200711 EXPECT_GT(NumRtpPackets(), 0);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200712 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 size_t last_packet = NumRtpPackets() - 1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000714 rtc::scoped_ptr<const rtc::Buffer>
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000715 p(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
717 EXPECT_EQ(kSsrc, ssrc);
718
719 // Remove the send stream that was added during Setup.
720 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
721 int rtp_packets = NumRtpPackets();
722
723 EXPECT_TRUE(channel_->AddSendStream(
724 cricket::StreamParams::CreateLegacy(789u)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000725 EXPECT_TRUE(channel_->SetCapturer(789u, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000726 EXPECT_EQ(rtp_packets, NumRtpPackets());
727 // Wait 30ms to guarantee the engine does not drop the frame.
728 EXPECT_TRUE(WaitAndSendFrame(30));
729 EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
730
731 last_packet = NumRtpPackets() - 1;
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000732 p.reset(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000733 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
734 EXPECT_EQ(789u, ssrc);
735 }
736
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000737 // Tests the behavior of incoming streams in a conference scenario.
738 void SimulateConference() {
739 cricket::FakeVideoRenderer renderer1, renderer2;
740 EXPECT_TRUE(SetDefaultCodec());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200741 cricket::VideoSendParameters parameters;
742 parameters.codecs.push_back(DefaultCodec());
Karl Wibergbe579832015-11-10 22:34:18 +0100743 parameters.options.conference_mode = rtc::Optional<bool>(true);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200744 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000745 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 EXPECT_TRUE(channel_->AddRecvStream(
747 cricket::StreamParams::CreateLegacy(1)));
748 EXPECT_TRUE(channel_->AddRecvStream(
749 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800750 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
751 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000752 EXPECT_EQ(0, renderer1.num_rendered_frames());
753 EXPECT_EQ(0, renderer2.num_rendered_frames());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200754 std::vector<uint32_t> ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000755 ssrcs.push_back(1);
756 ssrcs.push_back(2);
757 network_interface_.SetConferenceMode(true, ssrcs);
758 EXPECT_TRUE(SendFrame());
759 EXPECT_FRAME_ON_RENDERER_WAIT(
760 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
761 EXPECT_FRAME_ON_RENDERER_WAIT(
762 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
763
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000764 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000765 EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
766 EXPECT_EQ(DefaultCodec().width, renderer1.width());
767 EXPECT_EQ(DefaultCodec().height, renderer1.height());
768 EXPECT_EQ(DefaultCodec().width, renderer2.width());
769 EXPECT_EQ(DefaultCodec().height, renderer2.height());
770 EXPECT_TRUE(channel_->RemoveRecvStream(2));
771 EXPECT_TRUE(channel_->RemoveRecvStream(1));
772 }
773
774 // Tests that we can add and remove capturers and frames are sent out properly
775 void AddRemoveCapturer() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000776 cricket::VideoCodec codec = DefaultCodec();
777 codec.width = 320;
778 codec.height = 240;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000779 const int time_between_send = TimeBetweenSend(codec);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000780 EXPECT_TRUE(SetOneCodec(codec));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800782 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783 EXPECT_EQ(0, renderer_.num_rendered_frames());
784 EXPECT_TRUE(SendFrame());
785 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000786 rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000787 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788 capturer->SetScreencast(true);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000789 cricket::VideoFormat format(480, 360,
790 cricket::VideoFormat::FpsToInterval(30),
791 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000792 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
793 // All capturers start generating frames with the same timestamp. ViE does
794 // not allow the same timestamp to be used. Capture one frame before
795 // associating the capturer with the channel.
796 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
797 cricket::FOURCC_I420));
798
799 int captured_frames = 1;
800 for (int iterations = 0; iterations < 2; ++iterations) {
801 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000802 rtc::Thread::Current()->ProcessMessages(time_between_send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
804 cricket::FOURCC_I420));
805 ++captured_frames;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000806 // Wait until frame of right size is captured.
807 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
808 format.width == renderer_.width() &&
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000809 format.height == renderer_.height() &&
810 !renderer_.black_frame(), kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000811 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
812 EXPECT_EQ(format.width, renderer_.width());
813 EXPECT_EQ(format.height, renderer_.height());
814 captured_frames = renderer_.num_rendered_frames() + 1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000815 EXPECT_FALSE(renderer_.black_frame());
816 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000817 // Make sure a black frame is generated within the specified timeout.
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000818 // The black frame should be the resolution of the previous frame to
819 // prevent expensive encoder reconfigurations.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000820 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000821 format.width == renderer_.width() &&
822 format.height == renderer_.height() &&
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000823 renderer_.black_frame(), kTimeout);
824 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000825 EXPECT_EQ(format.width, renderer_.width());
826 EXPECT_EQ(format.height, renderer_.height());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000827 EXPECT_TRUE(renderer_.black_frame());
828
829 // The black frame has the same timestamp as the next frame since it's
830 // timestamp is set to the last frame's timestamp + interval. WebRTC will
831 // not render a frame with the same timestamp so capture another frame
832 // with the frame capturer to increment the next frame's timestamp.
833 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
834 cricket::FOURCC_I420));
835 }
836 }
837
838 // Tests that if RemoveCapturer is called without a capturer ever being
839 // added, the plugin shouldn't crash (and no black frame should be sent).
840 void RemoveCapturerWithoutAdd() {
841 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
842 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800843 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000844 EXPECT_EQ(0, renderer_.num_rendered_frames());
845 EXPECT_TRUE(SendFrame());
846 EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000847 // Wait for one frame so they don't get dropped because we send frames too
848 // tightly.
849 rtc::Thread::Current()->ProcessMessages(30);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000850 // Remove the capturer.
851 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000852 // Wait for one black frame for removing the capturer.
853 EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
854
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000855 // No capturer was added, so this RemoveCapturer should
856 // fail.
857 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000858 rtc::Thread::Current()->ProcessMessages(300);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000859 // Verify no more frames were sent.
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000860 EXPECT_EQ(2, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 }
862
863 // Tests that we can add and remove capturer as unique sources.
864 void AddRemoveCapturerMultipleSources() {
865 // WebRTC implementation will drop frames if pushed to quickly. Wait the
866 // interval time to avoid that.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000867 // WebRTC implementation will drop frames if pushed to quickly. Wait the
868 // interval time to avoid that.
869 // Set up the stream associated with the engine.
870 EXPECT_TRUE(channel_->AddRecvStream(
871 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800872 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000873 cricket::VideoFormat capture_format; // default format
874 capture_format.interval = cricket::VideoFormat::FpsToInterval(30);
875 // Set up additional stream 1.
876 cricket::FakeVideoRenderer renderer1;
nisse08582ff2016-02-04 01:24:52 -0800877 EXPECT_FALSE(channel_->SetSink(1, &renderer1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000878 EXPECT_TRUE(channel_->AddRecvStream(
879 cricket::StreamParams::CreateLegacy(1)));
nisse08582ff2016-02-04 01:24:52 -0800880 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000881 EXPECT_TRUE(channel_->AddSendStream(
882 cricket::StreamParams::CreateLegacy(1)));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000883 rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer1(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000884 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000885 capturer1->SetScreencast(true);
886 EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format));
887 // Set up additional stream 2.
888 cricket::FakeVideoRenderer renderer2;
nisse08582ff2016-02-04 01:24:52 -0800889 EXPECT_FALSE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000890 EXPECT_TRUE(channel_->AddRecvStream(
891 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800892 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000893 EXPECT_TRUE(channel_->AddSendStream(
894 cricket::StreamParams::CreateLegacy(2)));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000895 rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer2(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000896 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000897 capturer2->SetScreencast(true);
898 EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
899 // State for all the streams.
900 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
901 // A limitation in the lmi implementation requires that SetCapturer() is
902 // called after SetOneCodec().
903 // TODO(hellner): this seems like an unnecessary constraint, fix it.
904 EXPECT_TRUE(channel_->SetCapturer(1, capturer1.get()));
905 EXPECT_TRUE(channel_->SetCapturer(2, capturer2.get()));
906 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907 // Test capturer associated with engine.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000908 const int kTestWidth = 160;
909 const int kTestHeight = 120;
910 EXPECT_TRUE(capturer1->CaptureCustomFrame(
911 kTestWidth, kTestHeight, cricket::FOURCC_I420));
912 EXPECT_FRAME_ON_RENDERER_WAIT(
913 renderer1, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000914 // Capture a frame with additional capturer2, frames should be received
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000915 EXPECT_TRUE(capturer2->CaptureCustomFrame(
916 kTestWidth, kTestHeight, cricket::FOURCC_I420));
917 EXPECT_FRAME_ON_RENDERER_WAIT(
918 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000919 // Successfully remove the capturer.
920 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
921 // Fail to re-remove the capturer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000922 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
923 // The capturers must be unregistered here as it runs out of it's scope
924 // next.
925 EXPECT_TRUE(channel_->SetCapturer(1, NULL));
926 EXPECT_TRUE(channel_->SetCapturer(2, NULL));
927 }
928
929 void HighAspectHighHeightCapturer() {
930 const int kWidth = 80;
931 const int kHeight = 10000;
932 const int kScaledWidth = 20;
933 const int kScaledHeight = 2500;
934
935 cricket::VideoCodec codec(DefaultCodec());
936 EXPECT_TRUE(SetOneCodec(codec));
937 EXPECT_TRUE(SetSend(true));
938
939 cricket::FakeVideoRenderer renderer;
940 EXPECT_TRUE(channel_->AddRecvStream(
941 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800942 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 EXPECT_EQ(0, renderer.num_rendered_frames());
944
945 EXPECT_TRUE(SendFrame());
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000946 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
947 renderer, 1, codec.width, codec.height, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000948
949 // Registering an external capturer is currently the same as screen casting
950 // (update the test when this changes).
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000951 rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000952 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953 capturer->SetScreencast(true);
954 const std::vector<cricket::VideoFormat>* formats =
955 capturer->GetSupportedFormats();
956 cricket::VideoFormat capture_format = (*formats)[0];
957 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format));
958 // Capture frame to not get same frame timestamps as previous capturer.
959 capturer->CaptureFrame();
960 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000961 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000962 EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
963 cricket::FOURCC_ARGB));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000964 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
965 renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000966 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
967 }
968
969 // Tests that we can adapt video resolution with 16:10 aspect ratio properly.
970 void AdaptResolution16x10() {
nisse08582ff2016-02-04 01:24:52 -0800971 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000972 cricket::VideoCodec codec(DefaultCodec());
973 codec.width = 640;
974 codec.height = 400;
975 SendAndReceive(codec);
976 codec.width /= 2;
977 codec.height /= 2;
978 // Adapt the resolution.
979 EXPECT_TRUE(SetOneCodec(codec));
980 EXPECT_TRUE(WaitAndSendFrame(30));
981 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
982 }
983 // Tests that we can adapt video resolution with 4:3 aspect ratio properly.
984 void AdaptResolution4x3() {
nisse08582ff2016-02-04 01:24:52 -0800985 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 cricket::VideoCodec codec(DefaultCodec());
987 codec.width = 640;
988 codec.height = 400;
989 SendAndReceive(codec);
990 codec.width /= 2;
991 codec.height /= 2;
992 // Adapt the resolution.
993 EXPECT_TRUE(SetOneCodec(codec));
994 EXPECT_TRUE(WaitAndSendFrame(30));
995 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
996 }
997 // Tests that we can drop all frames properly.
998 void AdaptDropAllFrames() {
999 // Set the channel codec's resolution to 0, which will require the adapter
1000 // to drop all frames.
1001 cricket::VideoCodec codec(DefaultCodec());
1002 codec.width = codec.height = codec.framerate = 0;
1003 EXPECT_TRUE(SetOneCodec(codec));
1004 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -08001005 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001006 EXPECT_EQ(0, renderer_.num_rendered_frames());
1007 EXPECT_TRUE(SendFrame());
1008 EXPECT_TRUE(SendFrame());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001009 rtc::Thread::Current()->ProcessMessages(500);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001010 EXPECT_EQ(0, renderer_.num_rendered_frames());
1011 }
1012 // Tests that we can reduce the frame rate on demand properly.
1013 // TODO(fbarchard): This test is flakey on pulse. Fix and re-enable
1014 void AdaptFramerate() {
1015 cricket::VideoCodec codec(DefaultCodec());
1016 int frame_count = 0;
1017 // The capturer runs at 30 fps. The channel requires 30 fps.
1018 EXPECT_TRUE(SetOneCodec(codec));
1019 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001020 EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1021 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1022 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1023 frame_count += 2;
1024 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001025 rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001026 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
1027
1028 // The channel requires 15 fps.
1029 codec.framerate = 15;
1030 EXPECT_TRUE(SetOneCodec(codec));
1031 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1032 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1033 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1034 frame_count += 2;
1035 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1036
1037 // The channel requires 10 fps.
1038 codec.framerate = 10;
1039 EXPECT_TRUE(SetOneCodec(codec));
1040 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1041 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1042 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1043 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1044 frame_count += 2;
1045 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1046
1047 // The channel requires 8 fps. The adapter adapts to 10 fps, which is the
1048 // closest factor of 30.
1049 codec.framerate = 8;
1050 EXPECT_TRUE(SetOneCodec(codec));
1051 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1052 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1053 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1054 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1055 frame_count += 2;
1056 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1057 }
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001058 // Tests that adapted frames won't be upscaled to a higher resolution.
1059 void SendsLowerResolutionOnSmallerFrames() {
1060 cricket::VideoCodec codec = DefaultCodec();
1061 codec.width = 320;
1062 codec.height = 240;
1063 EXPECT_TRUE(SetOneCodec(codec));
1064 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -08001065 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001066 EXPECT_EQ(0, renderer_.num_rendered_frames());
1067 EXPECT_TRUE(SendFrame());
1068 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
1069
1070 // Check that we send smaller frames at the new resolution.
pbos@webrtc.orgebee4012014-09-03 15:52:02 +00001071 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(33));
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001072 EXPECT_TRUE(video_capturer_->CaptureCustomFrame(
1073 codec.width / 2, codec.height / 2, cricket::FOURCC_I420));
1074 EXPECT_FRAME_WAIT(2, codec.width / 2, codec.height / 2, kTimeout);
1075 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001076
1077 // Tests that we can mute and unmute the channel properly.
1078 void MuteStream() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001079 EXPECT_TRUE(SetDefaultCodec());
1080 cricket::FakeVideoCapturer video_capturer;
1081 video_capturer.Start(
1082 cricket::VideoFormat(
1083 640, 480,
1084 cricket::VideoFormat::FpsToInterval(30),
1085 cricket::FOURCC_I420));
1086 EXPECT_TRUE(channel_->SetCapturer(kSsrc, &video_capturer));
1087 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -08001088 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
buildbot@webrtc.org99f63082014-07-18 23:31:30 +00001089 EXPECT_EQ(0, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001090 // Mute the channel and expect black output frame.
buildbot@webrtc.org99f63082014-07-18 23:31:30 +00001091 int frame_count = 0;
solenbergdfc8f4f2015-10-01 02:31:10 -07001092 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093 EXPECT_TRUE(video_capturer.CaptureFrame());
1094 ++frame_count;
1095 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1096 EXPECT_TRUE(renderer_.black_frame());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001097 // Unmute the channel and expect non-black output frame.
solenbergdfc8f4f2015-10-01 02:31:10 -07001098 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001099 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001100 EXPECT_TRUE(video_capturer.CaptureFrame());
1101 ++frame_count;
1102 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1103 EXPECT_FALSE(renderer_.black_frame());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104 // Test that we can also Mute using the correct send stream SSRC.
solenbergdfc8f4f2015-10-01 02:31:10 -07001105 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001106 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001107 EXPECT_TRUE(video_capturer.CaptureFrame());
1108 ++frame_count;
1109 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1110 EXPECT_TRUE(renderer_.black_frame());
solenbergdfc8f4f2015-10-01 02:31:10 -07001111 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001112 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001113 EXPECT_TRUE(video_capturer.CaptureFrame());
1114 ++frame_count;
1115 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1116 EXPECT_FALSE(renderer_.black_frame());
pbos@webrtc.orgef8bb8d2014-08-13 21:36:18 +00001117 // Test that muting an existing stream succeeds even if it's muted.
solenbergdfc8f4f2015-10-01 02:31:10 -07001118 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
1119 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
pbos@webrtc.orgef8bb8d2014-08-13 21:36:18 +00001120 // Test that unmuting an existing stream succeeds even if it's not muted.
solenbergdfc8f4f2015-10-01 02:31:10 -07001121 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
1122 EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001123 // Test that muting an invalid stream fails.
solenbergdfc8f4f2015-10-01 02:31:10 -07001124 EXPECT_FALSE(channel_->SetVideoSend(kSsrc+1, false, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001125 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1126 }
1127
1128 // Test that multiple send streams can be created and deleted properly.
1129 void MultipleSendStreams() {
1130 // Remove stream added in Setup. I.e. remove stream corresponding to default
1131 // channel.
1132 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1133 const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]);
1134 for (unsigned int i = 0; i < kSsrcsSize; ++i) {
1135 EXPECT_TRUE(channel_->AddSendStream(
1136 cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
1137 }
1138 // Delete one of the non default channel streams, let the destructor delete
1139 // the remaining ones.
1140 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1141 // Stream should already be deleted.
1142 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1143 }
1144
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001145 // Two streams one channel tests.
1146
1147 // Tests that we can send and receive frames.
1148 void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) {
1149 SetUpSecondStream();
1150 // Test sending and receiving on first stream.
1151 SendAndReceive(codec);
1152 // Test sending and receiving on second stream.
1153 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +02001154 EXPECT_GT(NumRtpPackets(), 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001155 EXPECT_EQ(1, renderer2_.num_rendered_frames());
1156 }
1157
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001158 // Set up 2 streams where the first stream uses the default channel.
1159 // Then disconnect the first stream and verify default channel becomes
1160 // available.
1161 // Then add a new stream with |new_ssrc|. The new stream should re-use the
1162 // default channel.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163 void TwoStreamsReUseFirstStream(const cricket::VideoCodec& codec) {
1164 SetUpSecondStream();
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001165 // Default channel used by the first stream.
buildbot@webrtc.org2c0fb052014-08-13 16:47:12 +00001166 EXPECT_EQ(kSsrc, channel_->GetDefaultSendChannelSsrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001167 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc));
1168 EXPECT_FALSE(channel_->RemoveRecvStream(kSsrc));
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001169 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170 EXPECT_FALSE(channel_->RemoveSendStream(kSsrc));
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001171 // Default channel is no longer used by a stream.
buildbot@webrtc.org2c0fb052014-08-13 16:47:12 +00001172 EXPECT_EQ(0u, channel_->GetDefaultSendChannelSsrc());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001173 uint32_t new_ssrc = kSsrc + 100;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174 EXPECT_TRUE(channel_->AddSendStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001175 cricket::StreamParams::CreateLegacy(new_ssrc)));
1176 // Re-use default channel.
buildbot@webrtc.org2c0fb052014-08-13 16:47:12 +00001177 EXPECT_EQ(new_ssrc, channel_->GetDefaultSendChannelSsrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 EXPECT_FALSE(channel_->AddSendStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001179 cricket::StreamParams::CreateLegacy(new_ssrc)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 EXPECT_TRUE(channel_->AddRecvStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001181 cricket::StreamParams::CreateLegacy(new_ssrc)));
nisse08582ff2016-02-04 01:24:52 -08001182 EXPECT_TRUE(channel_->SetSink(new_ssrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001183 EXPECT_FALSE(channel_->AddRecvStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001184 cricket::StreamParams::CreateLegacy(new_ssrc)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001186 EXPECT_TRUE(channel_->SetCapturer(new_ssrc, video_capturer_.get()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001187
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001188 SendAndReceive(codec);
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001189 EXPECT_TRUE(channel_->RemoveSendStream(new_ssrc));
buildbot@webrtc.org2c0fb052014-08-13 16:47:12 +00001190 EXPECT_EQ(0u, channel_->GetDefaultSendChannelSsrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001191 }
1192
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001193 const rtc::scoped_ptr<webrtc::Call> call_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001194 VideoEngineOverride<E> engine_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001195 rtc::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_;
1196 rtc::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
1197 rtc::scoped_ptr<C> channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001198 cricket::FakeNetworkInterface network_interface_;
1199 cricket::FakeVideoRenderer renderer_;
1200 cricket::VideoMediaChannel::Error media_error_;
1201
1202 // Used by test cases where 2 streams are run on the same channel.
1203 cricket::FakeVideoRenderer renderer2_;
1204};
1205
kjellandera96e2d72016-02-04 23:52:28 -08001206#endif // WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT