blob: d0f84014e0dfa5ecdbc3e9d75fdce75e3fff2e28 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001// libjingle
2// Copyright 2004 Google Inc. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// 3. The name of the author may not be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
wu@webrtc.orgcadf9042013-08-30 21:24:16 +000026#ifndef TALK_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ // NOLINT
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027#define TALK_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_
28
29#include <string>
30#include <vector>
31
32#include "talk/base/bytebuffer.h"
33#include "talk/base/gunit.h"
34#include "talk/base/timeutils.h"
35#include "talk/media/base/fakenetworkinterface.h"
36#include "talk/media/base/fakevideocapturer.h"
37#include "talk/media/base/fakevideorenderer.h"
38#include "talk/media/base/mediachannel.h"
39#include "talk/media/base/streamparams.h"
40
41#ifdef WIN32
42#include <objbase.h> // NOLINT
43#endif
44
45#define EXPECT_FRAME_WAIT(c, w, h, t) \
46 EXPECT_EQ_WAIT((c), renderer_.num_rendered_frames(), (t)); \
47 EXPECT_EQ((w), renderer_.width()); \
48 EXPECT_EQ((h), renderer_.height()); \
49 EXPECT_EQ(0, renderer_.errors()); \
50
51#define EXPECT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
52 EXPECT_EQ_WAIT((c), (r).num_rendered_frames(), (t)); \
53 EXPECT_EQ((w), (r).width()); \
54 EXPECT_EQ((h), (r).height()); \
55 EXPECT_EQ(0, (r).errors()); \
56
wu@webrtc.org9caf2762013-12-11 18:25:07 +000057#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
58 EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
59 (w) == (r).width() && \
60 (h) == (r).height(), (t)); \
61 EXPECT_EQ(0, (r).errors()); \
62
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063static const uint32 kTimeout = 5000U;
64static const uint32 kSsrc = 1234u;
65static const uint32 kRtxSsrc = 4321u;
66static const uint32 kSsrcs4[] = {1, 2, 3, 4};
67
68inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) {
69 return a.width == w && a.height == h && a.framerate == fps;
70}
71
72inline bool IsEqualCodec(const cricket::VideoCodec& a,
73 const cricket::VideoCodec& b) {
74 return a.id == b.id && a.name == b.name &&
75 IsEqualRes(a, b.width, b.height, b.framerate);
76}
77
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000078namespace std {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
80 s << "{" << c.name << "(" << c.id << "), "
81 << c.width << "x" << c.height << "x" << c.framerate << "}";
82 return s;
83}
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000084} // namespace std
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085
86inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000087 return static_cast<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 cricket::VideoFormat::FpsToInterval(codec.framerate) /
89 talk_base::kNumNanosecsPerMillisec);
90}
91
92// Fake video engine that makes it possible to test enabling and disabling
93// capturer (checking that the engine state is updated and that the capturer
94// is indeed capturing) without having to create a channel. It also makes it
95// possible to test that the media processors are indeed being called when
96// registered.
97template<class T>
98class VideoEngineOverride : public T {
99 public:
100 VideoEngineOverride() {
101 }
102 virtual ~VideoEngineOverride() {
103 }
104 bool is_camera_on() const { return T::GetVideoCapturer()->IsRunning(); }
105 void set_has_senders(bool has_senders) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000106 cricket::VideoCapturer* video_capturer = T::GetVideoCapturer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107 if (has_senders) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000108 video_capturer->SignalVideoFrame.connect(this,
109 &VideoEngineOverride<T>::OnLocalFrame);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000111 video_capturer->SignalVideoFrame.disconnect(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112 }
113 }
114 void OnLocalFrame(cricket::VideoCapturer*,
115 const cricket::VideoFrame*) {
116 }
117 void OnLocalFrameFormat(cricket::VideoCapturer*,
118 const cricket::VideoFormat*) {
119 }
120
121 void TriggerMediaFrame(
122 uint32 ssrc, cricket::VideoFrame* frame, bool* drop_frame) {
123 T::SignalMediaFrame(ssrc, frame, drop_frame);
124 }
125};
126
127// Macroes that declare test functions for a given test class, before and after
128// Init().
129// To use, define a test function called FooBody and pass Foo to the macro.
130#define TEST_PRE_VIDEOENGINE_INIT(TestClass, func) \
131 TEST_F(TestClass, func##PreInit) { \
132 func##Body(); \
133 }
134#define TEST_POST_VIDEOENGINE_INIT(TestClass, func) \
135 TEST_F(TestClass, func##PostInit) { \
136 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); \
137 func##Body(); \
138 engine_.Terminate(); \
139 }
140
141template<class E>
142class VideoEngineTest : public testing::Test {
143 protected:
144 // Tests starting and stopping the engine, and creating a channel.
145 void StartupShutdown() {
146 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
147 cricket::VideoMediaChannel* channel = engine_.CreateChannel(NULL);
148 EXPECT_TRUE(channel != NULL);
149 delete channel;
150 engine_.Terminate();
151 }
152
153#ifdef WIN32
154 // Tests that the COM reference count is not munged by the engine.
155 // Test to make sure LMI does not munge the CoInitialize reference count.
156 void CheckCoInitialize() {
157 // Initial refcount should be 0.
158 EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
159
160 // Engine should start even with COM already inited.
161 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
162 engine_.Terminate();
163 // Refcount after terminate should be 1; this tests if it is nonzero.
164 EXPECT_EQ(S_FALSE, CoInitializeEx(NULL, COINIT_MULTITHREADED));
165 // Decrement refcount to (hopefully) 0.
166 CoUninitialize();
167 CoUninitialize();
168
169 // Ensure refcount is 0.
170 EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
171 CoUninitialize();
172 }
173#endif
174
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175 void ConstrainNewCodecBody() {
176 cricket::VideoCodec empty, in, out;
177 cricket::VideoCodec max_settings(engine_.codecs()[0].id,
178 engine_.codecs()[0].name,
179 1280, 800, 30, 0);
180
buildbot@webrtc.orgb92f6f92014-07-14 18:22:37 +0000181 // set max settings of 1280x800x30
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182 EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
183 cricket::VideoEncoderConfig(max_settings)));
184
185 // don't constrain the max resolution
186 in = max_settings;
187 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
188 EXPECT_PRED2(IsEqualCodec, out, in);
189
190 // constrain resolution greater than the max and wider aspect,
191 // picking best aspect (16:10)
192 in.width = 1380;
193 in.height = 800;
194 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
195 EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
196
197 // constrain resolution greater than the max and narrow aspect,
198 // picking best aspect (16:9)
199 in.width = 1280;
200 in.height = 740;
201 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
202 EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
203
204 // constrain resolution greater than the max, picking equal aspect (4:3)
205 in.width = 1280;
206 in.height = 960;
207 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
208 EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
209
210 // constrain resolution greater than the max, picking equal aspect (16:10)
211 in.width = 1280;
212 in.height = 800;
213 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
214 EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
215
216 // reduce max settings to 640x480x30
217 max_settings.width = 640;
218 max_settings.height = 480;
219 EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
220 cricket::VideoEncoderConfig(max_settings)));
221
222 // don't constrain the max resolution
223 in = max_settings;
224 in.width = 640;
225 in.height = 480;
226 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
227 EXPECT_PRED2(IsEqualCodec, out, in);
228
229 // keep 16:10 if they request it
230 in.height = 400;
231 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
232 EXPECT_PRED2(IsEqualCodec, out, in);
233
234 // don't constrain lesser 4:3 resolutions
235 in.width = 320;
236 in.height = 240;
237 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
238 EXPECT_PRED2(IsEqualCodec, out, in);
239
240 // don't constrain lesser 16:10 resolutions
241 in.width = 320;
242 in.height = 200;
243 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
244 EXPECT_PRED2(IsEqualCodec, out, in);
245
246 // requested resolution of 0x0 succeeds
247 in.width = 0;
248 in.height = 0;
249 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
250 EXPECT_PRED2(IsEqualCodec, out, in);
251
252 // constrain resolution lesser than the max and wider aspect,
253 // picking best aspect (16:9)
254 in.width = 350;
255 in.height = 201;
256 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
257 EXPECT_PRED4(IsEqualRes, out, 320, 180, 30);
258
259 // constrain resolution greater than the max and narrow aspect,
260 // picking best aspect (4:3)
261 in.width = 350;
262 in.height = 300;
263 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
264 EXPECT_PRED4(IsEqualRes, out, 320, 240, 30);
265
266 // constrain resolution greater than the max and wider aspect,
267 // picking best aspect (16:9)
268 in.width = 1380;
269 in.height = 800;
270 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
271 EXPECT_PRED4(IsEqualRes, out, 640, 360, 30);
272
273 // constrain resolution greater than the max and narrow aspect,
274 // picking best aspect (4:3)
275 in.width = 1280;
276 in.height = 900;
277 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
278 EXPECT_PRED4(IsEqualRes, out, 640, 480, 30);
279
280 // constrain resolution greater than the max, picking equal aspect (4:3)
281 in.width = 1280;
282 in.height = 960;
283 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
284 EXPECT_PRED4(IsEqualRes, out, 640, 480, 30);
285
286 // constrain resolution greater than the max, picking equal aspect (16:10)
287 in.width = 1280;
288 in.height = 800;
289 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
290 EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
291
292 // constrain res & fps greater than the max
293 in.framerate = 50;
294 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
295 EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
296
297 // reduce max settings to 160x100x10
298 max_settings.width = 160;
299 max_settings.height = 100;
300 max_settings.framerate = 10;
301 EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
302 cricket::VideoEncoderConfig(max_settings)));
303
304 // constrain res & fps to new max
305 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
306 EXPECT_PRED4(IsEqualRes, out, 160, 100, 10);
307
308 // allow 4:3 "comparable" resolutions
309 in.width = 160;
310 in.height = 120;
311 in.framerate = 10;
312 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
313 EXPECT_PRED4(IsEqualRes, out, 160, 120, 10);
314 }
315
buildbot@webrtc.orgb92f6f92014-07-14 18:22:37 +0000316 // This is the new way of constraining codec size, where we no longer maintain
317 // a list of the supported formats. Instead, CanSendCodec will just downscale
318 // the resolution by 2 until the width is below clamp.
319 void ConstrainNewCodec2Body() {
320 cricket::VideoCodec empty, in, out;
321 cricket::VideoCodec max_settings(engine_.codecs()[0].id,
322 engine_.codecs()[0].name,
323 1280, 800, 30, 0);
324
325 // Set max settings of 1280x800x30
326 EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
327 cricket::VideoEncoderConfig(max_settings)));
328
329 // Don't constrain the max resolution
330 in = max_settings;
331 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
332 EXPECT_PRED2(IsEqualCodec, out, in);
333
334 // Constrain resolution greater than the max width.
335 in.width = 1380;
336 in.height = 800;
337 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
338 EXPECT_PRED4(IsEqualRes, out, 690, 400, 30);
339
340 // Don't constrain resolution when only the height is greater than max.
341 in.width = 960;
342 in.height = 1280;
343 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
344 EXPECT_PRED4(IsEqualRes, out, 960, 1280, 30);
345
346 // Don't constrain smaller format.
347 in.width = 640;
348 in.height = 480;
349 EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
350 EXPECT_PRED4(IsEqualRes, out, 640, 480, 30);
351 }
352
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000353 void ConstrainRunningCodecBody() {
354 cricket::VideoCodec in, out, current;
355 cricket::VideoCodec max_settings(engine_.codecs()[0].id,
356 engine_.codecs()[0].name,
357 1280, 800, 30, 0);
358
359 // set max settings of 1280x960x30
360 EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
361 cricket::VideoEncoderConfig(max_settings)));
362
363 // establish current call at 1280x800x30 (16:10)
364 current = max_settings;
365 current.height = 800;
366
367 // Don't constrain current resolution
368 in = current;
369 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
370 EXPECT_PRED2(IsEqualCodec, out, in);
371
372 // requested resolution of 0x0 succeeds
373 in.width = 0;
374 in.height = 0;
375 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
376 EXPECT_PRED2(IsEqualCodec, out, in);
377
378 // Reduce an intermediate resolution down to the next lowest one, preserving
379 // aspect ratio.
380 in.width = 800;
381 in.height = 600;
382 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
383 EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
384
385 // Clamping by aspect ratio, but still never return a dimension higher than
386 // requested.
387 in.width = 1280;
388 in.height = 720;
389 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
390 EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
391
392 in.width = 1279;
393 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
394 EXPECT_PRED4(IsEqualRes, out, 960, 600, 30);
395
396 in.width = 1281;
397 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
398 EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
399
400 // Clamp large resolutions down, always preserving aspect
401 in.width = 1920;
402 in.height = 1080;
403 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
404 EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
405
406 in.width = 1921;
407 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
408 EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
409
410 in.width = 1919;
411 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
412 EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
413
414 // reduce max settings to 640x480x30
415 max_settings.width = 640;
416 max_settings.height = 480;
417 EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
418 cricket::VideoEncoderConfig(max_settings)));
419
420 // establish current call at 640x400x30 (16:10)
421 current = max_settings;
422 current.height = 400;
423
424 // Don't constrain current resolution
425 in = current;
426 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
427 EXPECT_PRED2(IsEqualCodec, out, in);
428
429 // requested resolution of 0x0 succeeds
430 in.width = 0;
431 in.height = 0;
432 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
433 EXPECT_PRED2(IsEqualCodec, out, in);
434
435 // Reduce an intermediate resolution down to the next lowest one, preserving
436 // aspect ratio.
437 in.width = 400;
438 in.height = 300;
439 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
440 EXPECT_PRED4(IsEqualRes, out, 320, 200, 30);
441
442 // Clamping by aspect ratio, but still never return a dimension higher than
443 // requested.
444 in.width = 640;
445 in.height = 360;
446 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
447 EXPECT_PRED4(IsEqualRes, out, 640, 360, 30);
448
449 in.width = 639;
450 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
451 EXPECT_PRED4(IsEqualRes, out, 480, 300, 30);
452
453 in.width = 641;
454 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
455 EXPECT_PRED4(IsEqualRes, out, 640, 360, 30);
456
457 // Clamp large resolutions down, always preserving aspect
458 in.width = 1280;
459 in.height = 800;
460 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
461 EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
462
463 in.width = 1281;
464 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
465 EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
466
467 in.width = 1279;
468 EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
469 EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
470
471 // Should fail for any that are smaller than our supported formats
472 in.width = 80;
473 in.height = 80;
474 EXPECT_FALSE(engine_.CanSendCodec(in, current, &out));
475
476 in.height = 50;
477 EXPECT_FALSE(engine_.CanSendCodec(in, current, &out));
478 }
479
480 VideoEngineOverride<E> engine_;
481 talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_;
482};
483
484template<class E, class C>
485class VideoMediaChannelTest : public testing::Test,
486 public sigslot::has_slots<> {
487 protected:
488 virtual cricket::VideoCodec DefaultCodec() = 0;
489
490 virtual cricket::StreamParams DefaultSendStreamParams() {
491 return cricket::StreamParams::CreateLegacy(kSsrc);
492 }
493
494 virtual void SetUp() {
495 cricket::Device device("test", "device");
496 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000497 channel_.reset(engine_.CreateChannel(NULL));
498 EXPECT_TRUE(channel_.get() != NULL);
499 ConnectVideoChannelError();
500 network_interface_.SetDestination(channel_.get());
501 channel_->SetInterface(&network_interface_);
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +0000502 SetRendererAsDefault();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503 media_error_ = cricket::VideoMediaChannel::ERROR_NONE;
504 channel_->SetRecvCodecs(engine_.codecs());
505 EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000506
507 video_capturer_.reset(new cricket::FakeVideoCapturer);
508 cricket::VideoFormat format(640, 480,
509 cricket::VideoFormat::FpsToInterval(30),
510 cricket::FOURCC_I420);
511 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
512 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000513 }
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000514 // Utility method to setup an additional stream to send and receive video.
515 // Used to test send and recv between two streams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000516 void SetUpSecondStream() {
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000517 SetUpSecondStreamWithNoRecv();
518 // Setup recv for second stream.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519 EXPECT_TRUE(channel_->AddRecvStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000520 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000521 // Make the second renderer available for use by a new stream.
522 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_));
523 }
524 // Setup an additional stream just to send video. Defer add recv stream.
525 // This is required if you want to test unsignalled recv of video rtp packets.
526 void SetUpSecondStreamWithNoRecv() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000527 // SetUp() already added kSsrc make sure duplicate SSRCs cant be added.
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000528 EXPECT_TRUE(channel_->AddRecvStream(
529 cricket::StreamParams::CreateLegacy(kSsrc)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 EXPECT_FALSE(channel_->AddSendStream(
531 cricket::StreamParams::CreateLegacy(kSsrc)));
532 EXPECT_TRUE(channel_->AddSendStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000533 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000534 // We dont add recv for the second stream.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000535
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000536 // Setup the receive and renderer for second stream after send.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000537 video_capturer_2_.reset(new cricket::FakeVideoCapturer());
538 cricket::VideoFormat format(640, 480,
539 cricket::VideoFormat::FpsToInterval(30),
540 cricket::FOURCC_I420);
541 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
542
543 EXPECT_TRUE(channel_->SetCapturer(kSsrc + 2, video_capturer_2_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544 }
545 virtual void TearDown() {
546 channel_.reset();
547 engine_.Terminate();
548 }
549 void ConnectVideoChannelError() {
550 channel_->SignalMediaError.connect(this,
551 &VideoMediaChannelTest<E, C>::OnVideoChannelError);
552 }
553 bool SetDefaultCodec() {
554 return SetOneCodec(DefaultCodec());
555 }
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +0000556 void SetRendererAsDefault() {
557 EXPECT_TRUE(channel_->SetRenderer(0, &renderer_));
558 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000559
560 bool SetOneCodec(int pt, const char* name, int w, int h, int fr) {
561 return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0));
562 }
563 bool SetOneCodec(const cricket::VideoCodec& codec) {
564 std::vector<cricket::VideoCodec> codecs;
565 codecs.push_back(codec);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000566
567 cricket::VideoFormat capture_format(codec.width, codec.height,
568 cricket::VideoFormat::FpsToInterval(codec.framerate),
569 cricket::FOURCC_I420);
570
571 if (video_capturer_) {
572 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format));
573 }
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000574 if (video_capturer_2_) {
575 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format));
576 }
577
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578 bool sending = channel_->sending();
579 bool success = SetSend(false);
580 if (success)
581 success = channel_->SetSendCodecs(codecs);
582 if (success)
583 success = SetSend(sending);
584 return success;
585 }
586 bool SetSend(bool send) {
587 return channel_->SetSend(send);
588 }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000589 bool SetSendStreamFormat(uint32 ssrc, const cricket::VideoCodec& codec) {
590 return channel_->SetSendStreamFormat(ssrc, cricket::VideoFormat(
591 codec.width, codec.height,
592 cricket::VideoFormat::FpsToInterval(codec.framerate),
593 cricket::FOURCC_ANY));
594 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000595 int DrainOutgoingPackets() {
596 int packets = 0;
597 do {
598 packets = NumRtpPackets();
599 // 100 ms should be long enough.
600 talk_base::Thread::Current()->ProcessMessages(100);
601 } while (NumRtpPackets() > packets);
602 return NumRtpPackets();
603 }
604 bool SendFrame() {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000605 if (video_capturer_2_) {
606 video_capturer_2_->CaptureFrame();
607 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000608 return video_capturer_.get() &&
609 video_capturer_->CaptureFrame();
610 }
611 bool WaitAndSendFrame(int wait_ms) {
612 bool ret = talk_base::Thread::Current()->ProcessMessages(wait_ms);
613 ret &= SendFrame();
614 return ret;
615 }
616 // Sends frames and waits for the decoder to be fully initialized.
617 // Returns the number of frames that were sent.
618 int WaitForDecoder() {
619#if defined(HAVE_OPENMAX)
620 // Send enough frames for the OpenMAX decoder to continue processing, and
621 // return the number of frames sent.
622 // Send frames for a full kTimeout's worth of 15fps video.
623 int frame_count = 0;
624 while (frame_count < static_cast<int>(kTimeout) / 66) {
625 EXPECT_TRUE(WaitAndSendFrame(66));
626 ++frame_count;
627 }
628 return frame_count;
629#else
630 return 0;
631#endif
632 }
633 bool SendCustomVideoFrame(int w, int h) {
634 if (!video_capturer_.get()) return false;
635 return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420);
636 }
637 int NumRtpBytes() {
638 return network_interface_.NumRtpBytes();
639 }
640 int NumRtpBytes(uint32 ssrc) {
641 return network_interface_.NumRtpBytes(ssrc);
642 }
643 int NumRtpPackets() {
644 return network_interface_.NumRtpPackets();
645 }
646 int NumRtpPackets(uint32 ssrc) {
647 return network_interface_.NumRtpPackets(ssrc);
648 }
649 int NumSentSsrcs() {
650 return network_interface_.NumSentSsrcs();
651 }
652 const talk_base::Buffer* GetRtpPacket(int index) {
653 return network_interface_.GetRtpPacket(index);
654 }
655 int NumRtcpPackets() {
656 return network_interface_.NumRtcpPackets();
657 }
658 const talk_base::Buffer* GetRtcpPacket(int index) {
659 return network_interface_.GetRtcpPacket(index);
660 }
661 static int GetPayloadType(const talk_base::Buffer* p) {
662 int pt = -1;
663 ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
664 return pt;
665 }
666 static bool ParseRtpPacket(const talk_base::Buffer* p, bool* x, int* pt,
667 int* seqnum, uint32* tstamp, uint32* ssrc,
668 std::string* payload) {
669 talk_base::ByteBuffer buf(p->data(), p->length());
670 uint8 u08 = 0;
671 uint16 u16 = 0;
672 uint32 u32 = 0;
673
674 // Read X and CC fields.
675 if (!buf.ReadUInt8(&u08)) return false;
676 bool extension = ((u08 & 0x10) != 0);
677 uint8 cc = (u08 & 0x0F);
678 if (x) *x = extension;
679
680 // Read PT field.
681 if (!buf.ReadUInt8(&u08)) return false;
682 if (pt) *pt = (u08 & 0x7F);
683
684 // Read Sequence Number field.
685 if (!buf.ReadUInt16(&u16)) return false;
686 if (seqnum) *seqnum = u16;
687
688 // Read Timestamp field.
689 if (!buf.ReadUInt32(&u32)) return false;
690 if (tstamp) *tstamp = u32;
691
692 // Read SSRC field.
693 if (!buf.ReadUInt32(&u32)) return false;
694 if (ssrc) *ssrc = u32;
695
696 // Skip CSRCs.
697 for (uint8 i = 0; i < cc; ++i) {
698 if (!buf.ReadUInt32(&u32)) return false;
699 }
700
701 // Skip extension header.
702 if (extension) {
703 // Read Profile-specific extension header ID
704 if (!buf.ReadUInt16(&u16)) return false;
705
706 // Read Extension header length
707 if (!buf.ReadUInt16(&u16)) return false;
708 uint16 ext_header_len = u16;
709
710 // Read Extension header
711 for (uint16 i = 0; i < ext_header_len; ++i) {
712 if (!buf.ReadUInt32(&u32)) return false;
713 }
714 }
715
716 if (payload) {
717 return buf.ReadString(payload, buf.Length());
718 }
719 return true;
720 }
721
722 // Parse all RTCP packet, from start_index to stop_index, and count how many
723 // FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count
724 // and return true.
725 bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
726 int count = 0;
727 for (int i = start_index; i < stop_index; ++i) {
728 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtcpPacket(i));
729 talk_base::ByteBuffer buf(p->data(), p->length());
730 size_t total_len = 0;
731 // The packet may be a compound RTCP packet.
732 while (total_len < p->length()) {
733 // Read FMT, type and length.
734 uint8 fmt = 0;
735 uint8 type = 0;
736 uint16 length = 0;
737 if (!buf.ReadUInt8(&fmt)) return false;
738 fmt &= 0x1F;
739 if (!buf.ReadUInt8(&type)) return false;
740 if (!buf.ReadUInt16(&length)) return false;
741 buf.Consume(length * 4); // Skip RTCP data.
742 total_len += (length + 1) * 4;
743 if ((192 == type) || ((206 == type) && (4 == fmt))) {
744 ++count;
745 }
746 }
747 }
748
749 if (fir_count) {
750 *fir_count = count;
751 }
752 return true;
753 }
754
755 void OnVideoChannelError(uint32 ssrc,
756 cricket::VideoMediaChannel::Error error) {
757 media_error_ = error;
758 }
759
760 // Test that SetSend works.
761 void SetSend() {
762 EXPECT_FALSE(channel_->sending());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000763 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
765 EXPECT_FALSE(channel_->sending());
766 EXPECT_TRUE(SetSend(true));
767 EXPECT_TRUE(channel_->sending());
768 EXPECT_TRUE(SendFrame());
769 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
770 EXPECT_TRUE(SetSend(false));
771 EXPECT_FALSE(channel_->sending());
772 }
773 // Test that SetSend fails without codecs being set.
774 void SetSendWithoutCodecs() {
775 EXPECT_FALSE(channel_->sending());
776 EXPECT_FALSE(SetSend(true));
777 EXPECT_FALSE(channel_->sending());
778 }
779 // Test that we properly set the send and recv buffer sizes by the time
780 // SetSend is called.
781 void SetSendSetsTransportBufferSizes() {
782 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
783 EXPECT_TRUE(SetSend(true));
784 // TODO(sriniv): Remove or re-enable this.
785 // As part of b/8030474, send-buffer is size now controlled through
786 // portallocator flags. Its not set by channels.
787 // EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size());
788 EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size());
789 }
790 // Tests that we can send frames and the right payload type is used.
791 void Send(const cricket::VideoCodec& codec) {
792 EXPECT_TRUE(SetOneCodec(codec));
793 EXPECT_TRUE(SetSend(true));
794 EXPECT_TRUE(SendFrame());
795 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
796 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
797 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
798 }
799 // Tests that we can send and receive frames.
800 void SendAndReceive(const cricket::VideoCodec& codec) {
801 EXPECT_TRUE(SetOneCodec(codec));
802 EXPECT_TRUE(SetSend(true));
803 EXPECT_TRUE(channel_->SetRender(true));
804 EXPECT_EQ(0, renderer_.num_rendered_frames());
805 EXPECT_TRUE(SendFrame());
806 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
807 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
808 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
809 }
810 // Tests that we only get a VideoRenderer::SetSize() callback when needed.
811 void SendManyResizeOnce() {
812 cricket::VideoCodec codec(DefaultCodec());
813 EXPECT_TRUE(SetOneCodec(codec));
814 EXPECT_TRUE(SetSend(true));
815 EXPECT_TRUE(channel_->SetRender(true));
816 EXPECT_EQ(0, renderer_.num_rendered_frames());
817 EXPECT_TRUE(WaitAndSendFrame(30));
818 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
819 EXPECT_TRUE(WaitAndSendFrame(30));
820 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
821 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
822 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
823 EXPECT_EQ(1, renderer_.num_set_sizes());
824
825 codec.width /= 2;
826 codec.height /= 2;
827 EXPECT_TRUE(SetOneCodec(codec));
828 EXPECT_TRUE(WaitAndSendFrame(30));
829 EXPECT_FRAME_WAIT(3, codec.width, codec.height, kTimeout);
830 EXPECT_EQ(2, renderer_.num_set_sizes());
831 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000832 void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec,
833 int duration_sec, int fps) {
834 EXPECT_TRUE(SetOneCodec(codec));
835 EXPECT_TRUE(SetSend(true));
836 EXPECT_TRUE(channel_->SetRender(true));
837 EXPECT_EQ(0, renderer_.num_rendered_frames());
838 for (int i = 0; i < duration_sec; ++i) {
839 for (int frame = 1; frame <= fps; ++frame) {
840 EXPECT_TRUE(WaitAndSendFrame(1000 / fps));
841 EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout);
842 }
843 cricket::VideoMediaInfo info;
844 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
845 // For webrtc, |framerate_sent| and |framerate_rcvd| depend on periodic
846 // callbacks (1 sec).
847 // Received |fraction_lost| and |packets_lost| are from sent RTCP packet.
848 // One sent packet needed (sent about once per second).
849 // |framerate_input|, |framerate_decoded| and |framerate_output| are using
850 // RateTracker. RateTracker needs to be called twice (with >1 second in
851 // b/w calls) before a framerate is calculated.
852 // Therefore insert frames (and call GetStats each sec) for a few seconds
853 // before testing stats.
854 }
855 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
856 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
857 }
858
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 // Test that stats work properly for a 1-1 call.
860 void GetStats() {
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000861 const int kDurationSec = 3;
862 const int kFps = 10;
863 SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps);
864
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000865 cricket::VideoMediaInfo info;
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000866 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000867
868 ASSERT_EQ(1U, info.senders.size());
869 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000870 // For webrtc, bytes_sent does not include the RTP header length.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000871 EXPECT_GT(info.senders[0].bytes_sent, 0);
872 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
873 EXPECT_EQ(0.0, info.senders[0].fraction_lost);
874 EXPECT_EQ(0, info.senders[0].firs_rcvd);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000875 EXPECT_EQ(0, info.senders[0].plis_rcvd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876 EXPECT_EQ(0, info.senders[0].nacks_rcvd);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000877 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
878 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000879 EXPECT_GT(info.senders[0].framerate_input, 0);
880 EXPECT_GT(info.senders[0].framerate_sent, 0);
881
882 ASSERT_EQ(1U, info.receivers.size());
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000883 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
884 EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
885 EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000886 EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
887 EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
888 EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
889 EXPECT_EQ(0, info.receivers[0].packets_lost);
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000890 // TODO(asapersson): Not set for webrtc. Handle missing stats.
891 // EXPECT_EQ(0, info.receivers[0].packets_concealed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892 EXPECT_EQ(0, info.receivers[0].firs_sent);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000893 EXPECT_EQ(0, info.receivers[0].plis_sent);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 EXPECT_EQ(0, info.receivers[0].nacks_sent);
895 EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width);
896 EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height);
897 EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
898 EXPECT_GT(info.receivers[0].framerate_decoded, 0);
899 EXPECT_GT(info.receivers[0].framerate_output, 0);
900 }
901 // Test that stats work properly for a conf call with multiple recv streams.
902 void GetStatsMultipleRecvStreams() {
903 cricket::FakeVideoRenderer renderer1, renderer2;
904 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
905 cricket::VideoOptions vmo;
906 vmo.conference_mode.Set(true);
907 EXPECT_TRUE(channel_->SetOptions(vmo));
908 EXPECT_TRUE(SetSend(true));
909 EXPECT_TRUE(channel_->AddRecvStream(
910 cricket::StreamParams::CreateLegacy(1)));
911 EXPECT_TRUE(channel_->AddRecvStream(
912 cricket::StreamParams::CreateLegacy(2)));
913 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
914 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
915 EXPECT_TRUE(channel_->SetRender(true));
916 EXPECT_EQ(0, renderer1.num_rendered_frames());
917 EXPECT_EQ(0, renderer2.num_rendered_frames());
918 std::vector<uint32> ssrcs;
919 ssrcs.push_back(1);
920 ssrcs.push_back(2);
921 network_interface_.SetConferenceMode(true, ssrcs);
922 EXPECT_TRUE(SendFrame());
923 EXPECT_FRAME_ON_RENDERER_WAIT(
924 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
925 EXPECT_FRAME_ON_RENDERER_WAIT(
926 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
927 cricket::VideoMediaInfo info;
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000928 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000929
930 ASSERT_EQ(1U, info.senders.size());
931 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000932 // For webrtc, bytes_sent does not include the RTP header length.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 EXPECT_GT(info.senders[0].bytes_sent, 0);
934 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000935 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
936 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937
938 ASSERT_EQ(2U, info.receivers.size());
939 for (size_t i = 0; i < info.receivers.size(); ++i) {
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000940 EXPECT_EQ(1U, info.receivers[i].ssrcs().size());
941 EXPECT_EQ(i + 1, info.receivers[i].ssrcs()[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942 EXPECT_EQ(NumRtpBytes(), info.receivers[i].bytes_rcvd);
943 EXPECT_EQ(NumRtpPackets(), info.receivers[i].packets_rcvd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 EXPECT_EQ(DefaultCodec().width, info.receivers[i].frame_width);
945 EXPECT_EQ(DefaultCodec().height, info.receivers[i].frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 }
947 }
948 // Test that stats work properly for a conf call with multiple send streams.
949 void GetStatsMultipleSendStreams() {
950 // Normal setup; note that we set the SSRC explicitly to ensure that
951 // it will come first in the senders map.
952 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
953 cricket::VideoOptions vmo;
954 vmo.conference_mode.Set(true);
955 EXPECT_TRUE(channel_->SetOptions(vmo));
956 EXPECT_TRUE(channel_->AddRecvStream(
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +0000957 cricket::StreamParams::CreateLegacy(1234)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000958 channel_->UpdateAspectRatio(640, 400);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 EXPECT_TRUE(SetSend(true));
960 EXPECT_TRUE(channel_->SetRender(true));
961 EXPECT_TRUE(SendFrame());
962 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
963 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
964
965 // Add an additional capturer, and hook up a renderer to receive it.
966 cricket::FakeVideoRenderer renderer1;
967 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
968 new cricket::FakeVideoCapturer);
969 capturer->SetScreencast(true);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000970 const int kTestWidth = 160;
971 const int kTestHeight = 120;
972 cricket::VideoFormat format(kTestWidth, kTestHeight,
973 cricket::VideoFormat::FpsToInterval(5),
974 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
976 EXPECT_TRUE(channel_->AddSendStream(
977 cricket::StreamParams::CreateLegacy(5678)));
978 EXPECT_TRUE(channel_->SetCapturer(5678, capturer.get()));
979 EXPECT_TRUE(channel_->AddRecvStream(
980 cricket::StreamParams::CreateLegacy(5678)));
981 EXPECT_TRUE(channel_->SetRenderer(5678, &renderer1));
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000982 EXPECT_TRUE(capturer->CaptureCustomFrame(
983 kTestWidth, kTestHeight, cricket::FOURCC_I420));
984 EXPECT_FRAME_ON_RENDERER_WAIT(
985 renderer1, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986
987 // Get stats, and make sure they are correct for two senders.
988 cricket::VideoMediaInfo info;
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000989 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000990 ASSERT_EQ(2U, info.senders.size());
991 EXPECT_EQ(NumRtpPackets(),
992 info.senders[0].packets_sent + info.senders[1].packets_sent);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000993 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
994 EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000995 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
996 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000997 EXPECT_EQ(1U, info.senders[1].ssrcs().size());
998 EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000999 EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width);
1000 EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001 // The capturer must be unregistered here as it runs out of it's scope next.
1002 EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
1003 }
1004
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001005 // Test that we can set the bandwidth.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001006 void SetSendBandwidth() {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001007 EXPECT_TRUE(channel_->SetStartSendBandwidth(64 * 1024));
1008 EXPECT_TRUE(channel_->SetMaxSendBandwidth(-1)); // <= 0 means unlimited.
1009 EXPECT_TRUE(channel_->SetMaxSendBandwidth(128 * 1024));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001010 }
1011 // Test that we can set the SSRC for the default send source.
1012 void SetSendSsrc() {
1013 EXPECT_TRUE(SetDefaultCodec());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001014 EXPECT_TRUE(SetSendStreamFormat(kSsrc, DefaultCodec()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001015 EXPECT_TRUE(SetSend(true));
1016 EXPECT_TRUE(SendFrame());
1017 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
1018 uint32 ssrc = 0;
1019 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
1020 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
1021 EXPECT_EQ(kSsrc, ssrc);
1022 EXPECT_EQ(NumRtpPackets(), NumRtpPackets(ssrc));
1023 EXPECT_EQ(NumRtpBytes(), NumRtpBytes(ssrc));
1024 EXPECT_EQ(1, NumSentSsrcs());
1025 EXPECT_EQ(0, NumRtpPackets(kSsrc - 1));
1026 EXPECT_EQ(0, NumRtpBytes(kSsrc - 1));
1027 }
1028 // Test that we can set the SSRC even after codecs are set.
1029 void SetSendSsrcAfterSetCodecs() {
1030 // Remove stream added in Setup.
1031 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1032 EXPECT_TRUE(SetDefaultCodec());
1033 EXPECT_TRUE(channel_->AddSendStream(
1034 cricket::StreamParams::CreateLegacy(999)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001035 EXPECT_TRUE(channel_->SetCapturer(999u, video_capturer_.get()));
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001036 EXPECT_TRUE(SetSendStreamFormat(999u, DefaultCodec()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037 EXPECT_TRUE(SetSend(true));
1038 EXPECT_TRUE(WaitAndSendFrame(0));
1039 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
1040 uint32 ssrc = 0;
1041 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
1042 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
1043 EXPECT_EQ(999u, ssrc);
1044 EXPECT_EQ(NumRtpPackets(), NumRtpPackets(ssrc));
1045 EXPECT_EQ(NumRtpBytes(), NumRtpBytes(ssrc));
1046 EXPECT_EQ(1, NumSentSsrcs());
1047 EXPECT_EQ(0, NumRtpPackets(kSsrc));
1048 EXPECT_EQ(0, NumRtpBytes(kSsrc));
1049 }
1050 // Test that we can set the default video renderer before and after
1051 // media is received.
1052 void SetRenderer() {
1053 uint8 data1[] = {
1054 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1055 };
1056
1057 talk_base::Buffer packet1(data1, sizeof(data1));
1058 talk_base::SetBE32(packet1.data() + 8, kSsrc);
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001059 channel_->SetRenderer(0, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 EXPECT_TRUE(SetDefaultCodec());
1061 EXPECT_TRUE(SetSend(true));
1062 EXPECT_TRUE(channel_->SetRender(true));
1063 EXPECT_EQ(0, renderer_.num_rendered_frames());
wu@webrtc.orga9890802013-12-13 00:21:03 +00001064 channel_->OnPacketReceived(&packet1, talk_base::PacketTime());
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001065 SetRendererAsDefault();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001066 EXPECT_TRUE(SendFrame());
1067 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1068 }
1069
1070 // Tests empty StreamParams is rejected.
1071 void RejectEmptyStreamParams() {
1072 // Remove the send stream that was added during Setup.
1073 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1074
1075 cricket::StreamParams empty;
1076 EXPECT_FALSE(channel_->AddSendStream(empty));
1077 EXPECT_TRUE(channel_->AddSendStream(
1078 cricket::StreamParams::CreateLegacy(789u)));
1079 }
1080
1081 // Tests setting up and configuring a send stream.
1082 void AddRemoveSendStreams() {
1083 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
1084 EXPECT_TRUE(SetSend(true));
1085 EXPECT_TRUE(channel_->SetRender(true));
1086 EXPECT_TRUE(SendFrame());
1087 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1088 EXPECT_GE(2, NumRtpPackets());
1089 uint32 ssrc = 0;
1090 size_t last_packet = NumRtpPackets() - 1;
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001091 talk_base::scoped_ptr<const talk_base::Buffer>
1092 p(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
1094 EXPECT_EQ(kSsrc, ssrc);
1095
1096 // Remove the send stream that was added during Setup.
1097 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1098 int rtp_packets = NumRtpPackets();
1099
1100 EXPECT_TRUE(channel_->AddSendStream(
1101 cricket::StreamParams::CreateLegacy(789u)));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001102 EXPECT_TRUE(channel_->SetCapturer(789u, video_capturer_.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001103 EXPECT_EQ(rtp_packets, NumRtpPackets());
1104 // Wait 30ms to guarantee the engine does not drop the frame.
1105 EXPECT_TRUE(WaitAndSendFrame(30));
1106 EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
1107
1108 last_packet = NumRtpPackets() - 1;
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001109 p.reset(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001110 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
1111 EXPECT_EQ(789u, ssrc);
1112 }
1113
1114 // Tests adding streams already exists returns false.
1115 void AddRecvStreamsAlreadyExist() {
1116 cricket::VideoOptions vmo;
1117 vmo.conference_mode.Set(true);
1118 EXPECT_TRUE(channel_->SetOptions(vmo));
1119
1120 EXPECT_FALSE(channel_->AddRecvStream(
1121 cricket::StreamParams::CreateLegacy(0)));
1122
1123 EXPECT_TRUE(channel_->AddRecvStream(
1124 cricket::StreamParams::CreateLegacy(1)));
1125 EXPECT_FALSE(channel_->AddRecvStream(
1126 cricket::StreamParams::CreateLegacy(1)));
1127
1128 EXPECT_TRUE(channel_->RemoveRecvStream(1));
1129 EXPECT_FALSE(channel_->AddRecvStream(
1130 cricket::StreamParams::CreateLegacy(0)));
1131 EXPECT_TRUE(channel_->AddRecvStream(
1132 cricket::StreamParams::CreateLegacy(1)));
1133 }
1134
1135 // Tests setting up and configuring multiple incoming streams.
1136 void AddRemoveRecvStreams() {
1137 cricket::FakeVideoRenderer renderer1, renderer2;
1138 cricket::VideoOptions vmo;
1139 vmo.conference_mode.Set(true);
1140 EXPECT_TRUE(channel_->SetOptions(vmo));
1141 // Ensure we can't set the renderer on a non-existent stream.
1142 EXPECT_FALSE(channel_->SetRenderer(1, &renderer1));
1143 EXPECT_FALSE(channel_->SetRenderer(2, &renderer2));
1144 cricket::VideoRenderer* renderer;
1145 EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1146 EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1147
1148 // Ensure we can add streams.
1149 EXPECT_TRUE(channel_->AddRecvStream(
1150 cricket::StreamParams::CreateLegacy(1)));
1151 EXPECT_TRUE(channel_->AddRecvStream(
1152 cricket::StreamParams::CreateLegacy(2)));
1153 EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001154 // Verify the first AddRecvStream hook up to the default renderer.
1155 EXPECT_EQ(&renderer_, renderer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1157 EXPECT_TRUE(NULL == renderer);
1158
1159 // Ensure we can now set the renderers.
1160 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1161 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1162 EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1163 EXPECT_TRUE(&renderer1 == renderer);
1164 EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1165 EXPECT_TRUE(&renderer2 == renderer);
1166
1167 // Ensure we can change the renderers if needed.
1168 EXPECT_TRUE(channel_->SetRenderer(1, &renderer2));
1169 EXPECT_TRUE(channel_->SetRenderer(2, &renderer1));
1170 EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1171 EXPECT_TRUE(&renderer2 == renderer);
1172 EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1173 EXPECT_TRUE(&renderer1 == renderer);
1174
1175 EXPECT_TRUE(channel_->RemoveRecvStream(2));
1176 EXPECT_TRUE(channel_->RemoveRecvStream(1));
1177 EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1178 EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1179 }
1180
1181 // Tests setting up and configuring multiple incoming streams in a
1182 // non-conference call.
1183 void AddRemoveRecvStreamsNoConference() {
1184 cricket::FakeVideoRenderer renderer1, renderer2;
1185 // Ensure we can't set the renderer on a non-existent stream.
1186 EXPECT_FALSE(channel_->SetRenderer(1, &renderer1));
1187 EXPECT_FALSE(channel_->SetRenderer(2, &renderer2));
1188 cricket::VideoRenderer* renderer;
1189 EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1190 EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1191
1192 // Ensure we can add streams.
1193 EXPECT_TRUE(channel_->AddRecvStream(
1194 cricket::StreamParams::CreateLegacy(1)));
1195 EXPECT_TRUE(channel_->AddRecvStream(
1196 cricket::StreamParams::CreateLegacy(2)));
1197 EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1198 // Verify the first AddRecvStream hook up to the default renderer.
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001199 EXPECT_EQ(&renderer_, renderer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001200 EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1201 EXPECT_TRUE(NULL == renderer);
1202
1203 // Ensure we can now set the renderers.
1204 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1205 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1206 EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1207 EXPECT_TRUE(&renderer1 == renderer);
1208 EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1209 EXPECT_TRUE(&renderer2 == renderer);
1210
1211 // Ensure we can change the renderers if needed.
1212 EXPECT_TRUE(channel_->SetRenderer(1, &renderer2));
1213 EXPECT_TRUE(channel_->SetRenderer(2, &renderer1));
1214 EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1215 EXPECT_TRUE(&renderer2 == renderer);
1216 EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1217 EXPECT_TRUE(&renderer1 == renderer);
1218
1219 EXPECT_TRUE(channel_->RemoveRecvStream(2));
1220 EXPECT_TRUE(channel_->RemoveRecvStream(1));
1221 EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1222 EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1223 }
1224
1225 // Test that no frames are rendered after the receive stream have been
1226 // removed.
1227 void AddRemoveRecvStreamAndRender() {
1228 cricket::FakeVideoRenderer renderer1;
1229 EXPECT_TRUE(SetDefaultCodec());
1230 EXPECT_TRUE(SetSend(true));
1231 EXPECT_TRUE(channel_->SetRender(true));
1232 EXPECT_TRUE(channel_->AddRecvStream(
1233 cricket::StreamParams::CreateLegacy(kSsrc)));
1234 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
1235
1236 EXPECT_TRUE(SendFrame());
1237 EXPECT_FRAME_ON_RENDERER_WAIT(
1238 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1239 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc));
1240 // Send three more frames. This is to avoid that the test might be flaky
1241 // due to frame dropping.
1242 for (size_t i = 0; i < 3; ++i)
1243 EXPECT_TRUE(WaitAndSendFrame(100));
1244
1245 // Test that no more frames have been rendered.
1246 EXPECT_EQ(1, renderer1.num_rendered_frames());
1247
1248 // Re-add the stream again and make sure it renders.
1249 EXPECT_TRUE(channel_->AddRecvStream(
1250 cricket::StreamParams::CreateLegacy(kSsrc)));
1251 // Force the next frame to be a key frame to make the receiving
1252 // decoder happy.
1253 EXPECT_TRUE(channel_->SendIntraFrame());
1254
1255 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
1256 EXPECT_TRUE(SendFrame());
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001257 // Because the default channel is used, RemoveRecvStream above is not going
1258 // to delete the channel. As a result the engine will continue to receive
1259 // and decode the 3 frames sent above. So it is possible we will receive
1260 // some (e.g. 1) of these 3 frames after the renderer is set again.
1261 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262 renderer1, 2, DefaultCodec().width, DefaultCodec().height, kTimeout);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001263 // Detach |renderer1| before exit as there might be frames come late.
1264 EXPECT_TRUE(channel_->SetRenderer(kSsrc, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001265 }
1266
1267 // Tests the behavior of incoming streams in a conference scenario.
1268 void SimulateConference() {
1269 cricket::FakeVideoRenderer renderer1, renderer2;
1270 EXPECT_TRUE(SetDefaultCodec());
1271 cricket::VideoOptions vmo;
1272 vmo.conference_mode.Set(true);
1273 EXPECT_TRUE(channel_->SetOptions(vmo));
1274 EXPECT_TRUE(SetSend(true));
1275 EXPECT_TRUE(channel_->SetRender(true));
1276 EXPECT_TRUE(channel_->AddRecvStream(
1277 cricket::StreamParams::CreateLegacy(1)));
1278 EXPECT_TRUE(channel_->AddRecvStream(
1279 cricket::StreamParams::CreateLegacy(2)));
1280 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1281 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1282 EXPECT_EQ(0, renderer1.num_rendered_frames());
1283 EXPECT_EQ(0, renderer2.num_rendered_frames());
1284 std::vector<uint32> ssrcs;
1285 ssrcs.push_back(1);
1286 ssrcs.push_back(2);
1287 network_interface_.SetConferenceMode(true, ssrcs);
1288 EXPECT_TRUE(SendFrame());
1289 EXPECT_FRAME_ON_RENDERER_WAIT(
1290 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1291 EXPECT_FRAME_ON_RENDERER_WAIT(
1292 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1293
1294 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
1295 EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
1296 EXPECT_EQ(DefaultCodec().width, renderer1.width());
1297 EXPECT_EQ(DefaultCodec().height, renderer1.height());
1298 EXPECT_EQ(DefaultCodec().width, renderer2.width());
1299 EXPECT_EQ(DefaultCodec().height, renderer2.height());
1300 EXPECT_TRUE(channel_->RemoveRecvStream(2));
1301 EXPECT_TRUE(channel_->RemoveRecvStream(1));
1302 }
1303
1304 // Tests that we can add and remove capturers and frames are sent out properly
1305 void AddRemoveCapturer() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001306 cricket::VideoCodec codec = DefaultCodec();
1307 codec.width = 320;
1308 codec.height = 240;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 const int time_between_send = TimeBetweenSend(codec);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001310 EXPECT_TRUE(SetOneCodec(codec));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001311 EXPECT_TRUE(SetSend(true));
1312 EXPECT_TRUE(channel_->SetRender(true));
1313 EXPECT_EQ(0, renderer_.num_rendered_frames());
1314 EXPECT_TRUE(SendFrame());
1315 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
1316 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
1317 new cricket::FakeVideoCapturer);
1318 capturer->SetScreencast(true);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001319 cricket::VideoFormat format(480, 360,
1320 cricket::VideoFormat::FpsToInterval(30),
1321 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
1323 // All capturers start generating frames with the same timestamp. ViE does
1324 // not allow the same timestamp to be used. Capture one frame before
1325 // associating the capturer with the channel.
1326 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
1327 cricket::FOURCC_I420));
1328
1329 int captured_frames = 1;
1330 for (int iterations = 0; iterations < 2; ++iterations) {
1331 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
1332 talk_base::Thread::Current()->ProcessMessages(time_between_send);
1333 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
1334 cricket::FOURCC_I420));
1335 ++captured_frames;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001336 // Wait until frame of right size is captured.
1337 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
1338 format.width == renderer_.width() &&
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001339 format.height == renderer_.height() &&
1340 !renderer_.black_frame(), kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001341 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
1342 EXPECT_EQ(format.width, renderer_.width());
1343 EXPECT_EQ(format.height, renderer_.height());
1344 captured_frames = renderer_.num_rendered_frames() + 1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001345 EXPECT_FALSE(renderer_.black_frame());
1346 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001347 // Make sure a black frame is generated within the specified timeout.
1348 // The black frame should be the resolution of the send codec.
1349 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
1350 codec.width == renderer_.width() &&
1351 codec.height == renderer_.height() &&
1352 renderer_.black_frame(), kTimeout);
1353 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
1354 EXPECT_EQ(codec.width, renderer_.width());
1355 EXPECT_EQ(codec.height, renderer_.height());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001356 EXPECT_TRUE(renderer_.black_frame());
1357
1358 // The black frame has the same timestamp as the next frame since it's
1359 // timestamp is set to the last frame's timestamp + interval. WebRTC will
1360 // not render a frame with the same timestamp so capture another frame
1361 // with the frame capturer to increment the next frame's timestamp.
1362 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
1363 cricket::FOURCC_I420));
1364 }
1365 }
1366
1367 // Tests that if RemoveCapturer is called without a capturer ever being
1368 // added, the plugin shouldn't crash (and no black frame should be sent).
1369 void RemoveCapturerWithoutAdd() {
1370 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
1371 EXPECT_TRUE(SetSend(true));
1372 EXPECT_TRUE(channel_->SetRender(true));
1373 EXPECT_EQ(0, renderer_.num_rendered_frames());
1374 EXPECT_TRUE(SendFrame());
1375 EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001376 // Remove the capturer.
1377 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001378 // Wait for one black frame for removing the capturer.
1379 EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
1380
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001381 // No capturer was added, so this RemoveCapturer should
1382 // fail.
1383 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001384 talk_base::Thread::Current()->ProcessMessages(300);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001385 // Verify no more frames were sent.
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001386 EXPECT_EQ(2, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001387 }
1388
1389 // Tests that we can add and remove capturer as unique sources.
1390 void AddRemoveCapturerMultipleSources() {
1391 // WebRTC implementation will drop frames if pushed to quickly. Wait the
1392 // interval time to avoid that.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001393 // WebRTC implementation will drop frames if pushed to quickly. Wait the
1394 // interval time to avoid that.
1395 // Set up the stream associated with the engine.
1396 EXPECT_TRUE(channel_->AddRecvStream(
1397 cricket::StreamParams::CreateLegacy(kSsrc)));
1398 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer_));
1399 cricket::VideoFormat capture_format; // default format
1400 capture_format.interval = cricket::VideoFormat::FpsToInterval(30);
1401 // Set up additional stream 1.
1402 cricket::FakeVideoRenderer renderer1;
1403 EXPECT_FALSE(channel_->SetRenderer(1, &renderer1));
1404 EXPECT_TRUE(channel_->AddRecvStream(
1405 cricket::StreamParams::CreateLegacy(1)));
1406 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1407 EXPECT_TRUE(channel_->AddSendStream(
1408 cricket::StreamParams::CreateLegacy(1)));
1409 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer1(
1410 new cricket::FakeVideoCapturer);
1411 capturer1->SetScreencast(true);
1412 EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format));
1413 // Set up additional stream 2.
1414 cricket::FakeVideoRenderer renderer2;
1415 EXPECT_FALSE(channel_->SetRenderer(2, &renderer2));
1416 EXPECT_TRUE(channel_->AddRecvStream(
1417 cricket::StreamParams::CreateLegacy(2)));
1418 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1419 EXPECT_TRUE(channel_->AddSendStream(
1420 cricket::StreamParams::CreateLegacy(2)));
1421 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer2(
1422 new cricket::FakeVideoCapturer);
1423 capturer2->SetScreencast(true);
1424 EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
1425 // State for all the streams.
1426 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
1427 // A limitation in the lmi implementation requires that SetCapturer() is
1428 // called after SetOneCodec().
1429 // TODO(hellner): this seems like an unnecessary constraint, fix it.
1430 EXPECT_TRUE(channel_->SetCapturer(1, capturer1.get()));
1431 EXPECT_TRUE(channel_->SetCapturer(2, capturer2.get()));
1432 EXPECT_TRUE(SetSend(true));
1433 EXPECT_TRUE(channel_->SetRender(true));
1434 // Test capturer associated with engine.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001435 const int kTestWidth = 160;
1436 const int kTestHeight = 120;
1437 EXPECT_TRUE(capturer1->CaptureCustomFrame(
1438 kTestWidth, kTestHeight, cricket::FOURCC_I420));
1439 EXPECT_FRAME_ON_RENDERER_WAIT(
1440 renderer1, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001441 // Capture a frame with additional capturer2, frames should be received
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001442 EXPECT_TRUE(capturer2->CaptureCustomFrame(
1443 kTestWidth, kTestHeight, cricket::FOURCC_I420));
1444 EXPECT_FRAME_ON_RENDERER_WAIT(
1445 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001446 // Successfully remove the capturer.
1447 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1448 // Fail to re-remove the capturer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001449 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
1450 // The capturers must be unregistered here as it runs out of it's scope
1451 // next.
1452 EXPECT_TRUE(channel_->SetCapturer(1, NULL));
1453 EXPECT_TRUE(channel_->SetCapturer(2, NULL));
1454 }
1455
1456 void HighAspectHighHeightCapturer() {
1457 const int kWidth = 80;
1458 const int kHeight = 10000;
1459 const int kScaledWidth = 20;
1460 const int kScaledHeight = 2500;
1461
1462 cricket::VideoCodec codec(DefaultCodec());
1463 EXPECT_TRUE(SetOneCodec(codec));
1464 EXPECT_TRUE(SetSend(true));
1465
1466 cricket::FakeVideoRenderer renderer;
1467 EXPECT_TRUE(channel_->AddRecvStream(
1468 cricket::StreamParams::CreateLegacy(kSsrc)));
1469 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer));
1470 EXPECT_TRUE(channel_->SetRender(true));
1471 EXPECT_EQ(0, renderer.num_rendered_frames());
1472
1473 EXPECT_TRUE(SendFrame());
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001474 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
1475 renderer, 1, codec.width, codec.height, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001476
1477 // Registering an external capturer is currently the same as screen casting
1478 // (update the test when this changes).
1479 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
1480 new cricket::FakeVideoCapturer);
1481 capturer->SetScreencast(true);
1482 const std::vector<cricket::VideoFormat>* formats =
1483 capturer->GetSupportedFormats();
1484 cricket::VideoFormat capture_format = (*formats)[0];
1485 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format));
1486 // Capture frame to not get same frame timestamps as previous capturer.
1487 capturer->CaptureFrame();
1488 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
1489 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1490 EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
1491 cricket::FOURCC_ARGB));
wu@webrtc.org9caf2762013-12-11 18:25:07 +00001492 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
1493 renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1495 }
1496
1497 // Tests that we can adapt video resolution with 16:10 aspect ratio properly.
1498 void AdaptResolution16x10() {
1499 cricket::VideoCodec codec(DefaultCodec());
1500 codec.width = 640;
1501 codec.height = 400;
1502 SendAndReceive(codec);
1503 codec.width /= 2;
1504 codec.height /= 2;
1505 // Adapt the resolution.
1506 EXPECT_TRUE(SetOneCodec(codec));
1507 EXPECT_TRUE(WaitAndSendFrame(30));
1508 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
1509 }
1510 // Tests that we can adapt video resolution with 4:3 aspect ratio properly.
1511 void AdaptResolution4x3() {
1512 cricket::VideoCodec codec(DefaultCodec());
1513 codec.width = 640;
1514 codec.height = 400;
1515 SendAndReceive(codec);
1516 codec.width /= 2;
1517 codec.height /= 2;
1518 // Adapt the resolution.
1519 EXPECT_TRUE(SetOneCodec(codec));
1520 EXPECT_TRUE(WaitAndSendFrame(30));
1521 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
1522 }
1523 // Tests that we can drop all frames properly.
1524 void AdaptDropAllFrames() {
1525 // Set the channel codec's resolution to 0, which will require the adapter
1526 // to drop all frames.
1527 cricket::VideoCodec codec(DefaultCodec());
1528 codec.width = codec.height = codec.framerate = 0;
1529 EXPECT_TRUE(SetOneCodec(codec));
1530 EXPECT_TRUE(SetSend(true));
1531 EXPECT_TRUE(channel_->SetRender(true));
1532 EXPECT_EQ(0, renderer_.num_rendered_frames());
1533 EXPECT_TRUE(SendFrame());
1534 EXPECT_TRUE(SendFrame());
1535 talk_base::Thread::Current()->ProcessMessages(500);
1536 EXPECT_EQ(0, renderer_.num_rendered_frames());
1537 }
1538 // Tests that we can reduce the frame rate on demand properly.
1539 // TODO(fbarchard): This test is flakey on pulse. Fix and re-enable
1540 void AdaptFramerate() {
1541 cricket::VideoCodec codec(DefaultCodec());
1542 int frame_count = 0;
1543 // The capturer runs at 30 fps. The channel requires 30 fps.
1544 EXPECT_TRUE(SetOneCodec(codec));
1545 EXPECT_TRUE(SetSend(true));
1546 EXPECT_TRUE(channel_->SetRender(true));
1547 EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1548 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1549 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1550 frame_count += 2;
1551 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
1552 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
1553 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
1554
1555 // The channel requires 15 fps.
1556 codec.framerate = 15;
1557 EXPECT_TRUE(SetOneCodec(codec));
1558 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1559 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1560 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1561 frame_count += 2;
1562 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1563
1564 // The channel requires 10 fps.
1565 codec.framerate = 10;
1566 EXPECT_TRUE(SetOneCodec(codec));
1567 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1568 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1569 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1570 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1571 frame_count += 2;
1572 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1573
1574 // The channel requires 8 fps. The adapter adapts to 10 fps, which is the
1575 // closest factor of 30.
1576 codec.framerate = 8;
1577 EXPECT_TRUE(SetOneCodec(codec));
1578 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1579 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1580 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1581 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1582 frame_count += 2;
1583 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1584 }
1585 // Tests that we can set the send stream format properly.
1586 void SetSendStreamFormat() {
1587 cricket::VideoCodec codec(DefaultCodec());
1588 SendAndReceive(codec);
1589 int frame_count = 1;
1590 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
1591
1592 // Adapt the resolution and frame rate to half.
1593 cricket::VideoFormat format(
1594 codec.width / 2,
1595 codec.height / 2,
1596 cricket::VideoFormat::FpsToInterval(codec.framerate / 2),
1597 cricket::FOURCC_I420);
1598 // The SSRC differs from the send SSRC.
1599 EXPECT_FALSE(channel_->SetSendStreamFormat(kSsrc - 1, format));
1600 EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format));
1601
1602 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1603 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1604 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1605 frame_count += 1;
1606 EXPECT_FRAME_WAIT(frame_count, format.width, format.height, kTimeout);
1607
1608 // Adapt the resolution to 0x0, which should drop all frames.
1609 format.width = 0;
1610 format.height = 0;
1611 EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format));
1612 EXPECT_TRUE(SendFrame());
1613 EXPECT_TRUE(SendFrame());
1614 talk_base::Thread::Current()->ProcessMessages(500);
1615 EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1616 }
1617 // Test that setting send stream format to 0x0 resolution will result in
1618 // frames being dropped.
1619 void SetSendStreamFormat0x0() {
1620 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001621 EXPECT_TRUE(SetSendStreamFormat(kSsrc, DefaultCodec()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 EXPECT_TRUE(SetSend(true));
1623 EXPECT_TRUE(channel_->SetRender(true));
1624 EXPECT_EQ(0, renderer_.num_rendered_frames());
1625 // This frame should be received.
1626 EXPECT_TRUE(SendFrame());
1627 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1628 const int64 interval = cricket::VideoFormat::FpsToInterval(
1629 DefaultCodec().framerate);
1630 cricket::VideoFormat format(
1631 0,
1632 0,
1633 interval,
1634 cricket::FOURCC_I420);
1635 EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format));
1636 // This frame should not be received.
1637 EXPECT_TRUE(WaitAndSendFrame(
1638 static_cast<int>(interval/talk_base::kNumNanosecsPerMillisec)));
1639 talk_base::Thread::Current()->ProcessMessages(500);
1640 EXPECT_EQ(1, renderer_.num_rendered_frames());
1641 }
1642
1643 // Tests that we can mute and unmute the channel properly.
1644 void MuteStream() {
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001645 int frame_count = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646 EXPECT_TRUE(SetDefaultCodec());
1647 cricket::FakeVideoCapturer video_capturer;
1648 video_capturer.Start(
1649 cricket::VideoFormat(
1650 640, 480,
1651 cricket::VideoFormat::FpsToInterval(30),
1652 cricket::FOURCC_I420));
1653 EXPECT_TRUE(channel_->SetCapturer(kSsrc, &video_capturer));
1654 EXPECT_TRUE(SetSend(true));
1655 EXPECT_TRUE(channel_->SetRender(true));
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001656 EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657
1658 // Mute the channel and expect black output frame.
1659 EXPECT_TRUE(channel_->MuteStream(kSsrc, true));
1660 EXPECT_TRUE(video_capturer.CaptureFrame());
1661 ++frame_count;
1662 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1663 EXPECT_TRUE(renderer_.black_frame());
1664
1665 // Unmute the channel and expect non-black output frame.
1666 EXPECT_TRUE(channel_->MuteStream(kSsrc, false));
1667 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1668 EXPECT_TRUE(video_capturer.CaptureFrame());
1669 ++frame_count;
1670 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1671 EXPECT_FALSE(renderer_.black_frame());
1672
1673 // Test that we can also Mute using the correct send stream SSRC.
1674 EXPECT_TRUE(channel_->MuteStream(kSsrc, true));
1675 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1676 EXPECT_TRUE(video_capturer.CaptureFrame());
1677 ++frame_count;
1678 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1679 EXPECT_TRUE(renderer_.black_frame());
1680
1681 EXPECT_TRUE(channel_->MuteStream(kSsrc, false));
1682 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1683 EXPECT_TRUE(video_capturer.CaptureFrame());
1684 ++frame_count;
1685 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1686 EXPECT_FALSE(renderer_.black_frame());
1687
1688 // Test that muting an invalid stream fails.
1689 EXPECT_FALSE(channel_->MuteStream(kSsrc+1, true));
1690 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1691 }
1692
1693 // Test that multiple send streams can be created and deleted properly.
1694 void MultipleSendStreams() {
1695 // Remove stream added in Setup. I.e. remove stream corresponding to default
1696 // channel.
1697 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1698 const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]);
1699 for (unsigned int i = 0; i < kSsrcsSize; ++i) {
1700 EXPECT_TRUE(channel_->AddSendStream(
1701 cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
1702 }
1703 // Delete one of the non default channel streams, let the destructor delete
1704 // the remaining ones.
1705 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1706 // Stream should already be deleted.
1707 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1708 }
1709
1710
1711 // Two streams one channel tests.
1712
1713 // Tests that we can send and receive frames.
1714 void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) {
1715 SetUpSecondStream();
1716 // Test sending and receiving on first stream.
1717 SendAndReceive(codec);
1718 // Test sending and receiving on second stream.
1719 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
1720 EXPECT_EQ(2, NumRtpPackets());
1721 EXPECT_EQ(1, renderer2_.num_rendered_frames());
1722 }
1723
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001724 // Set up 2 streams where the first stream uses the default channel.
1725 // Then disconnect the first stream and verify default channel becomes
1726 // available.
1727 // Then add a new stream with |new_ssrc|. The new stream should re-use the
1728 // default channel.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001729 void TwoStreamsReUseFirstStream(const cricket::VideoCodec& codec) {
1730 SetUpSecondStream();
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001731 // Default channel used by the first stream.
1732 EXPECT_EQ(kSsrc, channel_->GetDefaultChannelSsrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001733 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc));
1734 EXPECT_FALSE(channel_->RemoveRecvStream(kSsrc));
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001735 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001736 EXPECT_FALSE(channel_->RemoveSendStream(kSsrc));
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001737 // Default channel is no longer used by a stream.
1738 EXPECT_EQ(0u, channel_->GetDefaultChannelSsrc());
buildbot@webrtc.org196ae6d2014-07-18 21:41:41 +00001739 SetRendererAsDefault();
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001740 uint32 new_ssrc = kSsrc + 100;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741 EXPECT_TRUE(channel_->AddSendStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001742 cricket::StreamParams::CreateLegacy(new_ssrc)));
1743 // Re-use default channel.
1744 EXPECT_EQ(new_ssrc, channel_->GetDefaultChannelSsrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001745 EXPECT_FALSE(channel_->AddSendStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001746 cricket::StreamParams::CreateLegacy(new_ssrc)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747 EXPECT_TRUE(channel_->AddRecvStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001748 cricket::StreamParams::CreateLegacy(new_ssrc)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 EXPECT_FALSE(channel_->AddRecvStream(
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001750 cricket::StreamParams::CreateLegacy(new_ssrc)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001752 EXPECT_TRUE(channel_->SetCapturer(new_ssrc, video_capturer_.get()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001753
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001754 SendAndReceive(codec);
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00001755 EXPECT_TRUE(channel_->RemoveSendStream(new_ssrc));
1756 EXPECT_EQ(0u, channel_->GetDefaultChannelSsrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001757 }
1758
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001759 // Tests that we can send and receive frames with early receive.
1760 void TwoStreamsSendAndUnsignalledRecv(const cricket::VideoCodec& codec) {
1761 cricket::VideoOptions vmo;
1762 vmo.conference_mode.Set(true);
1763 vmo.unsignalled_recv_stream_limit.Set(1);
1764 EXPECT_TRUE(channel_->SetOptions(vmo));
1765 SetUpSecondStreamWithNoRecv();
1766 // Test sending and receiving on first stream.
1767 EXPECT_TRUE(channel_->SetRender(true));
1768 Send(codec);
1769 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout);
1770 EXPECT_EQ_WAIT(1, renderer_.num_rendered_frames(), kTimeout);
1771 // The first send is not expected to yield frames, because the ssrc
1772 // is not signalled yet. With unsignalled recv enabled, we will drop frames
1773 // instead of packets.
1774 EXPECT_EQ(0, renderer2_.num_rendered_frames());
1775 // Give a chance for the decoder to process before adding the receiver.
henrike@webrtc.org18e59112014-03-14 17:19:38 +00001776 talk_base::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001777 // Test sending and receiving on second stream.
1778 EXPECT_TRUE(channel_->AddRecvStream(
1779 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
1780 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_));
1781 SendFrame();
1782 EXPECT_EQ_WAIT(2, renderer_.num_rendered_frames(), kTimeout);
1783 EXPECT_EQ(4, NumRtpPackets());
1784 // The second send is expected to yield frame as the ssrc is signalled now.
1785 // Decode should succeed here, though we received the key frame earlier.
1786 // Without early recv, we would have dropped it and decoding would have
1787 // failed.
1788 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
1789 }
1790
1791 // Tests that we cannot receive key frames with unsignalled recv disabled.
1792 void TwoStreamsSendAndFailUnsignalledRecv(const cricket::VideoCodec& codec) {
1793 cricket::VideoOptions vmo;
henrike@webrtc.org18e59112014-03-14 17:19:38 +00001794 vmo.conference_mode.Set(true);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001795 vmo.unsignalled_recv_stream_limit.Set(0);
1796 EXPECT_TRUE(channel_->SetOptions(vmo));
1797 SetUpSecondStreamWithNoRecv();
1798 // Test sending and receiving on first stream.
1799 EXPECT_TRUE(channel_->SetRender(true));
1800 Send(codec);
1801 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout);
henrike@webrtc.org18e59112014-03-14 17:19:38 +00001802 talk_base::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001803 EXPECT_EQ_WAIT(1, renderer_.num_rendered_frames(), kTimeout);
1804 EXPECT_EQ_WAIT(0, renderer2_.num_rendered_frames(), kTimeout);
1805 // Give a chance for the decoder to process before adding the receiver.
1806 talk_base::Thread::Current()->ProcessMessages(10);
1807 // Test sending and receiving on second stream.
1808 EXPECT_TRUE(channel_->AddRecvStream(
1809 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
1810 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_));
1811 SendFrame();
1812 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= 1, kTimeout);
1813 EXPECT_EQ_WAIT(4, NumRtpPackets(), kTimeout);
1814 // We dont expect any frames here, because the key frame would have been
1815 // lost in the earlier packet. This is the case we want to solve with early
1816 // receive.
1817 EXPECT_EQ(0, renderer2_.num_rendered_frames());
1818 }
1819
1820 // Tests that we drop key frames when conference mode is disabled and we
1821 // receive rtp packets on unsignalled streams.
1822 void TwoStreamsSendAndFailUnsignalledRecvInOneToOne(
1823 const cricket::VideoCodec& codec) {
1824 cricket::VideoOptions vmo;
1825 vmo.conference_mode.Set(false);
1826 vmo.unsignalled_recv_stream_limit.Set(1);
1827 EXPECT_TRUE(channel_->SetOptions(vmo));
1828 SetUpSecondStreamWithNoRecv();
1829 // Test sending and receiving on first stream.
1830 EXPECT_TRUE(channel_->SetRender(true));
1831 Send(codec);
1832 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout);
henrike@webrtc.org18e59112014-03-14 17:19:38 +00001833 // In one-to-one mode, we deliver frames to the default channel if there
1834 // is no registered recv channel for the ssrc.
1835 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= 1, kTimeout);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001836 // Give a chance for the decoder to process before adding the receiver.
henrike@webrtc.org18e59112014-03-14 17:19:38 +00001837 talk_base::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001838 // Test sending and receiving on second stream.
1839 EXPECT_TRUE(channel_->AddRecvStream(
1840 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
1841 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_));
1842 SendFrame();
1843 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= 1, kTimeout);
1844 EXPECT_EQ_WAIT(4, NumRtpPackets(), kTimeout);
1845 // We dont expect any frames here, because the key frame would have been
henrike@webrtc.org18e59112014-03-14 17:19:38 +00001846 // delivered to default channel.
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +00001847 EXPECT_EQ(0, renderer2_.num_rendered_frames());
1848 }
1849
1850 // Tests that we drop key frames when conference mode is enabled and we
1851 // receive rtp packets on unsignalled streams. Removal of a unsignalled recv
1852 // stream is successful.
1853 void TwoStreamsAddAndRemoveUnsignalledRecv(
1854 const cricket::VideoCodec& codec) {
1855 cricket::VideoOptions vmo;
1856 vmo.conference_mode.Set(true);
1857 vmo.unsignalled_recv_stream_limit.Set(1);
1858 EXPECT_TRUE(channel_->SetOptions(vmo));
1859 SetUpSecondStreamWithNoRecv();
1860 // Sending and receiving on first stream.
1861 EXPECT_TRUE(channel_->SetRender(true));
1862 Send(codec);
1863 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout);
1864 EXPECT_EQ_WAIT(1, renderer_.num_rendered_frames(), kTimeout);
1865 // The first send is not expected to yield frames, because the ssrc
1866 // is no signalled yet. With unsignalled recv enabled, we will drop frames
1867 // instead of packets.
1868 EXPECT_EQ(0, renderer2_.num_rendered_frames());
1869 // Give a chance for the decoder to process before adding the receiver.
1870 talk_base::Thread::Current()->ProcessMessages(100);
1871 // Ensure that we can remove the unsignalled recv stream that was created
1872 // when the first video packet with unsignalled recv ssrc is received.
1873 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc + 2));
1874 }
1875
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876 VideoEngineOverride<E> engine_;
1877 talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001878 talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001879 talk_base::scoped_ptr<C> channel_;
1880 cricket::FakeNetworkInterface network_interface_;
1881 cricket::FakeVideoRenderer renderer_;
1882 cricket::VideoMediaChannel::Error media_error_;
1883
1884 // Used by test cases where 2 streams are run on the same channel.
1885 cricket::FakeVideoRenderer renderer2_;
1886};
1887
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001888#endif // TALK_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT