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 63 static const uint32 kTimeout = 5000U; 64 static const uint32 kSsrc = 1234u; 65 static const uint32 kRtxSsrc = 4321u; 66 static const uint32 kSsrcs4[] = {1, 2, 3, 4}; 67 68 inline 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 72 inline 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 78 namespace std { 79 inline 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 86 inline 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. 97 template<class T> 98 class 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 141 template<class E> 142 class 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 447 template<class E, class C> 448 class 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 // Utility method to setup an additional stream to send and receive video. 478 // Used to test send and recv between two streams. 479 void SetUpSecondStream() { 480 SetUpSecondStreamWithNoRecv(); 481 // Setup recv for second stream. 482 EXPECT_TRUE(channel_->AddRecvStream( 483 cricket::StreamParams::CreateLegacy(kSsrc + 2))); 484 // Make the second renderer available for use by a new stream. 485 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_)); 486 } 487 // Setup an additional stream just to send video. Defer add recv stream. 488 // This is required if you want to test unsignalled recv of video rtp packets. 489 void SetUpSecondStreamWithNoRecv() { 490 // SetUp() already added kSsrc make sure duplicate SSRCs cant be added. 491 EXPECT_TRUE(channel_->AddRecvStream( 492 cricket::StreamParams::CreateLegacy(kSsrc))); 493 EXPECT_FALSE(channel_->AddSendStream( 494 cricket::StreamParams::CreateLegacy(kSsrc))); 495 EXPECT_TRUE(channel_->AddSendStream( 496 cricket::StreamParams::CreateLegacy(kSsrc + 2))); 497 // We dont add recv for the second stream. 498 499 // Setup the receive and renderer for second stream after send. 500 video_capturer_2_.reset(new cricket::FakeVideoCapturer()); 501 cricket::VideoFormat format(640, 480, 502 cricket::VideoFormat::FpsToInterval(30), 503 cricket::FOURCC_I420); 504 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format)); 505 506 EXPECT_TRUE(channel_->SetCapturer(kSsrc + 2, video_capturer_2_.get())); 507 } 508 virtual void TearDown() { 509 channel_.reset(); 510 engine_.Terminate(); 511 } 512 void ConnectVideoChannelError() { 513 channel_->SignalMediaError.connect(this, 514 &VideoMediaChannelTest<E, C>::OnVideoChannelError); 515 } 516 bool SetDefaultCodec() { 517 return SetOneCodec(DefaultCodec()); 518 } 519 void SetRendererAsDefault() { 520 EXPECT_TRUE(channel_->SetRenderer(0, &renderer_)); 521 } 522 523 bool SetOneCodec(int pt, const char* name, int w, int h, int fr) { 524 return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0)); 525 } 526 bool SetOneCodec(const cricket::VideoCodec& codec) { 527 std::vector<cricket::VideoCodec> codecs; 528 codecs.push_back(codec); 529 530 cricket::VideoFormat capture_format(codec.width, codec.height, 531 cricket::VideoFormat::FpsToInterval(codec.framerate), 532 cricket::FOURCC_I420); 533 534 if (video_capturer_) { 535 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format)); 536 } 537 if (video_capturer_2_) { 538 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format)); 539 } 540 541 bool sending = channel_->sending(); 542 bool success = SetSend(false); 543 if (success) 544 success = channel_->SetSendCodecs(codecs); 545 if (success) 546 success = SetSend(sending); 547 return success; 548 } 549 bool SetSend(bool send) { 550 return channel_->SetSend(send); 551 } 552 bool SetSendStreamFormat(uint32 ssrc, const cricket::VideoCodec& codec) { 553 return channel_->SetSendStreamFormat(ssrc, cricket::VideoFormat( 554 codec.width, codec.height, 555 cricket::VideoFormat::FpsToInterval(codec.framerate), 556 cricket::FOURCC_ANY)); 557 } 558 int DrainOutgoingPackets() { 559 int packets = 0; 560 do { 561 packets = NumRtpPackets(); 562 // 100 ms should be long enough. 563 talk_base::Thread::Current()->ProcessMessages(100); 564 } while (NumRtpPackets() > packets); 565 return NumRtpPackets(); 566 } 567 bool SendFrame() { 568 if (video_capturer_2_) { 569 video_capturer_2_->CaptureFrame(); 570 } 571 return video_capturer_.get() && 572 video_capturer_->CaptureFrame(); 573 } 574 bool WaitAndSendFrame(int wait_ms) { 575 bool ret = talk_base::Thread::Current()->ProcessMessages(wait_ms); 576 ret &= SendFrame(); 577 return ret; 578 } 579 // Sends frames and waits for the decoder to be fully initialized. 580 // Returns the number of frames that were sent. 581 int WaitForDecoder() { 582 #if defined(HAVE_OPENMAX) 583 // Send enough frames for the OpenMAX decoder to continue processing, and 584 // return the number of frames sent. 585 // Send frames for a full kTimeout's worth of 15fps video. 586 int frame_count = 0; 587 while (frame_count < static_cast<int>(kTimeout) / 66) { 588 EXPECT_TRUE(WaitAndSendFrame(66)); 589 ++frame_count; 590 } 591 return frame_count; 592 #else 593 return 0; 594 #endif 595 } 596 bool SendCustomVideoFrame(int w, int h) { 597 if (!video_capturer_.get()) return false; 598 return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420); 599 } 600 int NumRtpBytes() { 601 return network_interface_.NumRtpBytes(); 602 } 603 int NumRtpBytes(uint32 ssrc) { 604 return network_interface_.NumRtpBytes(ssrc); 605 } 606 int NumRtpPackets() { 607 return network_interface_.NumRtpPackets(); 608 } 609 int NumRtpPackets(uint32 ssrc) { 610 return network_interface_.NumRtpPackets(ssrc); 611 } 612 int NumSentSsrcs() { 613 return network_interface_.NumSentSsrcs(); 614 } 615 const talk_base::Buffer* GetRtpPacket(int index) { 616 return network_interface_.GetRtpPacket(index); 617 } 618 int NumRtcpPackets() { 619 return network_interface_.NumRtcpPackets(); 620 } 621 const talk_base::Buffer* GetRtcpPacket(int index) { 622 return network_interface_.GetRtcpPacket(index); 623 } 624 static int GetPayloadType(const talk_base::Buffer* p) { 625 int pt = -1; 626 ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL); 627 return pt; 628 } 629 static bool ParseRtpPacket(const talk_base::Buffer* p, bool* x, int* pt, 630 int* seqnum, uint32* tstamp, uint32* ssrc, 631 std::string* payload) { 632 talk_base::ByteBuffer buf(p->data(), p->length()); 633 uint8 u08 = 0; 634 uint16 u16 = 0; 635 uint32 u32 = 0; 636 637 // Read X and CC fields. 638 if (!buf.ReadUInt8(&u08)) return false; 639 bool extension = ((u08 & 0x10) != 0); 640 uint8 cc = (u08 & 0x0F); 641 if (x) *x = extension; 642 643 // Read PT field. 644 if (!buf.ReadUInt8(&u08)) return false; 645 if (pt) *pt = (u08 & 0x7F); 646 647 // Read Sequence Number field. 648 if (!buf.ReadUInt16(&u16)) return false; 649 if (seqnum) *seqnum = u16; 650 651 // Read Timestamp field. 652 if (!buf.ReadUInt32(&u32)) return false; 653 if (tstamp) *tstamp = u32; 654 655 // Read SSRC field. 656 if (!buf.ReadUInt32(&u32)) return false; 657 if (ssrc) *ssrc = u32; 658 659 // Skip CSRCs. 660 for (uint8 i = 0; i < cc; ++i) { 661 if (!buf.ReadUInt32(&u32)) return false; 662 } 663 664 // Skip extension header. 665 if (extension) { 666 // Read Profile-specific extension header ID 667 if (!buf.ReadUInt16(&u16)) return false; 668 669 // Read Extension header length 670 if (!buf.ReadUInt16(&u16)) return false; 671 uint16 ext_header_len = u16; 672 673 // Read Extension header 674 for (uint16 i = 0; i < ext_header_len; ++i) { 675 if (!buf.ReadUInt32(&u32)) return false; 676 } 677 } 678 679 if (payload) { 680 return buf.ReadString(payload, buf.Length()); 681 } 682 return true; 683 } 684 685 // Parse all RTCP packet, from start_index to stop_index, and count how many 686 // FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count 687 // and return true. 688 bool CountRtcpFir(int start_index, int stop_index, int* fir_count) { 689 int count = 0; 690 for (int i = start_index; i < stop_index; ++i) { 691 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtcpPacket(i)); 692 talk_base::ByteBuffer buf(p->data(), p->length()); 693 size_t total_len = 0; 694 // The packet may be a compound RTCP packet. 695 while (total_len < p->length()) { 696 // Read FMT, type and length. 697 uint8 fmt = 0; 698 uint8 type = 0; 699 uint16 length = 0; 700 if (!buf.ReadUInt8(&fmt)) return false; 701 fmt &= 0x1F; 702 if (!buf.ReadUInt8(&type)) return false; 703 if (!buf.ReadUInt16(&length)) return false; 704 buf.Consume(length * 4); // Skip RTCP data. 705 total_len += (length + 1) * 4; 706 if ((192 == type) || ((206 == type) && (4 == fmt))) { 707 ++count; 708 } 709 } 710 } 711 712 if (fir_count) { 713 *fir_count = count; 714 } 715 return true; 716 } 717 718 void OnVideoChannelError(uint32 ssrc, 719 cricket::VideoMediaChannel::Error error) { 720 media_error_ = error; 721 } 722 723 // Test that SetSend works. 724 void SetSend() { 725 EXPECT_FALSE(channel_->sending()); 726 EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get())); 727 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 728 EXPECT_FALSE(channel_->sending()); 729 EXPECT_TRUE(SetSend(true)); 730 EXPECT_TRUE(channel_->sending()); 731 EXPECT_TRUE(SendFrame()); 732 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); 733 EXPECT_TRUE(SetSend(false)); 734 EXPECT_FALSE(channel_->sending()); 735 } 736 // Test that SetSend fails without codecs being set. 737 void SetSendWithoutCodecs() { 738 EXPECT_FALSE(channel_->sending()); 739 EXPECT_FALSE(SetSend(true)); 740 EXPECT_FALSE(channel_->sending()); 741 } 742 // Test that we properly set the send and recv buffer sizes by the time 743 // SetSend is called. 744 void SetSendSetsTransportBufferSizes() { 745 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 746 EXPECT_TRUE(SetSend(true)); 747 // TODO(sriniv): Remove or re-enable this. 748 // As part of b/8030474, send-buffer is size now controlled through 749 // portallocator flags. Its not set by channels. 750 // EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size()); 751 EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size()); 752 } 753 // Tests that we can send frames and the right payload type is used. 754 void Send(const cricket::VideoCodec& codec) { 755 EXPECT_TRUE(SetOneCodec(codec)); 756 EXPECT_TRUE(SetSend(true)); 757 EXPECT_TRUE(SendFrame()); 758 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); 759 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 760 EXPECT_EQ(codec.id, GetPayloadType(p.get())); 761 } 762 // Tests that we can send and receive frames. 763 void SendAndReceive(const cricket::VideoCodec& codec) { 764 EXPECT_TRUE(SetOneCodec(codec)); 765 EXPECT_TRUE(SetSend(true)); 766 EXPECT_TRUE(channel_->SetRender(true)); 767 EXPECT_EQ(0, renderer_.num_rendered_frames()); 768 EXPECT_TRUE(SendFrame()); 769 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); 770 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 771 EXPECT_EQ(codec.id, GetPayloadType(p.get())); 772 } 773 // Tests that we only get a VideoRenderer::SetSize() callback when needed. 774 void SendManyResizeOnce() { 775 cricket::VideoCodec codec(DefaultCodec()); 776 EXPECT_TRUE(SetOneCodec(codec)); 777 EXPECT_TRUE(SetSend(true)); 778 EXPECT_TRUE(channel_->SetRender(true)); 779 EXPECT_EQ(0, renderer_.num_rendered_frames()); 780 EXPECT_TRUE(WaitAndSendFrame(30)); 781 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); 782 EXPECT_TRUE(WaitAndSendFrame(30)); 783 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout); 784 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 785 EXPECT_EQ(codec.id, GetPayloadType(p.get())); 786 EXPECT_EQ(1, renderer_.num_set_sizes()); 787 788 codec.width /= 2; 789 codec.height /= 2; 790 EXPECT_TRUE(SetOneCodec(codec)); 791 EXPECT_TRUE(WaitAndSendFrame(30)); 792 EXPECT_FRAME_WAIT(3, codec.width, codec.height, kTimeout); 793 EXPECT_EQ(2, renderer_.num_set_sizes()); 794 } 795 void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec, 796 int duration_sec, int fps) { 797 EXPECT_TRUE(SetOneCodec(codec)); 798 EXPECT_TRUE(SetSend(true)); 799 EXPECT_TRUE(channel_->SetRender(true)); 800 EXPECT_EQ(0, renderer_.num_rendered_frames()); 801 for (int i = 0; i < duration_sec; ++i) { 802 for (int frame = 1; frame <= fps; ++frame) { 803 EXPECT_TRUE(WaitAndSendFrame(1000 / fps)); 804 EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout); 805 } 806 cricket::VideoMediaInfo info; 807 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); 808 // For webrtc, |framerate_sent| and |framerate_rcvd| depend on periodic 809 // callbacks (1 sec). 810 // Received |fraction_lost| and |packets_lost| are from sent RTCP packet. 811 // One sent packet needed (sent about once per second). 812 // |framerate_input|, |framerate_decoded| and |framerate_output| are using 813 // RateTracker. RateTracker needs to be called twice (with >1 second in 814 // b/w calls) before a framerate is calculated. 815 // Therefore insert frames (and call GetStats each sec) for a few seconds 816 // before testing stats. 817 } 818 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 819 EXPECT_EQ(codec.id, GetPayloadType(p.get())); 820 } 821 822 // Test that stats work properly for a 1-1 call. 823 void GetStats() { 824 const int kDurationSec = 3; 825 const int kFps = 10; 826 SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps); 827 828 cricket::VideoMediaInfo info; 829 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); 830 831 ASSERT_EQ(1U, info.senders.size()); 832 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload? 833 // For webrtc, bytes_sent does not include the RTP header length. 834 EXPECT_GT(info.senders[0].bytes_sent, 0); 835 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent); 836 EXPECT_EQ(0.0, info.senders[0].fraction_lost); 837 EXPECT_EQ(0, info.senders[0].firs_rcvd); 838 EXPECT_EQ(0, info.senders[0].plis_rcvd); 839 EXPECT_EQ(0, info.senders[0].nacks_rcvd); 840 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width); 841 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height); 842 EXPECT_GT(info.senders[0].framerate_input, 0); 843 EXPECT_GT(info.senders[0].framerate_sent, 0); 844 845 ASSERT_EQ(1U, info.receivers.size()); 846 EXPECT_EQ(1U, info.senders[0].ssrcs().size()); 847 EXPECT_EQ(1U, info.receivers[0].ssrcs().size()); 848 EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]); 849 EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd); 850 EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd); 851 EXPECT_EQ(0.0, info.receivers[0].fraction_lost); 852 EXPECT_EQ(0, info.receivers[0].packets_lost); 853 // TODO(asapersson): Not set for webrtc. Handle missing stats. 854 // EXPECT_EQ(0, info.receivers[0].packets_concealed); 855 EXPECT_EQ(0, info.receivers[0].firs_sent); 856 EXPECT_EQ(0, info.receivers[0].plis_sent); 857 EXPECT_EQ(0, info.receivers[0].nacks_sent); 858 EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width); 859 EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height); 860 EXPECT_GT(info.receivers[0].framerate_rcvd, 0); 861 EXPECT_GT(info.receivers[0].framerate_decoded, 0); 862 EXPECT_GT(info.receivers[0].framerate_output, 0); 863 } 864 // Test that stats work properly for a conf call with multiple recv streams. 865 void GetStatsMultipleRecvStreams() { 866 cricket::FakeVideoRenderer renderer1, renderer2; 867 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 868 cricket::VideoOptions vmo; 869 vmo.conference_mode.Set(true); 870 EXPECT_TRUE(channel_->SetOptions(vmo)); 871 EXPECT_TRUE(SetSend(true)); 872 EXPECT_TRUE(channel_->AddRecvStream( 873 cricket::StreamParams::CreateLegacy(1))); 874 EXPECT_TRUE(channel_->AddRecvStream( 875 cricket::StreamParams::CreateLegacy(2))); 876 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1)); 877 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2)); 878 EXPECT_TRUE(channel_->SetRender(true)); 879 EXPECT_EQ(0, renderer1.num_rendered_frames()); 880 EXPECT_EQ(0, renderer2.num_rendered_frames()); 881 std::vector<uint32> ssrcs; 882 ssrcs.push_back(1); 883 ssrcs.push_back(2); 884 network_interface_.SetConferenceMode(true, ssrcs); 885 EXPECT_TRUE(SendFrame()); 886 EXPECT_FRAME_ON_RENDERER_WAIT( 887 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); 888 EXPECT_FRAME_ON_RENDERER_WAIT( 889 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); 890 cricket::VideoMediaInfo info; 891 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); 892 893 ASSERT_EQ(1U, info.senders.size()); 894 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload? 895 // For webrtc, bytes_sent does not include the RTP header length. 896 EXPECT_GT(info.senders[0].bytes_sent, 0); 897 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent); 898 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width); 899 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height); 900 901 ASSERT_EQ(2U, info.receivers.size()); 902 for (size_t i = 0; i < info.receivers.size(); ++i) { 903 EXPECT_EQ(1U, info.receivers[i].ssrcs().size()); 904 EXPECT_EQ(i + 1, info.receivers[i].ssrcs()[0]); 905 EXPECT_EQ(NumRtpBytes(), info.receivers[i].bytes_rcvd); 906 EXPECT_EQ(NumRtpPackets(), info.receivers[i].packets_rcvd); 907 EXPECT_EQ(DefaultCodec().width, info.receivers[i].frame_width); 908 EXPECT_EQ(DefaultCodec().height, info.receivers[i].frame_height); 909 } 910 } 911 // Test that stats work properly for a conf call with multiple send streams. 912 void GetStatsMultipleSendStreams() { 913 // Normal setup; note that we set the SSRC explicitly to ensure that 914 // it will come first in the senders map. 915 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 916 cricket::VideoOptions vmo; 917 vmo.conference_mode.Set(true); 918 EXPECT_TRUE(channel_->SetOptions(vmo)); 919 EXPECT_TRUE(channel_->AddRecvStream( 920 cricket::StreamParams::CreateLegacy(1234))); 921 channel_->UpdateAspectRatio(640, 400); 922 EXPECT_TRUE(SetSend(true)); 923 EXPECT_TRUE(channel_->SetRender(true)); 924 EXPECT_TRUE(SendFrame()); 925 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); 926 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); 927 928 // Add an additional capturer, and hook up a renderer to receive it. 929 cricket::FakeVideoRenderer renderer1; 930 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer( 931 new cricket::FakeVideoCapturer); 932 capturer->SetScreencast(true); 933 const int kTestWidth = 160; 934 const int kTestHeight = 120; 935 cricket::VideoFormat format(kTestWidth, kTestHeight, 936 cricket::VideoFormat::FpsToInterval(5), 937 cricket::FOURCC_I420); 938 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format)); 939 EXPECT_TRUE(channel_->AddSendStream( 940 cricket::StreamParams::CreateLegacy(5678))); 941 EXPECT_TRUE(channel_->SetCapturer(5678, capturer.get())); 942 EXPECT_TRUE(channel_->AddRecvStream( 943 cricket::StreamParams::CreateLegacy(5678))); 944 EXPECT_TRUE(channel_->SetRenderer(5678, &renderer1)); 945 EXPECT_TRUE(capturer->CaptureCustomFrame( 946 kTestWidth, kTestHeight, cricket::FOURCC_I420)); 947 EXPECT_FRAME_ON_RENDERER_WAIT( 948 renderer1, 1, kTestWidth, kTestHeight, kTimeout); 949 950 // Get stats, and make sure they are correct for two senders. 951 cricket::VideoMediaInfo info; 952 EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); 953 ASSERT_EQ(2U, info.senders.size()); 954 EXPECT_EQ(NumRtpPackets(), 955 info.senders[0].packets_sent + info.senders[1].packets_sent); 956 EXPECT_EQ(1U, info.senders[0].ssrcs().size()); 957 EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]); 958 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width); 959 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height); 960 EXPECT_EQ(1U, info.senders[1].ssrcs().size()); 961 EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]); 962 EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width); 963 EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height); 964 // The capturer must be unregistered here as it runs out of it's scope next. 965 EXPECT_TRUE(channel_->SetCapturer(5678, NULL)); 966 } 967 968 // Test that we can set the bandwidth. 969 void SetSendBandwidth() { 970 EXPECT_TRUE(channel_->SetStartSendBandwidth(64 * 1024)); 971 EXPECT_TRUE(channel_->SetMaxSendBandwidth(-1)); // <= 0 means unlimited. 972 EXPECT_TRUE(channel_->SetMaxSendBandwidth(128 * 1024)); 973 } 974 // Test that we can set the SSRC for the default send source. 975 void SetSendSsrc() { 976 EXPECT_TRUE(SetDefaultCodec()); 977 EXPECT_TRUE(SetSendStreamFormat(kSsrc, DefaultCodec())); 978 EXPECT_TRUE(SetSend(true)); 979 EXPECT_TRUE(SendFrame()); 980 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); 981 uint32 ssrc = 0; 982 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 983 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL); 984 EXPECT_EQ(kSsrc, ssrc); 985 EXPECT_EQ(NumRtpPackets(), NumRtpPackets(ssrc)); 986 EXPECT_EQ(NumRtpBytes(), NumRtpBytes(ssrc)); 987 EXPECT_EQ(1, NumSentSsrcs()); 988 EXPECT_EQ(0, NumRtpPackets(kSsrc - 1)); 989 EXPECT_EQ(0, NumRtpBytes(kSsrc - 1)); 990 } 991 // Test that we can set the SSRC even after codecs are set. 992 void SetSendSsrcAfterSetCodecs() { 993 // Remove stream added in Setup. 994 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); 995 EXPECT_TRUE(SetDefaultCodec()); 996 EXPECT_TRUE(channel_->AddSendStream( 997 cricket::StreamParams::CreateLegacy(999))); 998 EXPECT_TRUE(channel_->SetCapturer(999u, video_capturer_.get())); 999 EXPECT_TRUE(SetSendStreamFormat(999u, DefaultCodec())); 1000 EXPECT_TRUE(SetSend(true)); 1001 EXPECT_TRUE(WaitAndSendFrame(0)); 1002 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); 1003 uint32 ssrc = 0; 1004 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 1005 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL); 1006 EXPECT_EQ(999u, ssrc); 1007 EXPECT_EQ(NumRtpPackets(), NumRtpPackets(ssrc)); 1008 EXPECT_EQ(NumRtpBytes(), NumRtpBytes(ssrc)); 1009 EXPECT_EQ(1, NumSentSsrcs()); 1010 EXPECT_EQ(0, NumRtpPackets(kSsrc)); 1011 EXPECT_EQ(0, NumRtpBytes(kSsrc)); 1012 } 1013 // Test that we can set the default video renderer before and after 1014 // media is received. 1015 void SetRenderer() { 1016 uint8 data1[] = { 1017 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1018 }; 1019 1020 talk_base::Buffer packet1(data1, sizeof(data1)); 1021 talk_base::SetBE32(packet1.data() + 8, kSsrc); 1022 channel_->SetRenderer(0, NULL); 1023 EXPECT_TRUE(SetDefaultCodec()); 1024 EXPECT_TRUE(SetSend(true)); 1025 EXPECT_TRUE(channel_->SetRender(true)); 1026 EXPECT_EQ(0, renderer_.num_rendered_frames()); 1027 channel_->OnPacketReceived(&packet1, talk_base::PacketTime()); 1028 SetRendererAsDefault(); 1029 EXPECT_TRUE(SendFrame()); 1030 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); 1031 } 1032 1033 // Tests empty StreamParams is rejected. 1034 void RejectEmptyStreamParams() { 1035 // Remove the send stream that was added during Setup. 1036 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); 1037 1038 cricket::StreamParams empty; 1039 EXPECT_FALSE(channel_->AddSendStream(empty)); 1040 EXPECT_TRUE(channel_->AddSendStream( 1041 cricket::StreamParams::CreateLegacy(789u))); 1042 } 1043 1044 // Tests setting up and configuring a send stream. 1045 void AddRemoveSendStreams() { 1046 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 1047 EXPECT_TRUE(SetSend(true)); 1048 EXPECT_TRUE(channel_->SetRender(true)); 1049 EXPECT_TRUE(SendFrame()); 1050 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); 1051 EXPECT_GE(2, NumRtpPackets()); 1052 uint32 ssrc = 0; 1053 size_t last_packet = NumRtpPackets() - 1; 1054 talk_base::scoped_ptr<const talk_base::Buffer> 1055 p(GetRtpPacket(static_cast<int>(last_packet))); 1056 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL); 1057 EXPECT_EQ(kSsrc, ssrc); 1058 1059 // Remove the send stream that was added during Setup. 1060 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); 1061 int rtp_packets = NumRtpPackets(); 1062 1063 EXPECT_TRUE(channel_->AddSendStream( 1064 cricket::StreamParams::CreateLegacy(789u))); 1065 EXPECT_TRUE(channel_->SetCapturer(789u, video_capturer_.get())); 1066 EXPECT_EQ(rtp_packets, NumRtpPackets()); 1067 // Wait 30ms to guarantee the engine does not drop the frame. 1068 EXPECT_TRUE(WaitAndSendFrame(30)); 1069 EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout); 1070 1071 last_packet = NumRtpPackets() - 1; 1072 p.reset(GetRtpPacket(static_cast<int>(last_packet))); 1073 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL); 1074 EXPECT_EQ(789u, ssrc); 1075 } 1076 1077 // Tests adding streams already exists returns false. 1078 void AddRecvStreamsAlreadyExist() { 1079 cricket::VideoOptions vmo; 1080 vmo.conference_mode.Set(true); 1081 EXPECT_TRUE(channel_->SetOptions(vmo)); 1082 1083 EXPECT_FALSE(channel_->AddRecvStream( 1084 cricket::StreamParams::CreateLegacy(0))); 1085 1086 EXPECT_TRUE(channel_->AddRecvStream( 1087 cricket::StreamParams::CreateLegacy(1))); 1088 EXPECT_FALSE(channel_->AddRecvStream( 1089 cricket::StreamParams::CreateLegacy(1))); 1090 1091 EXPECT_TRUE(channel_->RemoveRecvStream(1)); 1092 EXPECT_FALSE(channel_->AddRecvStream( 1093 cricket::StreamParams::CreateLegacy(0))); 1094 EXPECT_TRUE(channel_->AddRecvStream( 1095 cricket::StreamParams::CreateLegacy(1))); 1096 } 1097 1098 // Tests setting up and configuring multiple incoming streams. 1099 void AddRemoveRecvStreams() { 1100 cricket::FakeVideoRenderer renderer1, renderer2; 1101 cricket::VideoOptions vmo; 1102 vmo.conference_mode.Set(true); 1103 EXPECT_TRUE(channel_->SetOptions(vmo)); 1104 // Ensure we can't set the renderer on a non-existent stream. 1105 EXPECT_FALSE(channel_->SetRenderer(1, &renderer1)); 1106 EXPECT_FALSE(channel_->SetRenderer(2, &renderer2)); 1107 cricket::VideoRenderer* renderer; 1108 EXPECT_FALSE(channel_->GetRenderer(1, &renderer)); 1109 EXPECT_FALSE(channel_->GetRenderer(2, &renderer)); 1110 1111 // Ensure we can add streams. 1112 EXPECT_TRUE(channel_->AddRecvStream( 1113 cricket::StreamParams::CreateLegacy(1))); 1114 EXPECT_TRUE(channel_->AddRecvStream( 1115 cricket::StreamParams::CreateLegacy(2))); 1116 EXPECT_TRUE(channel_->GetRenderer(1, &renderer)); 1117 // Verify the first AddRecvStream hook up to the default renderer. 1118 EXPECT_EQ(&renderer_, renderer); 1119 EXPECT_TRUE(channel_->GetRenderer(2, &renderer)); 1120 EXPECT_TRUE(NULL == renderer); 1121 1122 // Ensure we can now set the renderers. 1123 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1)); 1124 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2)); 1125 EXPECT_TRUE(channel_->GetRenderer(1, &renderer)); 1126 EXPECT_TRUE(&renderer1 == renderer); 1127 EXPECT_TRUE(channel_->GetRenderer(2, &renderer)); 1128 EXPECT_TRUE(&renderer2 == renderer); 1129 1130 // Ensure we can change the renderers if needed. 1131 EXPECT_TRUE(channel_->SetRenderer(1, &renderer2)); 1132 EXPECT_TRUE(channel_->SetRenderer(2, &renderer1)); 1133 EXPECT_TRUE(channel_->GetRenderer(1, &renderer)); 1134 EXPECT_TRUE(&renderer2 == renderer); 1135 EXPECT_TRUE(channel_->GetRenderer(2, &renderer)); 1136 EXPECT_TRUE(&renderer1 == renderer); 1137 1138 EXPECT_TRUE(channel_->RemoveRecvStream(2)); 1139 EXPECT_TRUE(channel_->RemoveRecvStream(1)); 1140 EXPECT_FALSE(channel_->GetRenderer(1, &renderer)); 1141 EXPECT_FALSE(channel_->GetRenderer(2, &renderer)); 1142 } 1143 1144 // Tests setting up and configuring multiple incoming streams in a 1145 // non-conference call. 1146 void AddRemoveRecvStreamsNoConference() { 1147 cricket::FakeVideoRenderer renderer1, renderer2; 1148 // Ensure we can't set the renderer on a non-existent stream. 1149 EXPECT_FALSE(channel_->SetRenderer(1, &renderer1)); 1150 EXPECT_FALSE(channel_->SetRenderer(2, &renderer2)); 1151 cricket::VideoRenderer* renderer; 1152 EXPECT_FALSE(channel_->GetRenderer(1, &renderer)); 1153 EXPECT_FALSE(channel_->GetRenderer(2, &renderer)); 1154 1155 // Ensure we can add streams. 1156 EXPECT_TRUE(channel_->AddRecvStream( 1157 cricket::StreamParams::CreateLegacy(1))); 1158 EXPECT_TRUE(channel_->AddRecvStream( 1159 cricket::StreamParams::CreateLegacy(2))); 1160 EXPECT_TRUE(channel_->GetRenderer(1, &renderer)); 1161 // Verify the first AddRecvStream hook up to the default renderer. 1162 EXPECT_EQ(&renderer_, renderer); 1163 EXPECT_TRUE(channel_->GetRenderer(2, &renderer)); 1164 EXPECT_TRUE(NULL == renderer); 1165 1166 // Ensure we can now set the renderers. 1167 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1)); 1168 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2)); 1169 EXPECT_TRUE(channel_->GetRenderer(1, &renderer)); 1170 EXPECT_TRUE(&renderer1 == renderer); 1171 EXPECT_TRUE(channel_->GetRenderer(2, &renderer)); 1172 EXPECT_TRUE(&renderer2 == renderer); 1173 1174 // Ensure we can change the renderers if needed. 1175 EXPECT_TRUE(channel_->SetRenderer(1, &renderer2)); 1176 EXPECT_TRUE(channel_->SetRenderer(2, &renderer1)); 1177 EXPECT_TRUE(channel_->GetRenderer(1, &renderer)); 1178 EXPECT_TRUE(&renderer2 == renderer); 1179 EXPECT_TRUE(channel_->GetRenderer(2, &renderer)); 1180 EXPECT_TRUE(&renderer1 == renderer); 1181 1182 EXPECT_TRUE(channel_->RemoveRecvStream(2)); 1183 EXPECT_TRUE(channel_->RemoveRecvStream(1)); 1184 EXPECT_FALSE(channel_->GetRenderer(1, &renderer)); 1185 EXPECT_FALSE(channel_->GetRenderer(2, &renderer)); 1186 } 1187 1188 // Test that no frames are rendered after the receive stream have been 1189 // removed. 1190 void AddRemoveRecvStreamAndRender() { 1191 cricket::FakeVideoRenderer renderer1; 1192 EXPECT_TRUE(SetDefaultCodec()); 1193 EXPECT_TRUE(SetSend(true)); 1194 EXPECT_TRUE(channel_->SetRender(true)); 1195 EXPECT_TRUE(channel_->AddRecvStream( 1196 cricket::StreamParams::CreateLegacy(kSsrc))); 1197 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1)); 1198 1199 EXPECT_TRUE(SendFrame()); 1200 EXPECT_FRAME_ON_RENDERER_WAIT( 1201 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); 1202 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc)); 1203 // Send three more frames. This is to avoid that the test might be flaky 1204 // due to frame dropping. 1205 for (size_t i = 0; i < 3; ++i) 1206 EXPECT_TRUE(WaitAndSendFrame(100)); 1207 1208 // Test that no more frames have been rendered. 1209 EXPECT_EQ(1, renderer1.num_rendered_frames()); 1210 1211 // Re-add the stream again and make sure it renders. 1212 EXPECT_TRUE(channel_->AddRecvStream( 1213 cricket::StreamParams::CreateLegacy(kSsrc))); 1214 // Force the next frame to be a key frame to make the receiving 1215 // decoder happy. 1216 EXPECT_TRUE(channel_->SendIntraFrame()); 1217 1218 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1)); 1219 EXPECT_TRUE(SendFrame()); 1220 // Because the default channel is used, RemoveRecvStream above is not going 1221 // to delete the channel. As a result the engine will continue to receive 1222 // and decode the 3 frames sent above. So it is possible we will receive 1223 // some (e.g. 1) of these 3 frames after the renderer is set again. 1224 EXPECT_GT_FRAME_ON_RENDERER_WAIT( 1225 renderer1, 2, DefaultCodec().width, DefaultCodec().height, kTimeout); 1226 // Detach |renderer1| before exit as there might be frames come late. 1227 EXPECT_TRUE(channel_->SetRenderer(kSsrc, NULL)); 1228 } 1229 1230 // Tests the behavior of incoming streams in a conference scenario. 1231 void SimulateConference() { 1232 cricket::FakeVideoRenderer renderer1, renderer2; 1233 EXPECT_TRUE(SetDefaultCodec()); 1234 cricket::VideoOptions vmo; 1235 vmo.conference_mode.Set(true); 1236 EXPECT_TRUE(channel_->SetOptions(vmo)); 1237 EXPECT_TRUE(SetSend(true)); 1238 EXPECT_TRUE(channel_->SetRender(true)); 1239 EXPECT_TRUE(channel_->AddRecvStream( 1240 cricket::StreamParams::CreateLegacy(1))); 1241 EXPECT_TRUE(channel_->AddRecvStream( 1242 cricket::StreamParams::CreateLegacy(2))); 1243 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1)); 1244 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2)); 1245 EXPECT_EQ(0, renderer1.num_rendered_frames()); 1246 EXPECT_EQ(0, renderer2.num_rendered_frames()); 1247 std::vector<uint32> ssrcs; 1248 ssrcs.push_back(1); 1249 ssrcs.push_back(2); 1250 network_interface_.SetConferenceMode(true, ssrcs); 1251 EXPECT_TRUE(SendFrame()); 1252 EXPECT_FRAME_ON_RENDERER_WAIT( 1253 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); 1254 EXPECT_FRAME_ON_RENDERER_WAIT( 1255 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); 1256 1257 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 1258 EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get())); 1259 EXPECT_EQ(DefaultCodec().width, renderer1.width()); 1260 EXPECT_EQ(DefaultCodec().height, renderer1.height()); 1261 EXPECT_EQ(DefaultCodec().width, renderer2.width()); 1262 EXPECT_EQ(DefaultCodec().height, renderer2.height()); 1263 EXPECT_TRUE(channel_->RemoveRecvStream(2)); 1264 EXPECT_TRUE(channel_->RemoveRecvStream(1)); 1265 } 1266 1267 // Tests that we can add and remove capturers and frames are sent out properly 1268 void AddRemoveCapturer() { 1269 cricket::VideoCodec codec = DefaultCodec(); 1270 codec.width = 320; 1271 codec.height = 240; 1272 const int time_between_send = TimeBetweenSend(codec); 1273 EXPECT_TRUE(SetOneCodec(codec)); 1274 EXPECT_TRUE(SetSend(true)); 1275 EXPECT_TRUE(channel_->SetRender(true)); 1276 EXPECT_EQ(0, renderer_.num_rendered_frames()); 1277 EXPECT_TRUE(SendFrame()); 1278 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); 1279 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer( 1280 new cricket::FakeVideoCapturer); 1281 capturer->SetScreencast(true); 1282 cricket::VideoFormat format(480, 360, 1283 cricket::VideoFormat::FpsToInterval(30), 1284 cricket::FOURCC_I420); 1285 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format)); 1286 // All capturers start generating frames with the same timestamp. ViE does 1287 // not allow the same timestamp to be used. Capture one frame before 1288 // associating the capturer with the channel. 1289 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height, 1290 cricket::FOURCC_I420)); 1291 1292 int captured_frames = 1; 1293 for (int iterations = 0; iterations < 2; ++iterations) { 1294 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get())); 1295 talk_base::Thread::Current()->ProcessMessages(time_between_send); 1296 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height, 1297 cricket::FOURCC_I420)); 1298 ++captured_frames; 1299 // Wait until frame of right size is captured. 1300 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames && 1301 format.width == renderer_.width() && 1302 format.height == renderer_.height() && 1303 !renderer_.black_frame(), kTimeout); 1304 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames); 1305 EXPECT_EQ(format.width, renderer_.width()); 1306 EXPECT_EQ(format.height, renderer_.height()); 1307 captured_frames = renderer_.num_rendered_frames() + 1; 1308 EXPECT_FALSE(renderer_.black_frame()); 1309 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL)); 1310 // Make sure a black frame is generated within the specified timeout. 1311 // The black frame should be the resolution of the send codec. 1312 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames && 1313 codec.width == renderer_.width() && 1314 codec.height == renderer_.height() && 1315 renderer_.black_frame(), kTimeout); 1316 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames); 1317 EXPECT_EQ(codec.width, renderer_.width()); 1318 EXPECT_EQ(codec.height, renderer_.height()); 1319 EXPECT_TRUE(renderer_.black_frame()); 1320 1321 // The black frame has the same timestamp as the next frame since it's 1322 // timestamp is set to the last frame's timestamp + interval. WebRTC will 1323 // not render a frame with the same timestamp so capture another frame 1324 // with the frame capturer to increment the next frame's timestamp. 1325 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height, 1326 cricket::FOURCC_I420)); 1327 } 1328 } 1329 1330 // Tests that if RemoveCapturer is called without a capturer ever being 1331 // added, the plugin shouldn't crash (and no black frame should be sent). 1332 void RemoveCapturerWithoutAdd() { 1333 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 1334 EXPECT_TRUE(SetSend(true)); 1335 EXPECT_TRUE(channel_->SetRender(true)); 1336 EXPECT_EQ(0, renderer_.num_rendered_frames()); 1337 EXPECT_TRUE(SendFrame()); 1338 EXPECT_FRAME_WAIT(1, 640, 400, kTimeout); 1339 // Remove the capturer. 1340 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL)); 1341 // Wait for one black frame for removing the capturer. 1342 EXPECT_FRAME_WAIT(2, 640, 400, kTimeout); 1343 1344 // No capturer was added, so this RemoveCapturer should 1345 // fail. 1346 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL)); 1347 talk_base::Thread::Current()->ProcessMessages(300); 1348 // Verify no more frames were sent. 1349 EXPECT_EQ(2, renderer_.num_rendered_frames()); 1350 } 1351 1352 // Tests that we can add and remove capturer as unique sources. 1353 void AddRemoveCapturerMultipleSources() { 1354 // WebRTC implementation will drop frames if pushed to quickly. Wait the 1355 // interval time to avoid that. 1356 // WebRTC implementation will drop frames if pushed to quickly. Wait the 1357 // interval time to avoid that. 1358 // Set up the stream associated with the engine. 1359 EXPECT_TRUE(channel_->AddRecvStream( 1360 cricket::StreamParams::CreateLegacy(kSsrc))); 1361 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer_)); 1362 cricket::VideoFormat capture_format; // default format 1363 capture_format.interval = cricket::VideoFormat::FpsToInterval(30); 1364 // Set up additional stream 1. 1365 cricket::FakeVideoRenderer renderer1; 1366 EXPECT_FALSE(channel_->SetRenderer(1, &renderer1)); 1367 EXPECT_TRUE(channel_->AddRecvStream( 1368 cricket::StreamParams::CreateLegacy(1))); 1369 EXPECT_TRUE(channel_->SetRenderer(1, &renderer1)); 1370 EXPECT_TRUE(channel_->AddSendStream( 1371 cricket::StreamParams::CreateLegacy(1))); 1372 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer1( 1373 new cricket::FakeVideoCapturer); 1374 capturer1->SetScreencast(true); 1375 EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format)); 1376 // Set up additional stream 2. 1377 cricket::FakeVideoRenderer renderer2; 1378 EXPECT_FALSE(channel_->SetRenderer(2, &renderer2)); 1379 EXPECT_TRUE(channel_->AddRecvStream( 1380 cricket::StreamParams::CreateLegacy(2))); 1381 EXPECT_TRUE(channel_->SetRenderer(2, &renderer2)); 1382 EXPECT_TRUE(channel_->AddSendStream( 1383 cricket::StreamParams::CreateLegacy(2))); 1384 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer2( 1385 new cricket::FakeVideoCapturer); 1386 capturer2->SetScreencast(true); 1387 EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format)); 1388 // State for all the streams. 1389 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 1390 // A limitation in the lmi implementation requires that SetCapturer() is 1391 // called after SetOneCodec(). 1392 // TODO(hellner): this seems like an unnecessary constraint, fix it. 1393 EXPECT_TRUE(channel_->SetCapturer(1, capturer1.get())); 1394 EXPECT_TRUE(channel_->SetCapturer(2, capturer2.get())); 1395 EXPECT_TRUE(SetSend(true)); 1396 EXPECT_TRUE(channel_->SetRender(true)); 1397 // Test capturer associated with engine. 1398 const int kTestWidth = 160; 1399 const int kTestHeight = 120; 1400 EXPECT_TRUE(capturer1->CaptureCustomFrame( 1401 kTestWidth, kTestHeight, cricket::FOURCC_I420)); 1402 EXPECT_FRAME_ON_RENDERER_WAIT( 1403 renderer1, 1, kTestWidth, kTestHeight, kTimeout); 1404 // Capture a frame with additional capturer2, frames should be received 1405 EXPECT_TRUE(capturer2->CaptureCustomFrame( 1406 kTestWidth, kTestHeight, cricket::FOURCC_I420)); 1407 EXPECT_FRAME_ON_RENDERER_WAIT( 1408 renderer2, 1, kTestWidth, kTestHeight, kTimeout); 1409 // Successfully remove the capturer. 1410 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL)); 1411 // Fail to re-remove the capturer. 1412 EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL)); 1413 // The capturers must be unregistered here as it runs out of it's scope 1414 // next. 1415 EXPECT_TRUE(channel_->SetCapturer(1, NULL)); 1416 EXPECT_TRUE(channel_->SetCapturer(2, NULL)); 1417 } 1418 1419 void HighAspectHighHeightCapturer() { 1420 const int kWidth = 80; 1421 const int kHeight = 10000; 1422 const int kScaledWidth = 20; 1423 const int kScaledHeight = 2500; 1424 1425 cricket::VideoCodec codec(DefaultCodec()); 1426 EXPECT_TRUE(SetOneCodec(codec)); 1427 EXPECT_TRUE(SetSend(true)); 1428 1429 cricket::FakeVideoRenderer renderer; 1430 EXPECT_TRUE(channel_->AddRecvStream( 1431 cricket::StreamParams::CreateLegacy(kSsrc))); 1432 EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer)); 1433 EXPECT_TRUE(channel_->SetRender(true)); 1434 EXPECT_EQ(0, renderer.num_rendered_frames()); 1435 1436 EXPECT_TRUE(SendFrame()); 1437 EXPECT_GT_FRAME_ON_RENDERER_WAIT( 1438 renderer, 1, codec.width, codec.height, kTimeout); 1439 1440 // Registering an external capturer is currently the same as screen casting 1441 // (update the test when this changes). 1442 talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer( 1443 new cricket::FakeVideoCapturer); 1444 capturer->SetScreencast(true); 1445 const std::vector<cricket::VideoFormat>* formats = 1446 capturer->GetSupportedFormats(); 1447 cricket::VideoFormat capture_format = (*formats)[0]; 1448 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format)); 1449 // Capture frame to not get same frame timestamps as previous capturer. 1450 capturer->CaptureFrame(); 1451 EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get())); 1452 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30)); 1453 EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight, 1454 cricket::FOURCC_ARGB)); 1455 EXPECT_TRUE(capturer->CaptureFrame()); 1456 EXPECT_GT_FRAME_ON_RENDERER_WAIT( 1457 renderer, 2, kScaledWidth, kScaledHeight, kTimeout); 1458 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL)); 1459 } 1460 1461 // Tests that we can adapt video resolution with 16:10 aspect ratio properly. 1462 void AdaptResolution16x10() { 1463 cricket::VideoCodec codec(DefaultCodec()); 1464 codec.width = 640; 1465 codec.height = 400; 1466 SendAndReceive(codec); 1467 codec.width /= 2; 1468 codec.height /= 2; 1469 // Adapt the resolution. 1470 EXPECT_TRUE(SetOneCodec(codec)); 1471 EXPECT_TRUE(WaitAndSendFrame(30)); 1472 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout); 1473 } 1474 // Tests that we can adapt video resolution with 4:3 aspect ratio properly. 1475 void AdaptResolution4x3() { 1476 cricket::VideoCodec codec(DefaultCodec()); 1477 codec.width = 640; 1478 codec.height = 400; 1479 SendAndReceive(codec); 1480 codec.width /= 2; 1481 codec.height /= 2; 1482 // Adapt the resolution. 1483 EXPECT_TRUE(SetOneCodec(codec)); 1484 EXPECT_TRUE(WaitAndSendFrame(30)); 1485 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout); 1486 } 1487 // Tests that we can drop all frames properly. 1488 void AdaptDropAllFrames() { 1489 // Set the channel codec's resolution to 0, which will require the adapter 1490 // to drop all frames. 1491 cricket::VideoCodec codec(DefaultCodec()); 1492 codec.width = codec.height = codec.framerate = 0; 1493 EXPECT_TRUE(SetOneCodec(codec)); 1494 EXPECT_TRUE(SetSend(true)); 1495 EXPECT_TRUE(channel_->SetRender(true)); 1496 EXPECT_EQ(0, renderer_.num_rendered_frames()); 1497 EXPECT_TRUE(SendFrame()); 1498 EXPECT_TRUE(SendFrame()); 1499 talk_base::Thread::Current()->ProcessMessages(500); 1500 EXPECT_EQ(0, renderer_.num_rendered_frames()); 1501 } 1502 // Tests that we can reduce the frame rate on demand properly. 1503 // TODO(fbarchard): This test is flakey on pulse. Fix and re-enable 1504 void AdaptFramerate() { 1505 cricket::VideoCodec codec(DefaultCodec()); 1506 int frame_count = 0; 1507 // The capturer runs at 30 fps. The channel requires 30 fps. 1508 EXPECT_TRUE(SetOneCodec(codec)); 1509 EXPECT_TRUE(SetSend(true)); 1510 EXPECT_TRUE(channel_->SetRender(true)); 1511 EXPECT_EQ(frame_count, renderer_.num_rendered_frames()); 1512 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. 1513 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. 1514 frame_count += 2; 1515 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout); 1516 talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(0)); 1517 EXPECT_EQ(codec.id, GetPayloadType(p.get())); 1518 1519 // The channel requires 15 fps. 1520 codec.framerate = 15; 1521 EXPECT_TRUE(SetOneCodec(codec)); 1522 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. 1523 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1524 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. 1525 frame_count += 2; 1526 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1527 1528 // The channel requires 10 fps. 1529 codec.framerate = 10; 1530 EXPECT_TRUE(SetOneCodec(codec)); 1531 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. 1532 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1533 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1534 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. 1535 frame_count += 2; 1536 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1537 1538 // The channel requires 8 fps. The adapter adapts to 10 fps, which is the 1539 // closest factor of 30. 1540 codec.framerate = 8; 1541 EXPECT_TRUE(SetOneCodec(codec)); 1542 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. 1543 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1544 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1545 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. 1546 frame_count += 2; 1547 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1548 } 1549 // Tests that we can set the send stream format properly. 1550 void SetSendStreamFormat() { 1551 cricket::VideoCodec codec(DefaultCodec()); 1552 SendAndReceive(codec); 1553 int frame_count = 1; 1554 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout); 1555 1556 // Adapt the resolution and frame rate to half. 1557 cricket::VideoFormat format( 1558 codec.width / 2, 1559 codec.height / 2, 1560 cricket::VideoFormat::FpsToInterval(codec.framerate / 2), 1561 cricket::FOURCC_I420); 1562 // The SSRC differs from the send SSRC. 1563 EXPECT_FALSE(channel_->SetSendStreamFormat(kSsrc - 1, format)); 1564 EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format)); 1565 1566 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1567 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. 1568 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. 1569 frame_count += 1; 1570 EXPECT_FRAME_WAIT(frame_count, format.width, format.height, kTimeout); 1571 1572 // Adapt the resolution to 0x0, which should drop all frames. 1573 format.width = 0; 1574 format.height = 0; 1575 EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format)); 1576 EXPECT_TRUE(SendFrame()); 1577 EXPECT_TRUE(SendFrame()); 1578 talk_base::Thread::Current()->ProcessMessages(500); 1579 EXPECT_EQ(frame_count, renderer_.num_rendered_frames()); 1580 } 1581 // Test that setting send stream format to 0x0 resolution will result in 1582 // frames being dropped. 1583 void SetSendStreamFormat0x0() { 1584 EXPECT_TRUE(SetOneCodec(DefaultCodec())); 1585 EXPECT_TRUE(SetSendStreamFormat(kSsrc, DefaultCodec())); 1586 EXPECT_TRUE(SetSend(true)); 1587 EXPECT_TRUE(channel_->SetRender(true)); 1588 EXPECT_EQ(0, renderer_.num_rendered_frames()); 1589 // This frame should be received. 1590 EXPECT_TRUE(SendFrame()); 1591 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); 1592 const int64 interval = cricket::VideoFormat::FpsToInterval( 1593 DefaultCodec().framerate); 1594 cricket::VideoFormat format( 1595 0, 1596 0, 1597 interval, 1598 cricket::FOURCC_I420); 1599 EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrc, format)); 1600 // This frame should not be received. 1601 EXPECT_TRUE(WaitAndSendFrame( 1602 static_cast<int>(interval/talk_base::kNumNanosecsPerMillisec))); 1603 talk_base::Thread::Current()->ProcessMessages(500); 1604 EXPECT_EQ(1, renderer_.num_rendered_frames()); 1605 } 1606 1607 // Tests that we can mute and unmute the channel properly. 1608 void MuteStream() { 1609 int frame_count = 0; 1610 EXPECT_TRUE(SetDefaultCodec()); 1611 cricket::FakeVideoCapturer video_capturer; 1612 video_capturer.Start( 1613 cricket::VideoFormat( 1614 640, 480, 1615 cricket::VideoFormat::FpsToInterval(30), 1616 cricket::FOURCC_I420)); 1617 EXPECT_TRUE(channel_->SetCapturer(kSsrc, &video_capturer)); 1618 EXPECT_TRUE(SetSend(true)); 1619 EXPECT_TRUE(channel_->SetRender(true)); 1620 EXPECT_EQ(frame_count, renderer_.num_rendered_frames()); 1621 1622 // Mute the channel and expect black output frame. 1623 EXPECT_TRUE(channel_->MuteStream(kSsrc, true)); 1624 EXPECT_TRUE(video_capturer.CaptureFrame()); 1625 ++frame_count; 1626 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1627 EXPECT_TRUE(renderer_.black_frame()); 1628 1629 // Unmute the channel and expect non-black output frame. 1630 EXPECT_TRUE(channel_->MuteStream(kSsrc, false)); 1631 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30)); 1632 EXPECT_TRUE(video_capturer.CaptureFrame()); 1633 ++frame_count; 1634 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1635 EXPECT_FALSE(renderer_.black_frame()); 1636 1637 // Test that we can also Mute using the correct send stream SSRC. 1638 EXPECT_TRUE(channel_->MuteStream(kSsrc, true)); 1639 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30)); 1640 EXPECT_TRUE(video_capturer.CaptureFrame()); 1641 ++frame_count; 1642 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1643 EXPECT_TRUE(renderer_.black_frame()); 1644 1645 EXPECT_TRUE(channel_->MuteStream(kSsrc, false)); 1646 EXPECT_TRUE(talk_base::Thread::Current()->ProcessMessages(30)); 1647 EXPECT_TRUE(video_capturer.CaptureFrame()); 1648 ++frame_count; 1649 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 1650 EXPECT_FALSE(renderer_.black_frame()); 1651 1652 // Test that muting an invalid stream fails. 1653 EXPECT_FALSE(channel_->MuteStream(kSsrc+1, true)); 1654 EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL)); 1655 } 1656 1657 // Test that multiple send streams can be created and deleted properly. 1658 void MultipleSendStreams() { 1659 // Remove stream added in Setup. I.e. remove stream corresponding to default 1660 // channel. 1661 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); 1662 const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]); 1663 for (unsigned int i = 0; i < kSsrcsSize; ++i) { 1664 EXPECT_TRUE(channel_->AddSendStream( 1665 cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); 1666 } 1667 // Delete one of the non default channel streams, let the destructor delete 1668 // the remaining ones. 1669 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1])); 1670 // Stream should already be deleted. 1671 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1])); 1672 } 1673 1674 1675 // Two streams one channel tests. 1676 1677 // Tests that we can send and receive frames. 1678 void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) { 1679 SetUpSecondStream(); 1680 // Test sending and receiving on first stream. 1681 SendAndReceive(codec); 1682 // Test sending and receiving on second stream. 1683 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout); 1684 EXPECT_EQ(2, NumRtpPackets()); 1685 EXPECT_EQ(1, renderer2_.num_rendered_frames()); 1686 } 1687 1688 // Set up 2 streams where the first stream uses the default channel. 1689 // Then disconnect the first stream and verify default channel becomes 1690 // available. 1691 // Then add a new stream with |new_ssrc|. The new stream should re-use the 1692 // default channel. 1693 void TwoStreamsReUseFirstStream(const cricket::VideoCodec& codec) { 1694 SetUpSecondStream(); 1695 // Default channel used by the first stream. 1696 EXPECT_EQ(kSsrc, channel_->GetDefaultChannelSsrc()); 1697 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc)); 1698 EXPECT_FALSE(channel_->RemoveRecvStream(kSsrc)); 1699 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); 1700 EXPECT_FALSE(channel_->RemoveSendStream(kSsrc)); 1701 // Default channel is no longer used by a stream. 1702 EXPECT_EQ(0u, channel_->GetDefaultChannelSsrc()); 1703 SetRendererAsDefault(); 1704 uint32 new_ssrc = kSsrc + 100; 1705 EXPECT_TRUE(channel_->AddSendStream( 1706 cricket::StreamParams::CreateLegacy(new_ssrc))); 1707 // Re-use default channel. 1708 EXPECT_EQ(new_ssrc, channel_->GetDefaultChannelSsrc()); 1709 EXPECT_FALSE(channel_->AddSendStream( 1710 cricket::StreamParams::CreateLegacy(new_ssrc))); 1711 EXPECT_TRUE(channel_->AddRecvStream( 1712 cricket::StreamParams::CreateLegacy(new_ssrc))); 1713 EXPECT_FALSE(channel_->AddRecvStream( 1714 cricket::StreamParams::CreateLegacy(new_ssrc))); 1715 1716 EXPECT_TRUE(channel_->SetCapturer(new_ssrc, video_capturer_.get())); 1717 1718 SendAndReceive(codec); 1719 EXPECT_TRUE(channel_->RemoveSendStream(new_ssrc)); 1720 EXPECT_EQ(0u, channel_->GetDefaultChannelSsrc()); 1721 } 1722 1723 // Tests that we can send and receive frames with early receive. 1724 void TwoStreamsSendAndUnsignalledRecv(const cricket::VideoCodec& codec) { 1725 cricket::VideoOptions vmo; 1726 vmo.conference_mode.Set(true); 1727 vmo.unsignalled_recv_stream_limit.Set(1); 1728 EXPECT_TRUE(channel_->SetOptions(vmo)); 1729 SetUpSecondStreamWithNoRecv(); 1730 // Test sending and receiving on first stream. 1731 EXPECT_TRUE(channel_->SetRender(true)); 1732 Send(codec); 1733 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout); 1734 EXPECT_EQ_WAIT(1, renderer_.num_rendered_frames(), kTimeout); 1735 // The first send is not expected to yield frames, because the ssrc 1736 // is not signalled yet. With unsignalled recv enabled, we will drop frames 1737 // instead of packets. 1738 EXPECT_EQ(0, renderer2_.num_rendered_frames()); 1739 // Give a chance for the decoder to process before adding the receiver. 1740 talk_base::Thread::Current()->ProcessMessages(100); 1741 // Test sending and receiving on second stream. 1742 EXPECT_TRUE(channel_->AddRecvStream( 1743 cricket::StreamParams::CreateLegacy(kSsrc + 2))); 1744 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_)); 1745 SendFrame(); 1746 EXPECT_EQ_WAIT(2, renderer_.num_rendered_frames(), kTimeout); 1747 EXPECT_EQ(4, NumRtpPackets()); 1748 // The second send is expected to yield frame as the ssrc is signalled now. 1749 // Decode should succeed here, though we received the key frame earlier. 1750 // Without early recv, we would have dropped it and decoding would have 1751 // failed. 1752 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout); 1753 } 1754 1755 // Tests that we cannot receive key frames with unsignalled recv disabled. 1756 void TwoStreamsSendAndFailUnsignalledRecv(const cricket::VideoCodec& codec) { 1757 cricket::VideoOptions vmo; 1758 vmo.conference_mode.Set(true); 1759 vmo.unsignalled_recv_stream_limit.Set(0); 1760 EXPECT_TRUE(channel_->SetOptions(vmo)); 1761 SetUpSecondStreamWithNoRecv(); 1762 // Test sending and receiving on first stream. 1763 EXPECT_TRUE(channel_->SetRender(true)); 1764 Send(codec); 1765 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout); 1766 talk_base::Thread::Current()->ProcessMessages(100); 1767 EXPECT_EQ_WAIT(1, renderer_.num_rendered_frames(), kTimeout); 1768 EXPECT_EQ_WAIT(0, renderer2_.num_rendered_frames(), kTimeout); 1769 // Give a chance for the decoder to process before adding the receiver. 1770 talk_base::Thread::Current()->ProcessMessages(10); 1771 // Test sending and receiving on second stream. 1772 EXPECT_TRUE(channel_->AddRecvStream( 1773 cricket::StreamParams::CreateLegacy(kSsrc + 2))); 1774 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_)); 1775 SendFrame(); 1776 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= 1, kTimeout); 1777 EXPECT_EQ_WAIT(4, NumRtpPackets(), kTimeout); 1778 // We dont expect any frames here, because the key frame would have been 1779 // lost in the earlier packet. This is the case we want to solve with early 1780 // receive. 1781 EXPECT_EQ(0, renderer2_.num_rendered_frames()); 1782 } 1783 1784 // Tests that we drop key frames when conference mode is disabled and we 1785 // receive rtp packets on unsignalled streams. 1786 void TwoStreamsSendAndFailUnsignalledRecvInOneToOne( 1787 const cricket::VideoCodec& codec) { 1788 cricket::VideoOptions vmo; 1789 vmo.conference_mode.Set(false); 1790 vmo.unsignalled_recv_stream_limit.Set(1); 1791 EXPECT_TRUE(channel_->SetOptions(vmo)); 1792 SetUpSecondStreamWithNoRecv(); 1793 // Test sending and receiving on first stream. 1794 EXPECT_TRUE(channel_->SetRender(true)); 1795 Send(codec); 1796 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout); 1797 // In one-to-one mode, we deliver frames to the default channel if there 1798 // is no registered recv channel for the ssrc. 1799 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= 1, kTimeout); 1800 // Give a chance for the decoder to process before adding the receiver. 1801 talk_base::Thread::Current()->ProcessMessages(100); 1802 // Test sending and receiving on second stream. 1803 EXPECT_TRUE(channel_->AddRecvStream( 1804 cricket::StreamParams::CreateLegacy(kSsrc + 2))); 1805 EXPECT_TRUE(channel_->SetRenderer(kSsrc + 2, &renderer2_)); 1806 SendFrame(); 1807 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= 1, kTimeout); 1808 EXPECT_EQ_WAIT(4, NumRtpPackets(), kTimeout); 1809 // We dont expect any frames here, because the key frame would have been 1810 // delivered to default channel. 1811 EXPECT_EQ(0, renderer2_.num_rendered_frames()); 1812 } 1813 1814 // Tests that we drop key frames when conference mode is enabled and we 1815 // receive rtp packets on unsignalled streams. Removal of a unsignalled recv 1816 // stream is successful. 1817 void TwoStreamsAddAndRemoveUnsignalledRecv( 1818 const cricket::VideoCodec& codec) { 1819 cricket::VideoOptions vmo; 1820 vmo.conference_mode.Set(true); 1821 vmo.unsignalled_recv_stream_limit.Set(1); 1822 EXPECT_TRUE(channel_->SetOptions(vmo)); 1823 SetUpSecondStreamWithNoRecv(); 1824 // Sending and receiving on first stream. 1825 EXPECT_TRUE(channel_->SetRender(true)); 1826 Send(codec); 1827 EXPECT_EQ_WAIT(2, NumRtpPackets(), kTimeout); 1828 EXPECT_EQ_WAIT(1, renderer_.num_rendered_frames(), kTimeout); 1829 // The first send is not expected to yield frames, because the ssrc 1830 // is no signalled yet. With unsignalled recv enabled, we will drop frames 1831 // instead of packets. 1832 EXPECT_EQ(0, renderer2_.num_rendered_frames()); 1833 // Give a chance for the decoder to process before adding the receiver. 1834 talk_base::Thread::Current()->ProcessMessages(100); 1835 // Ensure that we can remove the unsignalled recv stream that was created 1836 // when the first video packet with unsignalled recv ssrc is received. 1837 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc + 2)); 1838 } 1839 1840 VideoEngineOverride<E> engine_; 1841 talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_; 1842 talk_base::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_2_; 1843 talk_base::scoped_ptr<C> channel_; 1844 cricket::FakeNetworkInterface network_interface_; 1845 cricket::FakeVideoRenderer renderer_; 1846 cricket::VideoMediaChannel::Error media_error_; 1847 1848 // Used by test cases where 2 streams are run on the same channel. 1849 cricket::FakeVideoRenderer renderer2_; 1850 }; 1851 1852 #endif // TALK_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT 1853