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