Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/talk/media/base/videoengine_unittest.h @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

File size: 64.9 KB
Line 
1// 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
26#ifndef TALK_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_  // NOLINT
27#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
57static const uint32 kTimeout = 5000U;
58static const uint32 kSsrc = 1234u;
59static const uint32 kRtxSsrc = 4321u;
60static const uint32 kSsrcs4[] = {1, 2, 3, 4};
61
62inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) {
63  return a.width == w && a.height == h && a.framerate == fps;
64}
65
66inline bool IsEqualCodec(const cricket::VideoCodec& a,
67                         const cricket::VideoCodec& b) {
68  return a.id == b.id && a.name == b.name &&
69      IsEqualRes(a, b.width, b.height, b.framerate);
70}
71
72namespace std {
73inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
74  s << "{" << c.name << "(" << c.id << "), "
75    << c.width << "x" << c.height << "x" << c.framerate << "}";
76  return s;
77}
78}  // namespace std
79
80inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
81  return static_cast<int>(
82      cricket::VideoFormat::FpsToInterval(codec.framerate) /
83      talk_base::kNumNanosecsPerMillisec);
84}
85
86// Fake video engine that makes it possible to test enabling and disabling
87// capturer (checking that the engine state is updated and that the capturer
88// is indeed capturing) without having to create a channel. It also makes it
89// possible to test that the media processors are indeed being called when
90// registered.
91template<class T>
92class VideoEngineOverride : public T {
93 public:
94  VideoEngineOverride() {
95  }
96  virtual ~VideoEngineOverride() {
97  }
98  bool is_camera_on() const { return T::GetVideoCapturer()->IsRunning(); }
99  void set_has_senders(bool has_senders) {
100    cricket::VideoCapturer* video_capturer = T::GetVideoCapturer();
101    if (has_senders) {
102      video_capturer->SignalVideoFrame.connect(this,
103          &VideoEngineOverride<T>::OnLocalFrame);
104    } else {
105      video_capturer->SignalVideoFrame.disconnect(this);
106    }
107  }
108  void OnLocalFrame(cricket::VideoCapturer*,
109                    const cricket::VideoFrame*) {
110  }
111  void OnLocalFrameFormat(cricket::VideoCapturer*,
112                          const cricket::VideoFormat*) {
113  }
114
115  void TriggerMediaFrame(
116      uint32 ssrc, cricket::VideoFrame* frame, bool* drop_frame) {
117    T::SignalMediaFrame(ssrc, frame, drop_frame);
118  }
119};
120
121// Macroes that declare test functions for a given test class, before and after
122// Init().
123// To use, define a test function called FooBody and pass Foo to the macro.
124#define TEST_PRE_VIDEOENGINE_INIT(TestClass, func) \
125  TEST_F(TestClass, func##PreInit) { \
126    func##Body(); \
127  }
128#define TEST_POST_VIDEOENGINE_INIT(TestClass, func) \
129  TEST_F(TestClass, func##PostInit) { \
130    EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); \
131    func##Body(); \
132    engine_.Terminate(); \
133  }
134
135template<class E>
136class VideoEngineTest : public testing::Test {
137 protected:
138  // Tests starting and stopping the engine, and creating a channel.
139  void StartupShutdown() {
140    EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
141    cricket::VideoMediaChannel* channel = engine_.CreateChannel(NULL);
142    EXPECT_TRUE(channel != NULL);
143    delete channel;
144    engine_.Terminate();
145  }
146
147#ifdef WIN32
148  // Tests that the COM reference count is not munged by the engine.
149  // Test to make sure LMI does not munge the CoInitialize reference count.
150  void CheckCoInitialize() {
151    // Initial refcount should be 0.
152    EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
153
154    // Engine should start even with COM already inited.
155    EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
156    engine_.Terminate();
157    // Refcount after terminate should be 1; this tests if it is nonzero.
158    EXPECT_EQ(S_FALSE, CoInitializeEx(NULL, COINIT_MULTITHREADED));
159    // Decrement refcount to (hopefully) 0.
160    CoUninitialize();
161    CoUninitialize();
162
163    // Ensure refcount is 0.
164    EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
165    CoUninitialize();
166  }
167#endif
168
169  void ConstrainNewCodecBody() {
170    cricket::VideoCodec empty, in, out;
171    cricket::VideoCodec max_settings(engine_.codecs()[0].id,
172                                     engine_.codecs()[0].name,
173                                     1280, 800, 30, 0);
174
175    // set max settings of 1280x960x30
176    EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
177        cricket::VideoEncoderConfig(max_settings)));
178
179    // don't constrain the max resolution
180    in = max_settings;
181    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
182    EXPECT_PRED2(IsEqualCodec, out, in);
183
184    // constrain resolution greater than the max and wider aspect,
185    // picking best aspect (16:10)
186    in.width = 1380;
187    in.height = 800;
188    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
189    EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
190
191    // constrain resolution greater than the max and narrow aspect,
192    // picking best aspect (16:9)
193    in.width = 1280;
194    in.height = 740;
195    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
196    EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
197
198    // constrain resolution greater than the max, picking equal aspect (4:3)
199    in.width = 1280;
200    in.height = 960;
201    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
202    EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
203
204    // constrain resolution greater than the max, picking equal aspect (16:10)
205    in.width = 1280;
206    in.height = 800;
207    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
208    EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
209
210    // reduce max settings to 640x480x30
211    max_settings.width = 640;
212    max_settings.height = 480;
213    EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
214        cricket::VideoEncoderConfig(max_settings)));
215
216    // don't constrain the max resolution
217    in = max_settings;
218    in.width = 640;
219    in.height = 480;
220    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
221    EXPECT_PRED2(IsEqualCodec, out, in);
222
223    // keep 16:10 if they request it
224    in.height = 400;
225    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
226    EXPECT_PRED2(IsEqualCodec, out, in);
227
228    // don't constrain lesser 4:3 resolutions
229    in.width = 320;
230    in.height = 240;
231    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
232    EXPECT_PRED2(IsEqualCodec, out, in);
233
234    // don't constrain lesser 16:10 resolutions
235    in.width = 320;
236    in.height = 200;
237    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
238    EXPECT_PRED2(IsEqualCodec, out, in);
239
240    // requested resolution of 0x0 succeeds
241    in.width = 0;
242    in.height = 0;
243    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
244    EXPECT_PRED2(IsEqualCodec, out, in);
245
246    // constrain resolution lesser than the max and wider aspect,
247    // picking best aspect (16:9)
248    in.width = 350;
249    in.height = 201;
250    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
251    EXPECT_PRED4(IsEqualRes, out, 320, 180, 30);
252
253    // constrain resolution greater than the max and narrow aspect,
254    // picking best aspect (4:3)
255    in.width = 350;
256    in.height = 300;
257    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
258    EXPECT_PRED4(IsEqualRes, out, 320, 240, 30);
259
260    // constrain resolution greater than the max and wider aspect,
261    // picking best aspect (16:9)
262    in.width = 1380;
263    in.height = 800;
264    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
265    EXPECT_PRED4(IsEqualRes, out, 640, 360, 30);
266
267    // constrain resolution greater than the max and narrow aspect,
268    // picking best aspect (4:3)
269    in.width = 1280;
270    in.height = 900;
271    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
272    EXPECT_PRED4(IsEqualRes, out, 640, 480, 30);
273
274    // constrain resolution greater than the max, picking equal aspect (4:3)
275    in.width = 1280;
276    in.height = 960;
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 (16:10)
281    in.width = 1280;
282    in.height = 800;
283    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
284    EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
285
286    // constrain res & fps greater than the max
287    in.framerate = 50;
288    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
289    EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
290
291    // reduce max settings to 160x100x10
292    max_settings.width = 160;
293    max_settings.height = 100;
294    max_settings.framerate = 10;
295    EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
296        cricket::VideoEncoderConfig(max_settings)));
297
298    // constrain res & fps to new max
299    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
300    EXPECT_PRED4(IsEqualRes, out, 160, 100, 10);
301
302    // allow 4:3 "comparable" resolutions
303    in.width = 160;
304    in.height = 120;
305    in.framerate = 10;
306    EXPECT_TRUE(engine_.CanSendCodec(in, empty, &out));
307    EXPECT_PRED4(IsEqualRes, out, 160, 120, 10);
308  }
309
310  void ConstrainRunningCodecBody() {
311    cricket::VideoCodec in, out, current;
312    cricket::VideoCodec max_settings(engine_.codecs()[0].id,
313                                     engine_.codecs()[0].name,
314                                     1280, 800, 30, 0);
315
316    // set max settings of 1280x960x30
317    EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
318        cricket::VideoEncoderConfig(max_settings)));
319
320    // establish current call at 1280x800x30 (16:10)
321    current = max_settings;
322    current.height = 800;
323
324    // Don't constrain current resolution
325    in = current;
326    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
327    EXPECT_PRED2(IsEqualCodec, out, in);
328
329    // requested resolution of 0x0 succeeds
330    in.width = 0;
331    in.height = 0;
332    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
333    EXPECT_PRED2(IsEqualCodec, out, in);
334
335    // Reduce an intermediate resolution down to the next lowest one, preserving
336    // aspect ratio.
337    in.width = 800;
338    in.height = 600;
339    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
340    EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
341
342    // Clamping by aspect ratio, but still never return a dimension higher than
343    // requested.
344    in.width = 1280;
345    in.height = 720;
346    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
347    EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
348
349    in.width = 1279;
350    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
351    EXPECT_PRED4(IsEqualRes, out, 960, 600, 30);
352
353    in.width = 1281;
354    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
355    EXPECT_PRED4(IsEqualRes, out, 1280, 720, 30);
356
357    // Clamp large resolutions down, always preserving aspect
358    in.width = 1920;
359    in.height = 1080;
360    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
361    EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
362
363    in.width = 1921;
364    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
365    EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
366
367    in.width = 1919;
368    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
369    EXPECT_PRED4(IsEqualRes, out, 1280, 800, 30);
370
371    // reduce max settings to 640x480x30
372    max_settings.width = 640;
373    max_settings.height = 480;
374    EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
375        cricket::VideoEncoderConfig(max_settings)));
376
377    // establish current call at 640x400x30 (16:10)
378    current = max_settings;
379    current.height = 400;
380
381    // Don't constrain current resolution
382    in = current;
383    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
384    EXPECT_PRED2(IsEqualCodec, out, in);
385
386    // requested resolution of 0x0 succeeds
387    in.width = 0;
388    in.height = 0;
389    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
390    EXPECT_PRED2(IsEqualCodec, out, in);
391
392    // Reduce an intermediate resolution down to the next lowest one, preserving
393    // aspect ratio.
394    in.width = 400;
395    in.height = 300;
396    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
397    EXPECT_PRED4(IsEqualRes, out, 320, 200, 30);
398
399    // Clamping by aspect ratio, but still never return a dimension higher than
400    // requested.
401    in.width = 640;
402    in.height = 360;
403    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
404    EXPECT_PRED4(IsEqualRes, out, 640, 360, 30);
405
406    in.width = 639;
407    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
408    EXPECT_PRED4(IsEqualRes, out, 480, 300, 30);
409
410    in.width = 641;
411    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
412    EXPECT_PRED4(IsEqualRes, out, 640, 360, 30);
413
414    // Clamp large resolutions down, always preserving aspect
415    in.width = 1280;
416    in.height = 800;
417    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
418    EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
419
420    in.width = 1281;
421    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
422    EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
423
424    in.width = 1279;
425    EXPECT_TRUE(engine_.CanSendCodec(in, current, &out));
426    EXPECT_PRED4(IsEqualRes, out, 640, 400, 30);
427
428    // Should fail for any that are smaller than our supported formats
429    in.width = 80;
430    in.height = 80;
431    EXPECT_FALSE(engine_.CanSendCodec(in, current, &out));
432
433    in.height = 50;
434    EXPECT_FALSE(engine_.CanSendCodec(in, current, &out));
435  }
436
437  VideoEngineOverride<E> engine_;
438  talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_;
439};
440
441template<class E, class C>
442class VideoMediaChannelTest : public testing::Test,
443                              public sigslot::has_slots<> {
444 protected:
445  virtual cricket::VideoCodec DefaultCodec() = 0;
446
447  virtual cricket::StreamParams DefaultSendStreamParams() {
448    return cricket::StreamParams::CreateLegacy(kSsrc);
449  }
450
451  virtual void SetUp() {
452    cricket::Device device("test", "device");
453    EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
454    channel_.reset(engine_.CreateChannel(NULL));
455    EXPECT_TRUE(channel_.get() != NULL);
456    ConnectVideoChannelError();
457    network_interface_.SetDestination(channel_.get());
458    channel_->SetInterface(&network_interface_);
459    SetRendererAsDefault();
460    media_error_ = cricket::VideoMediaChannel::ERROR_NONE;
461    channel_->SetRecvCodecs(engine_.codecs());
462    EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams()));
463
464    video_capturer_.reset(new cricket::FakeVideoCapturer);
465    cricket::VideoFormat format(640, 480,
466                                cricket::VideoFormat::FpsToInterval(30),
467                                cricket::FOURCC_I420);
468    EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
469    EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
470  }
471  void SetUpSecondStream() {
472    EXPECT_TRUE(channel_->AddRecvStream(
473        cricket::StreamParams::CreateLegacy(kSsrc)));
474    EXPECT_TRUE(channel_->AddRecvStream(
475        cricket::StreamParams::CreateLegacy(kSsrc + 2)));
476    // SetUp() already added kSsrc make sure duplicate SSRCs cant be added.
477    EXPECT_FALSE(channel_->AddSendStream(
478        cricket::StreamParams::CreateLegacy(kSsrc)));
479    EXPECT_TRUE(channel_->AddSendStream(
480        cricket::StreamParams::CreateLegacy(kSsrc + 2)));
481
482    video_capturer_2_.reset(new cricket::FakeVideoCapturer());
483    cricket::VideoFormat format(640, 480,
484                                cricket::VideoFormat::FpsToInterval(30),
485                                cricket::FOURCC_I420);
486    EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
487
488    EXPECT_TRUE(channel_->SetCapturer(kSsrc + 2, video_capturer_2_.get()));
489    // Make the second renderer available for use by a new stream.
490    EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_));
491  }
492  virtual void TearDown() {
493    channel_.reset();
494    engine_.Terminate();
495  }
496  void ConnectVideoChannelError() {
497    channel_->SignalMediaError.connect(this,
498        &VideoMediaChannelTest<E, C>::OnVideoChannelError);
499  }
500  bool SetDefaultCodec() {
501    return SetOneCodec(DefaultCodec());
502  }
503  void SetRendererAsDefault() {
504    EXPECT_TRUE(channel_->SetRenderer(0, &renderer_));
505  }
506
507  bool SetOneCodec(int pt, const char* name, int w, int h, int fr) {
508    return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0));
509  }
510  bool SetOneCodec(const cricket::VideoCodec& codec) {
511    std::vector<cricket::VideoCodec> codecs;
512    codecs.push_back(codec);
513
514    cricket::VideoFormat capture_format(codec.width, codec.height,
515        cricket::VideoFormat::FpsToInterval(codec.framerate),
516        cricket::FOURCC_I420);
517
518    if (video_capturer_) {
519      EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format));
520    }
521
522    if (video_capturer_2_) {
523      EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format));
524    }
525
526    bool sending = channel_->sending();
527    bool success = SetSend(false);
528    if (success)
529      success = channel_->SetSendCodecs(codecs);
530    if (success)
531      success = SetSend(sending);
532    return success;
533  }
534  bool SetSend(bool send) {
535    return channel_->SetSend(send);
536  }
537  int DrainOutgoingPackets() {
538    int packets = 0;
539    do {
540      packets = NumRtpPackets();
541      // 100 ms should be long enough.
542      talk_base::Thread::Current()->ProcessMessages(100);
543    } while (NumRtpPackets() > packets);
544    return NumRtpPackets();
545  }
546  bool SendFrame() {
547    if (video_capturer_2_) {
548      video_capturer_2_->CaptureFrame();
549    }
550    return video_capturer_.get() &&
551        video_capturer_->CaptureFrame();
552  }
553  bool WaitAndSendFrame(int wait_ms) {
554    bool ret = talk_base::Thread::Current()->ProcessMessages(wait_ms);
555    ret &= SendFrame();
556    return ret;
557  }
558  // Sends frames and waits for the decoder to be fully initialized.
559  // Returns the number of frames that were sent.
560  int WaitForDecoder() {
561#if defined(HAVE_OPENMAX)
562    // Send enough frames for the OpenMAX decoder to continue processing, and
563    // return the number of frames sent.
564    // Send frames for a full kTimeout's worth of 15fps video.
565    int frame_count = 0;
566    while (frame_count < static_cast<int>(kTimeout) / 66) {
567      EXPECT_TRUE(WaitAndSendFrame(66));
568      ++frame_count;
569    }
570    return frame_count;
571#else
572    return 0;
573#endif
574  }
575  bool SendCustomVideoFrame(int w, int h) {
576    if (!video_capturer_.get()) return false;
577    return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420);
578  }
579  int NumRtpBytes() {
580    return network_interface_.NumRtpBytes();
581  }
582  int NumRtpBytes(uint32 ssrc) {
583    return network_interface_.NumRtpBytes(ssrc);
584  }
585  int NumRtpPackets() {
586    return network_interface_.NumRtpPackets();
587  }
588  int NumRtpPackets(uint32 ssrc) {
589    return network_interface_.NumRtpPackets(ssrc);
590  }
591  int NumSentSsrcs() {
592    return network_interface_.NumSentSsrcs();
593  }
594  const talk_base::Buffer* GetRtpPacket(int index) {
595    return network_interface_.GetRtpPacket(index);
596  }
597  int NumRtcpPackets() {
598    return network_interface_.NumRtcpPackets();
599  }
600  const talk_base::Buffer* GetRtcpPacket(int index) {
601    return network_interface_.GetRtcpPacket(index);
602  }
603  static int GetPayloadType(const talk_base::Buffer* p) {
604    int pt = -1;
605    ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
606    return pt;
607  }
608  static bool ParseRtpPacket(const talk_base::Buffer* p, bool* x, int* pt,
609                             int* seqnum, uint32* tstamp, uint32* ssrc,
610                             std::string* payload) {
611    talk_base::ByteBuffer buf(p->data(), p->length());
612    uint8 u08 = 0;
613    uint16 u16 = 0;
614    uint32 u32 = 0;
615
616    // Read X and CC fields.
617    if (!buf.ReadUInt8(&u08)) return false;
618    bool extension = ((u08 & 0x10) != 0);
619    uint8 cc = (u08 & 0x0F);
620    if (x) *x = extension;
621
622    // Read PT field.
623    if (!buf.ReadUInt8(&u08)) return false;
624    if (pt) *pt = (u08 & 0x7F);
625
626    // Read Sequence Number field.
627    if (!buf.ReadUInt16(&u16)) return false;
628    if (seqnum) *seqnum = u16;
629
630    // Read Timestamp field.
631    if (!buf.ReadUInt32(&u32)) return false;
632    if (tstamp) *tstamp = u32;
633
634    // Read SSRC field.
635    if (!buf.ReadUInt32(&u32)) return false;
636    if (ssrc) *ssrc = u32;
637
638    // Skip CSRCs.
639    for (uint8 i = 0; i < cc; ++i) {
640      if (!buf.ReadUInt32(&u32)) return false;
641    }
642
643    // Skip extension header.
644    if (extension) {
645      // Read Profile-specific extension header ID
646      if (!buf.ReadUInt16(&u16)) return false;
647
648      // Read Extension header length
649      if (!buf.ReadUInt16(&u16)) return false;
650      uint16 ext_header_len = u16;
651
652      // Read Extension header
653      for (uint16 i = 0; i < ext_header_len; ++i) {
654        if (!buf.ReadUInt32(&u32)) return false;
655      }
656    }
657
658    if (payload) {
659      return buf.ReadString(payload, buf.Length());
660    }
661    return true;
662  }
663
664  // Parse all RTCP packet, from start_index to stop_index, and count how many
665  // FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count
666  // and return true.
667  bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
668    int count = 0;
669    for (int i = start_index; i < stop_index; ++i) {
670      talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtcpPacket(i));
671      talk_base::ByteBuffer buf(p->data(), p->length());
672      size_t total_len = 0;
673      // The packet may be a compound RTCP packet.
674      while (total_len < p->length()) {
675        // Read FMT, type and length.
676        uint8 fmt = 0;
677        uint8 type = 0;
678        uint16 length = 0;
679        if (!buf.ReadUInt8(&fmt)) return false;
680        fmt &= 0x1F;
681        if (!buf.ReadUInt8(&type)) return false;
682        if (!buf.ReadUInt16(&length)) return false;
683        buf.Consume(length * 4);  // Skip RTCP data.
684        total_len += (length + 1) * 4;
685        if ((192 == type) || ((206 == type) && (4 == fmt))) {
686          ++count;
687        }
688      }
689    }
690
691    if (fir_count) {
692      *fir_count = count;
693    }
694    return true;
695  }
696
697  void OnVideoChannelError(uint32 ssrc,
698                           cricket::VideoMediaChannel::Error error) {
699    media_error_ = error;
700  }
701
702  // Test that SetSend works.
703  void SetSend() {
704    EXPECT_FALSE(channel_->sending());
705    EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
706    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
707    EXPECT_FALSE(channel_->sending());
708    EXPECT_TRUE(SetSend(true));
709    EXPECT_TRUE(channel_->sending());
710    EXPECT_TRUE(SendFrame());
711    EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
712    EXPECT_TRUE(SetSend(false));
713    EXPECT_FALSE(channel_->sending());
714  }
715  // Test that SetSend fails without codecs being set.
716  void SetSendWithoutCodecs() {
717    EXPECT_FALSE(channel_->sending());
718    EXPECT_FALSE(SetSend(true));
719    EXPECT_FALSE(channel_->sending());
720  }
721  // Test that we properly set the send and recv buffer sizes by the time
722  // SetSend is called.
723  void SetSendSetsTransportBufferSizes() {
724    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
725    EXPECT_TRUE(SetSend(true));
726    // TODO(sriniv): Remove or re-enable this.
727    // As part of b/8030474, send-buffer is size now controlled through
728    // portallocator flags. Its not set by channels.
729    // EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size());
730    EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size());
731  }
732  // Tests that we can send frames and the right payload type is used.
733  void Send(const cricket::VideoCodec& codec) {
734    EXPECT_TRUE(SetOneCodec(codec));
735    EXPECT_TRUE(SetSend(true));
736    EXPECT_TRUE(SendFrame());
737    EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
738    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
739    EXPECT_EQ(codec.id, GetPayloadType(p.get()));
740  }
741  // Tests that we can send and receive frames.
742  void SendAndReceive(const cricket::VideoCodec& codec) {
743    EXPECT_TRUE(SetOneCodec(codec));
744    EXPECT_TRUE(SetSend(true));
745    EXPECT_TRUE(channel_->SetRender(true));
746    EXPECT_EQ(0, renderer_.num_rendered_frames());
747    EXPECT_TRUE(SendFrame());
748    EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
749    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
750    EXPECT_EQ(codec.id, GetPayloadType(p.get()));
751  }
752  // Tests that we only get a VideoRenderer::SetSize() callback when needed.
753  void SendManyResizeOnce() {
754    cricket::VideoCodec codec(DefaultCodec());
755    EXPECT_TRUE(SetOneCodec(codec));
756    EXPECT_TRUE(SetSend(true));
757    EXPECT_TRUE(channel_->SetRender(true));
758    EXPECT_EQ(0, renderer_.num_rendered_frames());
759    EXPECT_TRUE(WaitAndSendFrame(30));
760    EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
761    EXPECT_TRUE(WaitAndSendFrame(30));
762    EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
763    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
764    EXPECT_EQ(codec.id, GetPayloadType(p.get()));
765    EXPECT_EQ(1, renderer_.num_set_sizes());
766
767    codec.width /= 2;
768    codec.height /= 2;
769    EXPECT_TRUE(SetOneCodec(codec));
770    EXPECT_TRUE(WaitAndSendFrame(30));
771    EXPECT_FRAME_WAIT(3, codec.width, codec.height, kTimeout);
772    EXPECT_EQ(2, renderer_.num_set_sizes());
773  }
774  // Test that stats work properly for a 1-1 call.
775  void GetStats() {
776    SendAndReceive(DefaultCodec());
777    cricket::VideoMediaInfo info;
778    EXPECT_TRUE(channel_->GetStats(&info));
779
780    ASSERT_EQ(1U, info.senders.size());
781    // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
782    EXPECT_GT(info.senders[0].bytes_sent, 0);
783    EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
784    EXPECT_EQ(0.0, info.senders[0].fraction_lost);
785    EXPECT_EQ(0, info.senders[0].firs_rcvd);
786    EXPECT_EQ(0, info.senders[0].nacks_rcvd);
787    EXPECT_EQ(DefaultCodec().width, info.senders[0].frame_width);
788    EXPECT_EQ(DefaultCodec().height, info.senders[0].frame_height);
789    EXPECT_GT(info.senders[0].framerate_input, 0);
790    EXPECT_GT(info.senders[0].framerate_sent, 0);
791
792    ASSERT_EQ(1U, info.receivers.size());
793    EXPECT_EQ(1U, info.senders[0].ssrcs().size());
794    EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
795    EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
796    EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
797    EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
798    EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
799    EXPECT_EQ(0, info.receivers[0].packets_lost);
800    EXPECT_EQ(0, info.receivers[0].packets_concealed);
801    EXPECT_EQ(0, info.receivers[0].firs_sent);
802    EXPECT_EQ(0, info.receivers[0].nacks_sent);
803    EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width);
804    EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height);
805    EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
806    EXPECT_GT(info.receivers[0].framerate_decoded, 0);
807    EXPECT_GT(info.receivers[0].framerate_output, 0);
808  }
809  // Test that stats work properly for a conf call with multiple recv streams.
810  void GetStatsMultipleRecvStreams() {
811    cricket::FakeVideoRenderer renderer1, renderer2;
812    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
813    cricket::VideoOptions vmo;
814    vmo.conference_mode.Set(true);
815    EXPECT_TRUE(channel_->SetOptions(vmo));
816    EXPECT_TRUE(SetSend(true));
817    EXPECT_TRUE(channel_->AddRecvStream(
818        cricket::StreamParams::CreateLegacy(1)));
819    EXPECT_TRUE(channel_->AddRecvStream(
820        cricket::StreamParams::CreateLegacy(2)));
821    EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
822    EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
823    EXPECT_TRUE(channel_->SetRender(true));
824    EXPECT_EQ(0, renderer1.num_rendered_frames());
825    EXPECT_EQ(0, renderer2.num_rendered_frames());
826    std::vector<uint32> ssrcs;
827    ssrcs.push_back(1);
828    ssrcs.push_back(2);
829    network_interface_.SetConferenceMode(true, ssrcs);
830    EXPECT_TRUE(SendFrame());
831    EXPECT_FRAME_ON_RENDERER_WAIT(
832        renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
833    EXPECT_FRAME_ON_RENDERER_WAIT(
834        renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
835    cricket::VideoMediaInfo info;
836    EXPECT_TRUE(channel_->GetStats(&info));
837
838    ASSERT_EQ(1U, info.senders.size());
839    // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
840    EXPECT_GT(info.senders[0].bytes_sent, 0);
841    EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
842    EXPECT_EQ(0.0, info.senders[0].fraction_lost);
843    EXPECT_EQ(0, info.senders[0].firs_rcvd);
844    EXPECT_EQ(0, info.senders[0].nacks_rcvd);
845    EXPECT_EQ(DefaultCodec().width, info.senders[0].frame_width);
846    EXPECT_EQ(DefaultCodec().height, info.senders[0].frame_height);
847    EXPECT_GT(info.senders[0].framerate_input, 0);
848    EXPECT_GT(info.senders[0].framerate_sent, 0);
849
850    ASSERT_EQ(2U, info.receivers.size());
851    for (size_t i = 0; i < info.receivers.size(); ++i) {
852      EXPECT_EQ(1U, info.receivers[i].ssrcs().size());
853      EXPECT_EQ(i + 1, info.receivers[i].ssrcs()[0]);
854      EXPECT_EQ(NumRtpBytes(), info.receivers[i].bytes_rcvd);
855      EXPECT_EQ(NumRtpPackets(), info.receivers[i].packets_rcvd);
856      EXPECT_EQ(0.0, info.receivers[i].fraction_lost);
857      EXPECT_EQ(0, info.receivers[i].packets_lost);
858      EXPECT_EQ(0, info.receivers[i].packets_concealed);
859      EXPECT_EQ(0, info.receivers[i].firs_sent);
860      EXPECT_EQ(0, info.receivers[i].nacks_sent);
861      EXPECT_EQ(DefaultCodec().width, info.receivers[i].frame_width);
862      EXPECT_EQ(DefaultCodec().height, info.receivers[i].frame_height);
863      EXPECT_GT(info.receivers[i].framerate_rcvd, 0);
864      EXPECT_GT(info.receivers[i].framerate_decoded, 0);
865      EXPECT_GT(info.receivers[i].framerate_output, 0);
866    }
867  }
868  // Test that stats work properly for a conf call with multiple send streams.
869  void GetStatsMultipleSendStreams() {
870    // Normal setup; note that we set the SSRC explicitly to ensure that
871    // it will come first in the senders map.
872    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
873    cricket::VideoOptions vmo;
874    vmo.conference_mode.Set(true);
875    EXPECT_TRUE(channel_->SetOptions(vmo));
876    EXPECT_TRUE(channel_->AddRecvStream(
877        cricket::StreamParams::CreateLegacy(1234)));
878    channel_->UpdateAspectRatio(640, 400);
879    EXPECT_TRUE(SetSend(true));
880    EXPECT_TRUE(channel_->SetRender(true));
881    EXPECT_TRUE(SendFrame());
882    EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
883    EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
884
885    // Add an additional capturer, and hook up a renderer to receive it.
886    cricket::FakeVideoRenderer renderer1;
887    talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
888      new cricket::FakeVideoCapturer);
889    capturer->SetScreencast(true);
890    cricket::VideoFormat format(1024, 768,
891                                cricket::VideoFormat::FpsToInterval(5), 0);
892    EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
893    EXPECT_TRUE(channel_->AddSendStream(
894        cricket::StreamParams::CreateLegacy(5678)));
895    EXPECT_TRUE(channel_->SetCapturer(5678, capturer.get()));
896    EXPECT_TRUE(channel_->AddRecvStream(
897        cricket::StreamParams::CreateLegacy(5678)));
898    EXPECT_TRUE(channel_->SetRenderer(5678, &renderer1));
899    EXPECT_TRUE(capturer->CaptureCustomFrame(1024, 768, cricket::FOURCC_I420));
900    EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, 1024, 768, kTimeout);
901
902    // Get stats, and make sure they are correct for two senders.
903    cricket::VideoMediaInfo info;
904    EXPECT_TRUE(channel_->GetStats(&info));
905    ASSERT_EQ(2U, info.senders.size());
906    EXPECT_EQ(NumRtpPackets(),
907        info.senders[0].packets_sent + info.senders[1].packets_sent);
908    EXPECT_EQ(1U, info.senders[0].ssrcs().size());
909    EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
910    EXPECT_EQ(DefaultCodec().width, info.senders[0].frame_width);
911    EXPECT_EQ(DefaultCodec().height, info.senders[0].frame_height);
912    EXPECT_EQ(1U, info.senders[1].ssrcs().size());
913    EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
914    EXPECT_EQ(1024, info.senders[1].frame_width);
915    EXPECT_EQ(768, info.senders[1].frame_height);
916    // The capturer must be unregistered here as it runs out of it's scope next.
917    EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
918  }
919
920  // Test that we can set the bandwidth to auto or a specific value.
921  void SetSendBandwidth() {
922    EXPECT_TRUE(channel_->SetSendBandwidth(true, -1));
923    EXPECT_TRUE(channel_->SetSendBandwidth(true, 128 * 1024));
924    EXPECT_TRUE(channel_->SetSendBandwidth(false, -1));
925    EXPECT_TRUE(channel_->SetSendBandwidth(false, 128 * 1024));
926  }
927  // Test that we can set the SSRC for the default send source.
928  void SetSendSsrc() {
929    EXPECT_TRUE(SetDefaultCodec());
930    EXPECT_TRUE(SetSend(true));
931    EXPECT_TRUE(SendFrame());
932    EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
933    uint32 ssrc = 0;
934    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
935    ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
936    EXPECT_EQ(kSsrc, ssrc);
937    EXPECT_EQ(NumRtpPackets(), NumRtpPackets(ssrc));
938    EXPECT_EQ(NumRtpBytes(), NumRtpBytes(ssrc));
939    EXPECT_EQ(1, NumSentSsrcs());
940    EXPECT_EQ(0, NumRtpPackets(kSsrc - 1));
941    EXPECT_EQ(0, NumRtpBytes(kSsrc - 1));
942  }
943  // Test that we can set the SSRC even after codecs are set.
944  void SetSendSsrcAfterSetCodecs() {
945    // Remove stream added in Setup.
946    EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
947    EXPECT_TRUE(SetDefaultCodec());
948    EXPECT_TRUE(channel_->AddSendStream(
949        cricket::StreamParams::CreateLegacy(999)));
950    EXPECT_TRUE(channel_->SetCapturer(999u, video_capturer_.get()));
951    EXPECT_TRUE(SetSend(true));
952    EXPECT_TRUE(WaitAndSendFrame(0));
953    EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
954    uint32 ssrc = 0;
955    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
956    ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
957    EXPECT_EQ(999u, ssrc);
958    EXPECT_EQ(NumRtpPackets(), NumRtpPackets(ssrc));
959    EXPECT_EQ(NumRtpBytes(), NumRtpBytes(ssrc));
960    EXPECT_EQ(1, NumSentSsrcs());
961    EXPECT_EQ(0, NumRtpPackets(kSsrc));
962    EXPECT_EQ(0, NumRtpBytes(kSsrc));
963  }
964  // Test that we can set the default video renderer before and after
965  // media is received.
966  void SetRenderer() {
967    uint8 data1[] = {
968        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
969    };
970
971    talk_base::Buffer packet1(data1, sizeof(data1));
972    talk_base::SetBE32(packet1.data() + 8, kSsrc);
973    channel_->SetRenderer(0, NULL);
974    EXPECT_TRUE(SetDefaultCodec());
975    EXPECT_TRUE(SetSend(true));
976    EXPECT_TRUE(channel_->SetRender(true));
977    EXPECT_EQ(0, renderer_.num_rendered_frames());
978    channel_->OnPacketReceived(&packet1);
979    SetRendererAsDefault();
980    EXPECT_TRUE(SendFrame());
981    EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
982  }
983
984  // Tests empty StreamParams is rejected.
985  void RejectEmptyStreamParams() {
986    // Remove the send stream that was added during Setup.
987    EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
988
989    cricket::StreamParams empty;
990    EXPECT_FALSE(channel_->AddSendStream(empty));
991    EXPECT_TRUE(channel_->AddSendStream(
992        cricket::StreamParams::CreateLegacy(789u)));
993  }
994
995  // Tests setting up and configuring a send stream.
996  void AddRemoveSendStreams() {
997    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
998    EXPECT_TRUE(SetSend(true));
999    EXPECT_TRUE(channel_->SetRender(true));
1000    EXPECT_TRUE(SendFrame());
1001    EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1002    EXPECT_GE(2, NumRtpPackets());
1003    uint32 ssrc = 0;
1004    size_t last_packet = NumRtpPackets() - 1;
1005    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(last_packet));
1006    ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
1007    EXPECT_EQ(kSsrc, ssrc);
1008
1009    // Remove the send stream that was added during Setup.
1010    EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1011    int rtp_packets = NumRtpPackets();
1012
1013    EXPECT_TRUE(channel_->AddSendStream(
1014        cricket::StreamParams::CreateLegacy(789u)));
1015    EXPECT_TRUE(channel_->SetCapturer(789u, video_capturer_.get()));
1016    EXPECT_EQ(rtp_packets, NumRtpPackets());
1017    // Wait 30ms to guarantee the engine does not drop the frame.
1018    EXPECT_TRUE(WaitAndSendFrame(30));
1019    EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
1020
1021    last_packet = NumRtpPackets() - 1;
1022    p.reset(GetRtpPacket(last_packet));
1023    ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
1024    EXPECT_EQ(789u, ssrc);
1025  }
1026
1027  // Tests adding streams already exists returns false.
1028  void AddRecvStreamsAlreadyExist() {
1029    cricket::VideoOptions vmo;
1030    vmo.conference_mode.Set(true);
1031    EXPECT_TRUE(channel_->SetOptions(vmo));
1032
1033    EXPECT_FALSE(channel_->AddRecvStream(
1034        cricket::StreamParams::CreateLegacy(0)));
1035
1036    EXPECT_TRUE(channel_->AddRecvStream(
1037        cricket::StreamParams::CreateLegacy(1)));
1038    EXPECT_FALSE(channel_->AddRecvStream(
1039        cricket::StreamParams::CreateLegacy(1)));
1040
1041    EXPECT_TRUE(channel_->RemoveRecvStream(1));
1042    EXPECT_FALSE(channel_->AddRecvStream(
1043        cricket::StreamParams::CreateLegacy(0)));
1044    EXPECT_TRUE(channel_->AddRecvStream(
1045        cricket::StreamParams::CreateLegacy(1)));
1046  }
1047
1048  // Tests setting up and configuring multiple incoming streams.
1049  void AddRemoveRecvStreams() {
1050    cricket::FakeVideoRenderer renderer1, renderer2;
1051    cricket::VideoOptions vmo;
1052    vmo.conference_mode.Set(true);
1053    EXPECT_TRUE(channel_->SetOptions(vmo));
1054    // Ensure we can't set the renderer on a non-existent stream.
1055    EXPECT_FALSE(channel_->SetRenderer(1, &renderer1));
1056    EXPECT_FALSE(channel_->SetRenderer(2, &renderer2));
1057    cricket::VideoRenderer* renderer;
1058    EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1059    EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1060
1061    // Ensure we can add streams.
1062    EXPECT_TRUE(channel_->AddRecvStream(
1063        cricket::StreamParams::CreateLegacy(1)));
1064    EXPECT_TRUE(channel_->AddRecvStream(
1065        cricket::StreamParams::CreateLegacy(2)));
1066    EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1067    // Verify the first AddRecvStream hook up to the default renderer.
1068    EXPECT_EQ(&renderer_, renderer);
1069    EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1070    EXPECT_TRUE(NULL == renderer);
1071
1072    // Ensure we can now set the renderers.
1073    EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1074    EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1075    EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1076    EXPECT_TRUE(&renderer1 == renderer);
1077    EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1078    EXPECT_TRUE(&renderer2 == renderer);
1079
1080    // Ensure we can change the renderers if needed.
1081    EXPECT_TRUE(channel_->SetRenderer(1, &renderer2));
1082    EXPECT_TRUE(channel_->SetRenderer(2, &renderer1));
1083    EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1084    EXPECT_TRUE(&renderer2 == renderer);
1085    EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1086    EXPECT_TRUE(&renderer1 == renderer);
1087
1088    EXPECT_TRUE(channel_->RemoveRecvStream(2));
1089    EXPECT_TRUE(channel_->RemoveRecvStream(1));
1090    EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1091    EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1092  }
1093
1094  // Tests setting up and configuring multiple incoming streams in a
1095  // non-conference call.
1096  void AddRemoveRecvStreamsNoConference() {
1097    cricket::FakeVideoRenderer renderer1, renderer2;
1098    // Ensure we can't set the renderer on a non-existent stream.
1099    EXPECT_FALSE(channel_->SetRenderer(1, &renderer1));
1100    EXPECT_FALSE(channel_->SetRenderer(2, &renderer2));
1101    cricket::VideoRenderer* renderer;
1102    EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1103    EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1104
1105    // Ensure we can add streams.
1106    EXPECT_TRUE(channel_->AddRecvStream(
1107        cricket::StreamParams::CreateLegacy(1)));
1108    EXPECT_TRUE(channel_->AddRecvStream(
1109        cricket::StreamParams::CreateLegacy(2)));
1110    EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1111    // Verify the first AddRecvStream hook up to the default renderer.
1112    EXPECT_EQ(&renderer_, renderer);
1113    EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1114    EXPECT_TRUE(NULL == renderer);
1115
1116    // Ensure we can now set the renderers.
1117    EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1118    EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1119    EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1120    EXPECT_TRUE(&renderer1 == renderer);
1121    EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1122    EXPECT_TRUE(&renderer2 == renderer);
1123
1124    // Ensure we can change the renderers if needed.
1125    EXPECT_TRUE(channel_->SetRenderer(1, &renderer2));
1126    EXPECT_TRUE(channel_->SetRenderer(2, &renderer1));
1127    EXPECT_TRUE(channel_->GetRenderer(1, &renderer));
1128    EXPECT_TRUE(&renderer2 == renderer);
1129    EXPECT_TRUE(channel_->GetRenderer(2, &renderer));
1130    EXPECT_TRUE(&renderer1 == renderer);
1131
1132    EXPECT_TRUE(channel_->RemoveRecvStream(2));
1133    EXPECT_TRUE(channel_->RemoveRecvStream(1));
1134    EXPECT_FALSE(channel_->GetRenderer(1, &renderer));
1135    EXPECT_FALSE(channel_->GetRenderer(2, &renderer));
1136  }
1137
1138  // Test that no frames are rendered after the receive stream have been
1139  // removed.
1140  void AddRemoveRecvStreamAndRender() {
1141    cricket::FakeVideoRenderer renderer1;
1142    EXPECT_TRUE(SetDefaultCodec());
1143    EXPECT_TRUE(SetSend(true));
1144    EXPECT_TRUE(channel_->SetRender(true));
1145    EXPECT_TRUE(channel_->AddRecvStream(
1146        cricket::StreamParams::CreateLegacy(kSsrc)));
1147    EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
1148
1149    EXPECT_TRUE(SendFrame());
1150    EXPECT_FRAME_ON_RENDERER_WAIT(
1151        renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1152    EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc));
1153    // Send three more frames. This is to avoid that the test might be flaky
1154    // due to frame dropping.
1155    for (size_t i = 0; i < 3; ++i)
1156      EXPECT_TRUE(WaitAndSendFrame(100));
1157
1158    // Test that no more frames have been rendered.
1159    EXPECT_EQ(1, renderer1.num_rendered_frames());
1160
1161    // Re-add the stream again and make sure it renders.
1162    EXPECT_TRUE(channel_->AddRecvStream(
1163        cricket::StreamParams::CreateLegacy(kSsrc)));
1164    // Force the next frame to be a key frame to make the receiving
1165    // decoder happy.
1166    EXPECT_TRUE(channel_->SendIntraFrame());
1167
1168    EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
1169    EXPECT_TRUE(SendFrame());
1170    EXPECT_FRAME_ON_RENDERER_WAIT(
1171        renderer1, 2, DefaultCodec().width, DefaultCodec().height, kTimeout);
1172  }
1173
1174  // Tests the behavior of incoming streams in a conference scenario.
1175  void SimulateConference() {
1176    cricket::FakeVideoRenderer renderer1, renderer2;
1177    EXPECT_TRUE(SetDefaultCodec());
1178    cricket::VideoOptions vmo;
1179    vmo.conference_mode.Set(true);
1180    EXPECT_TRUE(channel_->SetOptions(vmo));
1181    EXPECT_TRUE(SetSend(true));
1182    EXPECT_TRUE(channel_->SetRender(true));
1183    EXPECT_TRUE(channel_->AddRecvStream(
1184        cricket::StreamParams::CreateLegacy(1)));
1185    EXPECT_TRUE(channel_->AddRecvStream(
1186        cricket::StreamParams::CreateLegacy(2)));
1187    EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1188    EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1189    EXPECT_EQ(0, renderer1.num_rendered_frames());
1190    EXPECT_EQ(0, renderer2.num_rendered_frames());
1191    std::vector<uint32> ssrcs;
1192    ssrcs.push_back(1);
1193    ssrcs.push_back(2);
1194    network_interface_.SetConferenceMode(true, ssrcs);
1195    EXPECT_TRUE(SendFrame());
1196    EXPECT_FRAME_ON_RENDERER_WAIT(
1197        renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1198    EXPECT_FRAME_ON_RENDERER_WAIT(
1199        renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1200
1201    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
1202    EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
1203    EXPECT_EQ(DefaultCodec().width, renderer1.width());
1204    EXPECT_EQ(DefaultCodec().height, renderer1.height());
1205    EXPECT_EQ(DefaultCodec().width, renderer2.width());
1206    EXPECT_EQ(DefaultCodec().height, renderer2.height());
1207    EXPECT_TRUE(channel_->RemoveRecvStream(2));
1208    EXPECT_TRUE(channel_->RemoveRecvStream(1));
1209  }
1210
1211  // Tests that we can add and remove capturers and frames are sent out properly
1212  void AddRemoveCapturer() {
1213    const cricket::VideoCodec codec(DefaultCodec());
1214    const int time_between_send = TimeBetweenSend(codec);
1215    EXPECT_TRUE(SetDefaultCodec());
1216    EXPECT_TRUE(SetSend(true));
1217    EXPECT_TRUE(channel_->SetRender(true));
1218    EXPECT_EQ(0, renderer_.num_rendered_frames());
1219    EXPECT_TRUE(SendFrame());
1220    EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
1221    talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
1222        new cricket::FakeVideoCapturer);
1223    capturer->SetScreencast(true);
1224    cricket::VideoFormat format(1024, 768,
1225                                cricket::VideoFormat::FpsToInterval(30), 0);
1226    EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
1227    // All capturers start generating frames with the same timestamp. ViE does
1228    // not allow the same timestamp to be used. Capture one frame before
1229    // associating the capturer with the channel.
1230    EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
1231                                             cricket::FOURCC_I420));
1232
1233    int captured_frames = 1;
1234    for (int iterations = 0; iterations < 2; ++iterations) {
1235      EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
1236      talk_base::Thread::Current()->ProcessMessages(time_between_send);
1237      EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
1238                                               cricket::FOURCC_I420));
1239      ++captured_frames;
1240      // Wait until frame of right size is captured.
1241      EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
1242                       format.width == renderer_.width() &&
1243                       format.height == renderer_.height() &&
1244                       !renderer_.black_frame(), kTimeout);
1245      EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
1246      EXPECT_EQ(format.width, renderer_.width());
1247      EXPECT_EQ(format.height, renderer_.height());
1248      captured_frames = renderer_.num_rendered_frames() + 1;
1249      EXPECT_FALSE(renderer_.black_frame());
1250      EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1251      // Make sure a black frame is generated within the specified timeout.
1252      // The black frame should be the resolution of the send codec.
1253      EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
1254                       codec.width == renderer_.width() &&
1255                       codec.height == renderer_.height() &&
1256                       renderer_.black_frame(), kTimeout);
1257      EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
1258      EXPECT_EQ(codec.width, renderer_.width());
1259      EXPECT_EQ(codec.height, renderer_.height());
1260      EXPECT_TRUE(renderer_.black_frame());
1261
1262      // The black frame has the same timestamp as the next frame since it's
1263      // timestamp is set to the last frame's timestamp + interval. WebRTC will
1264      // not render a frame with the same timestamp so capture another frame
1265      // with the frame capturer to increment the next frame's timestamp.
1266      EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
1267                                               cricket::FOURCC_I420));
1268    }
1269  }
1270
1271  // Tests that if RemoveCapturer is called without a capturer ever being
1272  // added, the plugin shouldn't crash (and no black frame should be sent).
1273  void RemoveCapturerWithoutAdd() {
1274    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
1275    EXPECT_TRUE(SetSend(true));
1276    EXPECT_TRUE(channel_->SetRender(true));
1277    EXPECT_EQ(0, renderer_.num_rendered_frames());
1278    EXPECT_TRUE(SendFrame());
1279    EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
1280    // Remove the capturer.
1281    EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1282    // No capturer was added, so this RemoveCapturer should
1283    // fail.
1284    EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
1285    // Wait for frames to stop flowing.
1286    talk_base::Thread::Current()->ProcessMessages(300);
1287    int num_frames = renderer_.num_rendered_frames();
1288    // Wait to make sure no more frames are sent
1289    WAIT(renderer_.num_rendered_frames() != num_frames, 300);
1290    // Verify no more frames were sent.
1291    EXPECT_EQ(num_frames, renderer_.num_rendered_frames());
1292  }
1293
1294  // Tests that we can add and remove capturer as unique sources.
1295  void AddRemoveCapturerMultipleSources() {
1296    // WebRTC implementation will drop frames if pushed to quickly. Wait the
1297    // interval time to avoid that.
1298    const cricket::VideoFormat send_format(
1299        1024,
1300        768,
1301        cricket::VideoFormat::FpsToInterval(30),
1302        0);
1303    // WebRTC implementation will drop frames if pushed to quickly. Wait the
1304    // interval time to avoid that.
1305    // Set up the stream associated with the engine.
1306    EXPECT_TRUE(channel_->AddRecvStream(
1307        cricket::StreamParams::CreateLegacy(kSsrc)));
1308    EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer_));
1309    cricket::VideoFormat capture_format;  // default format
1310    capture_format.interval = cricket::VideoFormat::FpsToInterval(30);
1311    // Set up additional stream 1.
1312    cricket::FakeVideoRenderer renderer1;
1313    EXPECT_FALSE(channel_->SetRenderer(1, &renderer1));
1314    EXPECT_TRUE(channel_->AddRecvStream(
1315        cricket::StreamParams::CreateLegacy(1)));
1316    EXPECT_TRUE(channel_->SetRenderer(1, &renderer1));
1317    EXPECT_TRUE(channel_->AddSendStream(
1318        cricket::StreamParams::CreateLegacy(1)));
1319    talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer1(
1320        new cricket::FakeVideoCapturer);
1321    capturer1->SetScreencast(true);
1322    EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format));
1323    // Set up additional stream 2.
1324    cricket::FakeVideoRenderer renderer2;
1325    EXPECT_FALSE(channel_->SetRenderer(2, &renderer2));
1326    EXPECT_TRUE(channel_->AddRecvStream(
1327        cricket::StreamParams::CreateLegacy(2)));
1328    EXPECT_TRUE(channel_->SetRenderer(2, &renderer2));
1329    EXPECT_TRUE(channel_->AddSendStream(
1330        cricket::StreamParams::CreateLegacy(2)));
1331    talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer2(
1332        new cricket::FakeVideoCapturer);
1333    capturer2->SetScreencast(true);
1334    EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
1335    // State for all the streams.
1336    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
1337    // A limitation in the lmi implementation requires that SetCapturer() is
1338    // called after SetOneCodec().
1339    // TODO(hellner): this seems like an unnecessary constraint, fix it.
1340    EXPECT_TRUE(channel_->SetCapturer(1, capturer1.get()));
1341    EXPECT_TRUE(channel_->SetCapturer(2, capturer2.get()));
1342    EXPECT_TRUE(SetSend(true));
1343    EXPECT_TRUE(channel_->SetRender(true));
1344    // Test capturer associated with engine.
1345    EXPECT_TRUE(capturer1->CaptureCustomFrame(1024, 768, cricket::FOURCC_I420));
1346    EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, 1024, 768, kTimeout);
1347    // Capture a frame with additional capturer2, frames should be received
1348    EXPECT_TRUE(capturer2->CaptureCustomFrame(1024, 768, cricket::FOURCC_I420));
1349    EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, 1024, 768, kTimeout);
1350    // Successfully remove the capturer.
1351    EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1352    // Fail to re-remove the capturer.
1353    EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
1354    // The capturers must be unregistered here as it runs out of it's scope
1355    // next.
1356    EXPECT_TRUE(channel_->SetCapturer(1, NULL));
1357    EXPECT_TRUE(channel_->SetCapturer(2, NULL));
1358  }
1359
1360  void HighAspectHighHeightCapturer() {
1361    const int kWidth  = 80;
1362    const int kHeight = 10000;
1363    const int kScaledWidth = 20;
1364    const int kScaledHeight = 2500;
1365
1366    cricket::VideoCodec codec(DefaultCodec());
1367    EXPECT_TRUE(SetOneCodec(codec));
1368    EXPECT_TRUE(SetSend(true));
1369
1370    cricket::FakeVideoRenderer renderer;
1371    EXPECT_TRUE(channel_->AddRecvStream(
1372        cricket::StreamParams::CreateLegacy(kSsrc)));
1373    EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer));
1374    EXPECT_TRUE(channel_->SetRender(true));
1375    EXPECT_EQ(0, renderer.num_rendered_frames());
1376
1377    EXPECT_TRUE(SendFrame());
1378    EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 1 &&
1379                     codec.width == renderer.width() &&
1380                     codec.height == renderer.height(), kTimeout);
1381    EXPECT_EQ(0, renderer.errors());
1382
1383    // Registering an external capturer is currently the same as screen casting
1384    // (update the test when this changes).
1385    talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
1386        new cricket::FakeVideoCapturer);
1387    capturer->SetScreencast(true);
1388    const std::vector<cricket::VideoFormat>* formats =
1389        capturer->GetSupportedFormats();
1390    cricket::VideoFormat capture_format = (*formats)[0];
1391    EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format));
1392    // Capture frame to not get same frame timestamps as previous capturer.
1393    capturer->CaptureFrame();
1394    EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
1395    EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1396    EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
1397                                             cricket::FOURCC_ARGB));
1398    EXPECT_TRUE(capturer->CaptureFrame());
1399    EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 2 &&
1400                     kScaledWidth == renderer.width() &&
1401                     kScaledHeight == renderer.height(), kTimeout);
1402    EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1403  }
1404
1405  // Tests that we can adapt video resolution with 16:10 aspect ratio properly.
1406  void AdaptResolution16x10() {
1407    cricket::VideoCodec codec(DefaultCodec());
1408    codec.width = 640;
1409    codec.height = 400;
1410    SendAndReceive(codec);
1411    codec.width /= 2;
1412    codec.height /= 2;
1413    // Adapt the resolution.
1414    EXPECT_TRUE(SetOneCodec(codec));
1415    EXPECT_TRUE(WaitAndSendFrame(30));
1416    EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
1417  }
1418  // Tests that we can adapt video resolution with 4:3 aspect ratio properly.
1419  void AdaptResolution4x3() {
1420    cricket::VideoCodec codec(DefaultCodec());
1421    codec.width = 640;
1422    codec.height = 400;
1423    SendAndReceive(codec);
1424    codec.width /= 2;
1425    codec.height /= 2;
1426    // Adapt the resolution.
1427    EXPECT_TRUE(SetOneCodec(codec));
1428    EXPECT_TRUE(WaitAndSendFrame(30));
1429    EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
1430  }
1431  // Tests that we can drop all frames properly.
1432  void AdaptDropAllFrames() {
1433    // Set the channel codec's resolution to 0, which will require the adapter
1434    // to drop all frames.
1435    cricket::VideoCodec codec(DefaultCodec());
1436    codec.width = codec.height = codec.framerate = 0;
1437    EXPECT_TRUE(SetOneCodec(codec));
1438    EXPECT_TRUE(SetSend(true));
1439    EXPECT_TRUE(channel_->SetRender(true));
1440    EXPECT_EQ(0, renderer_.num_rendered_frames());
1441    EXPECT_TRUE(SendFrame());
1442    EXPECT_TRUE(SendFrame());
1443    talk_base::Thread::Current()->ProcessMessages(500);
1444    EXPECT_EQ(0, renderer_.num_rendered_frames());
1445  }
1446  // Tests that we can reduce the frame rate on demand properly.
1447  // TODO(fbarchard): This test is flakey on pulse.  Fix and re-enable
1448  void AdaptFramerate() {
1449    cricket::VideoCodec codec(DefaultCodec());
1450    int frame_count = 0;
1451    // The capturer runs at 30 fps. The channel requires 30 fps.
1452    EXPECT_TRUE(SetOneCodec(codec));
1453    EXPECT_TRUE(SetSend(true));
1454    EXPECT_TRUE(channel_->SetRender(true));
1455    EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1456    EXPECT_TRUE(WaitAndSendFrame(0));  // Should be rendered.
1457    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be rendered.
1458    frame_count += 2;
1459    EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
1460    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0));
1461    EXPECT_EQ(codec.id, GetPayloadType(p.get()));
1462
1463    // The channel requires 15 fps.
1464    codec.framerate = 15;
1465    EXPECT_TRUE(SetOneCodec(codec));
1466    EXPECT_TRUE(WaitAndSendFrame(0));  // Should be rendered.
1467    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1468    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be rendered.
1469    frame_count += 2;
1470    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1471
1472    // The channel requires 10 fps.
1473    codec.framerate = 10;
1474    EXPECT_TRUE(SetOneCodec(codec));
1475    EXPECT_TRUE(WaitAndSendFrame(0));  // Should be rendered.
1476    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1477    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1478    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be rendered.
1479    frame_count += 2;
1480    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1481
1482    // The channel requires 8 fps. The adapter adapts to 10 fps, which is the
1483    // closest factor of 30.
1484    codec.framerate = 8;
1485    EXPECT_TRUE(SetOneCodec(codec));
1486    EXPECT_TRUE(WaitAndSendFrame(0));  // Should be rendered.
1487    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1488    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1489    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be rendered.
1490    frame_count += 2;
1491    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1492  }
1493  // Tests that we can set the send stream format properly.
1494  void SetSendStreamFormat() {
1495    cricket::VideoCodec codec(DefaultCodec());
1496    SendAndReceive(codec);
1497    int frame_count = 1;
1498    EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
1499
1500    // Adapt the resolution and frame rate to half.
1501    cricket::VideoFormat format(
1502        codec.width / 2,
1503        codec.height / 2,
1504        cricket::VideoFormat::FpsToInterval(codec.framerate / 2),
1505        cricket::FOURCC_I420);
1506    // The SSRC differs from the send SSRC.
1507    EXPECT_FALSE(channel_->SetSendStreamFormat(kSsrc - 1, format));
1508    EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format));
1509
1510    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1511    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be rendered.
1512    EXPECT_TRUE(WaitAndSendFrame(30));  // Should be dropped.
1513    frame_count += 1;
1514    EXPECT_FRAME_WAIT(frame_count, format.width, format.height, kTimeout);
1515
1516    // Adapt the resolution to 0x0, which should drop all frames.
1517    format.width = 0;
1518    format.height = 0;
1519    EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format));
1520    EXPECT_TRUE(SendFrame());
1521    EXPECT_TRUE(SendFrame());
1522    talk_base::Thread::Current()->ProcessMessages(500);
1523    EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1524  }
1525  // Test that setting send stream format to 0x0 resolution will result in
1526  // frames being dropped.
1527  void SetSendStreamFormat0x0() {
1528    EXPECT_TRUE(SetOneCodec(DefaultCodec()));
1529    EXPECT_TRUE(SetSend(true));
1530    EXPECT_TRUE(channel_->SetRender(true));
1531    EXPECT_EQ(0, renderer_.num_rendered_frames());
1532    // This frame should be received.
1533    EXPECT_TRUE(SendFrame());
1534    EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
1535    const int64 interval = cricket::VideoFormat::FpsToInterval(
1536        DefaultCodec().framerate);
1537    cricket::VideoFormat format(
1538        0,
1539        0,
1540        interval,
1541        cricket::FOURCC_I420);
1542    EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format));
1543    // This frame should not be received.
1544    EXPECT_TRUE(WaitAndSendFrame(
1545        static_cast<int>(interval/talk_base::kNumNanosecsPerMillisec)));
1546    talk_base::Thread::Current()->ProcessMessages(500);
1547    EXPECT_EQ(1, renderer_.num_rendered_frames());
1548  }
1549
1550  // Tests that we can mute and unmute the channel properly.
1551  void MuteStream() {
1552    int frame_count = 0;
1553    EXPECT_TRUE(SetDefaultCodec());
1554    cricket::FakeVideoCapturer video_capturer;
1555    video_capturer.Start(
1556        cricket::VideoFormat(
1557            640, 480,
1558            cricket::VideoFormat::FpsToInterval(30),
1559            cricket::FOURCC_I420));
1560    EXPECT_TRUE(channel_->SetCapturer(kSsrc, &video_capturer));
1561    EXPECT_TRUE(SetSend(true));
1562    EXPECT_TRUE(channel_->SetRender(true));
1563    EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
1564
1565    // Mute the channel and expect black output frame.
1566    EXPECT_TRUE(channel_->MuteStream(kSsrc, true));
1567    EXPECT_TRUE(video_capturer.CaptureFrame());
1568    ++frame_count;
1569    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1570    EXPECT_TRUE(renderer_.black_frame());
1571
1572    // Unmute the channel and expect non-black output frame.
1573    EXPECT_TRUE(channel_->MuteStream(kSsrc, false));
1574    EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1575    EXPECT_TRUE(video_capturer.CaptureFrame());
1576    ++frame_count;
1577    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1578    EXPECT_FALSE(renderer_.black_frame());
1579
1580    // Test that we can also Mute using the correct send stream SSRC.
1581    EXPECT_TRUE(channel_->MuteStream(kSsrc, true));
1582    EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1583    EXPECT_TRUE(video_capturer.CaptureFrame());
1584    ++frame_count;
1585    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1586    EXPECT_TRUE(renderer_.black_frame());
1587
1588    EXPECT_TRUE(channel_->MuteStream(kSsrc, false));
1589    EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30));
1590    EXPECT_TRUE(video_capturer.CaptureFrame());
1591    ++frame_count;
1592    EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1593    EXPECT_FALSE(renderer_.black_frame());
1594
1595    // Test that muting an invalid stream fails.
1596    EXPECT_FALSE(channel_->MuteStream(kSsrc+1, true));
1597    EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
1598  }
1599
1600  // Test that multiple send streams can be created and deleted properly.
1601  void MultipleSendStreams() {
1602    // Remove stream added in Setup. I.e. remove stream corresponding to default
1603    // channel.
1604    EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1605    const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]);
1606    for (unsigned int i = 0; i < kSsrcsSize; ++i) {
1607      EXPECT_TRUE(channel_->AddSendStream(
1608          cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
1609    }
1610    // Delete one of the non default channel streams, let the destructor delete
1611    // the remaining ones.
1612    EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1613    // Stream should already be deleted.
1614    EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1615  }
1616
1617
1618  // Two streams one channel tests.
1619
1620  // Tests that we can send and receive frames.
1621  void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) {
1622    SetUpSecondStream();
1623    // Test sending and receiving on first stream.
1624    SendAndReceive(codec);
1625    // Test sending and receiving on second stream.
1626    EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
1627    EXPECT_EQ(2, NumRtpPackets());
1628    EXPECT_EQ(1, renderer2_.num_rendered_frames());
1629  }
1630
1631  // Disconnect the first stream and re-use it with another SSRC
1632  void TwoStreamsReUseFirstStream(const cricket::VideoCodec& codec) {
1633    SetUpSecondStream();
1634    EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc));
1635    EXPECT_FALSE(channel_->RemoveRecvStream(kSsrc));
1636    // SSRC 0 should map to the "default" stream. I.e. the first added stream.
1637    EXPECT_TRUE(channel_->RemoveSendStream(0));
1638    // Make sure that the first added stream was indeed the "default" stream.
1639    EXPECT_FALSE(channel_->RemoveSendStream(kSsrc));
1640    // Make sure that the "default" stream is indeed removed and that removing
1641    // the default stream has an effect.
1642    EXPECT_FALSE(channel_->RemoveSendStream(0));
1643
1644    SetRendererAsDefault();
1645    EXPECT_TRUE(channel_->AddSendStream(
1646        cricket::StreamParams::CreateLegacy(kSsrc)));
1647    EXPECT_FALSE(channel_->AddSendStream(
1648        cricket::StreamParams::CreateLegacy(kSsrc)));
1649    EXPECT_TRUE(channel_->AddRecvStream(
1650        cricket::StreamParams::CreateLegacy(kSsrc)));
1651    EXPECT_FALSE(channel_->AddRecvStream(
1652        cricket::StreamParams::CreateLegacy(kSsrc)));
1653
1654    EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get()));
1655
1656    SendAndReceive(codec);
1657    EXPECT_TRUE(channel_->RemoveSendStream(0));
1658  }
1659
1660  VideoEngineOverride<E> engine_;
1661  talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_;
1662  talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
1663  talk_base::scoped_ptr<C> channel_;
1664  cricket::FakeNetworkInterface network_interface_;
1665  cricket::FakeVideoRenderer renderer_;
1666  cricket::VideoMediaChannel::Error media_error_;
1667
1668  // Used by test cases where 2 streams are run on the same channel.
1669  cricket::FakeVideoRenderer renderer2_;
1670};
1671
1672#endif  // TALK_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_  NOLINT
Note: See TracBrowser for help on using the repository browser.