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