1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 #include <assert.h> 11 12 #include <algorithm> 13 #include <sstream> 14 #include <string> 15 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 #include "webrtc/call.h" 19 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" 20 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 21 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 22 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 23 #include "webrtc/system_wrappers/interface/rtp_to_ntp.h" 24 #include "webrtc/system_wrappers/interface/scoped_ptr.h" 25 #include "webrtc/system_wrappers/interface/thread_annotations.h" 26 #include "webrtc/test/direct_transport.h" 27 #include "webrtc/test/encoder_settings.h" 28 #include "webrtc/test/fake_audio_device.h" 29 #include "webrtc/test/fake_decoder.h" 30 #include "webrtc/test/fake_encoder.h" 31 #include "webrtc/test/frame_generator.h" 32 #include "webrtc/test/frame_generator_capturer.h" 33 #include "webrtc/test/rtp_rtcp_observer.h" 34 #include "webrtc/test/testsupport/fileutils.h" 35 #include "webrtc/test/testsupport/perf_test.h" 36 #include "webrtc/video/transport_adapter.h" 37 #include "webrtc/voice_engine/include/voe_base.h" 38 #include "webrtc/voice_engine/include/voe_codec.h" 39 #include "webrtc/voice_engine/include/voe_network.h" 40 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" 41 #include "webrtc/voice_engine/include/voe_video_sync.h" 42 43 namespace webrtc { 44 45 static unsigned int kLongTimeoutMs = 120 * 1000; 46 static const uint32_t kSendSsrc = 0x654321; 47 static const uint32_t kReceiverLocalSsrc = 0x123456; 48 static const uint8_t kSendPayloadType = 125; 49 50 class CallPerfTest : public ::testing::Test { 51 public: 52 CallPerfTest() 53 : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {} 54 55 protected: 56 void CreateTestConfig(Call* call) { 57 send_config_ = call->GetDefaultSendConfig(); 58 send_config_.rtp.ssrcs.push_back(kSendSsrc); 59 send_config_.encoder_settings.encoder = &fake_encoder_; 60 send_config_.encoder_settings.payload_type = kSendPayloadType; 61 send_config_.encoder_settings.payload_name = "FAKE"; 62 video_streams_ = test::CreateVideoStreams(1); 63 } 64 65 void RunVideoSendTest(Call* call, 66 const VideoSendStream::Config& config, 67 test::RtpRtcpObserver* observer) { 68 send_stream_ = call->CreateVideoSendStream(config, video_streams_, NULL); 69 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer( 70 test::FrameGeneratorCapturer::Create( 71 send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock())); 72 send_stream_->Start(); 73 frame_generator_capturer->Start(); 74 75 EXPECT_EQ(kEventSignaled, observer->Wait()); 76 77 observer->StopSending(); 78 frame_generator_capturer->Stop(); 79 send_stream_->Stop(); 80 call->DestroyVideoSendStream(send_stream_); 81 } 82 83 void TestMinTransmitBitrate(bool pad_to_min_bitrate); 84 85 void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, 86 int threshold_ms, 87 int start_time_ms, 88 int run_time_ms); 89 90 VideoSendStream::Config send_config_; 91 std::vector<VideoStream> video_streams_; 92 VideoSendStream* send_stream_; 93 test::FakeEncoder fake_encoder_; 94 }; 95 96 class SyncRtcpObserver : public test::RtpRtcpObserver { 97 public: 98 explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config) 99 : test::RtpRtcpObserver(kLongTimeoutMs, config), 100 crit_(CriticalSectionWrapper::CreateCriticalSection()) {} 101 102 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { 103 RTCPUtility::RTCPParserV2 parser(packet, length, true); 104 EXPECT_TRUE(parser.IsValid()); 105 106 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin(); 107 packet_type != RTCPUtility::kRtcpNotValidCode; 108 packet_type = parser.Iterate()) { 109 if (packet_type == RTCPUtility::kRtcpSrCode) { 110 const RTCPUtility::RTCPPacket& packet = parser.Packet(); 111 RtcpMeasurement ntp_rtp_pair( 112 packet.SR.NTPMostSignificant, 113 packet.SR.NTPLeastSignificant, 114 packet.SR.RTPTimestamp); 115 StoreNtpRtpPair(ntp_rtp_pair); 116 } 117 } 118 return SEND_PACKET; 119 } 120 121 int64_t RtpTimestampToNtp(uint32_t timestamp) const { 122 CriticalSectionScoped lock(crit_.get()); 123 int64_t timestamp_in_ms = -1; 124 if (ntp_rtp_pairs_.size() == 2) { 125 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the 126 // RTCP sender where it sends RTCP SR before any RTP packets, which leads 127 // to a bogus NTP/RTP mapping. 128 RtpToNtpMs(timestamp, ntp_rtp_pairs_, ×tamp_in_ms); 129 return timestamp_in_ms; 130 } 131 return -1; 132 } 133 134 private: 135 void StoreNtpRtpPair(RtcpMeasurement ntp_rtp_pair) { 136 CriticalSectionScoped lock(crit_.get()); 137 for (RtcpList::iterator it = ntp_rtp_pairs_.begin(); 138 it != ntp_rtp_pairs_.end(); 139 ++it) { 140 if (ntp_rtp_pair.ntp_secs == it->ntp_secs && 141 ntp_rtp_pair.ntp_frac == it->ntp_frac) { 142 // This RTCP has already been added to the list. 143 return; 144 } 145 } 146 // We need two RTCP SR reports to map between RTP and NTP. More than two 147 // will not improve the mapping. 148 if (ntp_rtp_pairs_.size() == 2) { 149 ntp_rtp_pairs_.pop_back(); 150 } 151 ntp_rtp_pairs_.push_front(ntp_rtp_pair); 152 } 153 154 const scoped_ptr<CriticalSectionWrapper> crit_; 155 RtcpList ntp_rtp_pairs_ GUARDED_BY(crit_); 156 }; 157 158 class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer { 159 static const int kInSyncThresholdMs = 50; 160 static const int kStartupTimeMs = 2000; 161 static const int kMinRunTimeMs = 30000; 162 163 public: 164 VideoRtcpAndSyncObserver(Clock* clock, 165 int voe_channel, 166 VoEVideoSync* voe_sync, 167 SyncRtcpObserver* audio_observer) 168 : SyncRtcpObserver(FakeNetworkPipe::Config()), 169 clock_(clock), 170 voe_channel_(voe_channel), 171 voe_sync_(voe_sync), 172 audio_observer_(audio_observer), 173 creation_time_ms_(clock_->TimeInMilliseconds()), 174 first_time_in_sync_(-1) {} 175 176 virtual void RenderFrame(const I420VideoFrame& video_frame, 177 int time_to_render_ms) OVERRIDE { 178 int64_t now_ms = clock_->TimeInMilliseconds(); 179 uint32_t playout_timestamp = 0; 180 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0) 181 return; 182 int64_t latest_audio_ntp = 183 audio_observer_->RtpTimestampToNtp(playout_timestamp); 184 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp()); 185 if (latest_audio_ntp < 0 || latest_video_ntp < 0) 186 return; 187 int time_until_render_ms = 188 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms)); 189 latest_video_ntp += time_until_render_ms; 190 int64_t stream_offset = latest_audio_ntp - latest_video_ntp; 191 std::stringstream ss; 192 ss << stream_offset; 193 webrtc::test::PrintResult("stream_offset", 194 "", 195 "synchronization", 196 ss.str(), 197 "ms", 198 false); 199 int64_t time_since_creation = now_ms - creation_time_ms_; 200 // During the first couple of seconds audio and video can falsely be 201 // estimated as being synchronized. We don't want to trigger on those. 202 if (time_since_creation < kStartupTimeMs) 203 return; 204 if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) { 205 if (first_time_in_sync_ == -1) { 206 first_time_in_sync_ = now_ms; 207 webrtc::test::PrintResult("sync_convergence_time", 208 "", 209 "synchronization", 210 time_since_creation, 211 "ms", 212 false); 213 } 214 if (time_since_creation > kMinRunTimeMs) 215 observation_complete_->Set(); 216 } 217 } 218 219 private: 220 Clock* const clock_; 221 int voe_channel_; 222 VoEVideoSync* voe_sync_; 223 SyncRtcpObserver* audio_observer_; 224 int64_t creation_time_ms_; 225 int64_t first_time_in_sync_; 226 }; 227 228 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) { 229 VoiceEngine* voice_engine = VoiceEngine::Create(); 230 VoEBase* voe_base = VoEBase::GetInterface(voice_engine); 231 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine); 232 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine); 233 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine); 234 const std::string audio_filename = 235 test::ResourcePath("voice_engine/audio_long16", "pcm"); 236 ASSERT_STRNE("", audio_filename.c_str()); 237 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(), 238 audio_filename); 239 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL)); 240 int channel = voe_base->CreateChannel(); 241 242 FakeNetworkPipe::Config net_config; 243 net_config.queue_delay_ms = 500; 244 SyncRtcpObserver audio_observer(net_config); 245 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(), 246 channel, 247 voe_sync, 248 &audio_observer); 249 250 Call::Config receiver_config(observer.ReceiveTransport()); 251 receiver_config.voice_engine = voice_engine; 252 scoped_ptr<Call> sender_call( 253 Call::Create(Call::Config(observer.SendTransport()))); 254 scoped_ptr<Call> receiver_call(Call::Create(receiver_config)); 255 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000}; 256 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac)); 257 258 class VoicePacketReceiver : public PacketReceiver { 259 public: 260 VoicePacketReceiver(int channel, VoENetwork* voe_network) 261 : channel_(channel), 262 voe_network_(voe_network), 263 parser_(RtpHeaderParser::Create()) {} 264 virtual DeliveryStatus DeliverPacket(const uint8_t* packet, 265 size_t length) OVERRIDE { 266 int ret; 267 if (parser_->IsRtcp(packet, static_cast<int>(length))) { 268 ret = voe_network_->ReceivedRTCPPacket( 269 channel_, packet, static_cast<unsigned int>(length)); 270 } else { 271 ret = voe_network_->ReceivedRTPPacket( 272 channel_, packet, static_cast<unsigned int>(length), PacketTime()); 273 } 274 return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR; 275 } 276 277 private: 278 int channel_; 279 VoENetwork* voe_network_; 280 scoped_ptr<RtpHeaderParser> parser_; 281 } voe_packet_receiver(channel, voe_network); 282 283 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver); 284 285 internal::TransportAdapter transport_adapter(audio_observer.SendTransport()); 286 transport_adapter.Enable(); 287 EXPECT_EQ(0, 288 voe_network->RegisterExternalTransport(channel, transport_adapter)); 289 290 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver()); 291 292 test::FakeDecoder fake_decoder; 293 294 CreateTestConfig(sender_call.get()); 295 296 VideoReceiveStream::Config receive_config = 297 receiver_call->GetDefaultReceiveConfig(); 298 assert(receive_config.codecs.empty()); 299 VideoCodec codec = 300 test::CreateDecoderVideoCodec(send_config_.encoder_settings); 301 receive_config.codecs.push_back(codec); 302 assert(receive_config.external_decoders.empty()); 303 ExternalVideoDecoder decoder; 304 decoder.decoder = &fake_decoder; 305 decoder.payload_type = send_config_.encoder_settings.payload_type; 306 receive_config.external_decoders.push_back(decoder); 307 receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0]; 308 receive_config.rtp.local_ssrc = kReceiverLocalSsrc; 309 receive_config.renderer = &observer; 310 receive_config.audio_channel_id = channel; 311 312 VideoSendStream* send_stream = 313 sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL); 314 VideoReceiveStream* receive_stream = 315 receiver_call->CreateVideoReceiveStream(receive_config); 316 scoped_ptr<test::FrameGeneratorCapturer> capturer( 317 test::FrameGeneratorCapturer::Create(send_stream->Input(), 318 video_streams_[0].width, 319 video_streams_[0].height, 320 30, 321 Clock::GetRealTimeClock())); 322 receive_stream->Start(); 323 send_stream->Start(); 324 capturer->Start(); 325 326 fake_audio_device.Start(); 327 EXPECT_EQ(0, voe_base->StartPlayout(channel)); 328 EXPECT_EQ(0, voe_base->StartReceive(channel)); 329 EXPECT_EQ(0, voe_base->StartSend(channel)); 330 331 EXPECT_EQ(kEventSignaled, observer.Wait()) 332 << "Timed out while waiting for audio and video to be synchronized."; 333 334 EXPECT_EQ(0, voe_base->StopSend(channel)); 335 EXPECT_EQ(0, voe_base->StopReceive(channel)); 336 EXPECT_EQ(0, voe_base->StopPlayout(channel)); 337 fake_audio_device.Stop(); 338 339 capturer->Stop(); 340 send_stream->Stop(); 341 receive_stream->Stop(); 342 observer.StopSending(); 343 audio_observer.StopSending(); 344 345 voe_base->DeleteChannel(channel); 346 voe_base->Release(); 347 voe_codec->Release(); 348 voe_network->Release(); 349 voe_sync->Release(); 350 sender_call->DestroyVideoSendStream(send_stream); 351 receiver_call->DestroyVideoReceiveStream(receive_stream); 352 VoiceEngine::Delete(voice_engine); 353 } 354 355 class CaptureNtpTimeObserver : public test::RtpRtcpObserver, 356 public VideoRenderer { 357 public: 358 CaptureNtpTimeObserver(Clock* clock, 359 const FakeNetworkPipe::Config& config, 360 int threshold_ms, 361 int start_time_ms, 362 int run_time_ms) 363 : RtpRtcpObserver(kLongTimeoutMs, config), 364 clock_(clock), 365 threshold_ms_(threshold_ms), 366 start_time_ms_(start_time_ms), 367 run_time_ms_(run_time_ms), 368 creation_time_ms_(clock_->TimeInMilliseconds()), 369 capturer_(NULL), 370 rtp_start_timestamp_set_(false), 371 rtp_start_timestamp_(0) {} 372 373 virtual void RenderFrame(const I420VideoFrame& video_frame, 374 int time_to_render_ms) OVERRIDE { 375 if (video_frame.ntp_time_ms() <= 0) { 376 // Haven't got enough RTCP SR in order to calculate the capture ntp time. 377 return; 378 } 379 380 int64_t now_ms = clock_->TimeInMilliseconds(); 381 int64_t time_since_creation = now_ms - creation_time_ms_; 382 if (time_since_creation < start_time_ms_) { 383 // Wait for |start_time_ms_| before start measuring. 384 return; 385 } 386 387 if (time_since_creation > run_time_ms_) { 388 observation_complete_->Set(); 389 } 390 391 FrameCaptureTimeList::iterator iter = 392 capture_time_list_.find(video_frame.timestamp()); 393 EXPECT_TRUE(iter != capture_time_list_.end()); 394 395 // The real capture time has been wrapped to uint32_t before converted 396 // to rtp timestamp in the sender side. So here we convert the estimated 397 // capture time to a uint32_t 90k timestamp also for comparing. 398 uint32_t estimated_capture_timestamp = 399 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); 400 uint32_t real_capture_timestamp = iter->second; 401 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; 402 time_offset_ms = time_offset_ms / 90; 403 std::stringstream ss; 404 ss << time_offset_ms; 405 406 webrtc::test::PrintResult("capture_ntp_time", 407 "", 408 "real - estimated", 409 ss.str(), 410 "ms", 411 true); 412 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); 413 } 414 415 virtual Action OnSendRtp(const uint8_t* packet, size_t length) { 416 RTPHeader header; 417 EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header)); 418 419 if (!rtp_start_timestamp_set_) { 420 // Calculate the rtp timestamp offset in order to calculate the real 421 // capture time. 422 uint32_t first_capture_timestamp = 423 90 * static_cast<uint32_t>(capturer_->first_frame_capture_time()); 424 rtp_start_timestamp_ = header.timestamp - first_capture_timestamp; 425 rtp_start_timestamp_set_ = true; 426 } 427 428 uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_; 429 capture_time_list_.insert(capture_time_list_.end(), 430 std::make_pair(header.timestamp, 431 capture_timestamp)); 432 return SEND_PACKET; 433 } 434 435 void SetCapturer(test::FrameGeneratorCapturer* capturer) { 436 capturer_ = capturer; 437 } 438 439 private: 440 Clock* clock_; 441 int threshold_ms_; 442 int start_time_ms_; 443 int run_time_ms_; 444 int64_t creation_time_ms_; 445 test::FrameGeneratorCapturer* capturer_; 446 bool rtp_start_timestamp_set_; 447 uint32_t rtp_start_timestamp_; 448 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; 449 FrameCaptureTimeList capture_time_list_; 450 }; 451 452 void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, 453 int threshold_ms, 454 int start_time_ms, 455 int run_time_ms) { 456 CaptureNtpTimeObserver observer(Clock::GetRealTimeClock(), 457 net_config, 458 threshold_ms, 459 start_time_ms, 460 run_time_ms); 461 462 // Sender/receiver call. 463 Call::Config receiver_config(observer.ReceiveTransport()); 464 scoped_ptr<Call> receiver_call(Call::Create(receiver_config)); 465 scoped_ptr<Call> sender_call( 466 Call::Create(Call::Config(observer.SendTransport()))); 467 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver()); 468 469 // Configure send stream. 470 CreateTestConfig(sender_call.get()); 471 VideoSendStream* send_stream = 472 sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL); 473 scoped_ptr<test::FrameGeneratorCapturer> capturer( 474 test::FrameGeneratorCapturer::Create(send_stream->Input(), 475 video_streams_[0].width, 476 video_streams_[0].height, 477 30, 478 Clock::GetRealTimeClock())); 479 observer.SetCapturer(capturer.get()); 480 481 // Configure receive stream. 482 VideoReceiveStream::Config receive_config = 483 receiver_call->GetDefaultReceiveConfig(); 484 assert(receive_config.codecs.empty()); 485 VideoCodec codec = 486 test::CreateDecoderVideoCodec(send_config_.encoder_settings); 487 receive_config.codecs.push_back(codec); 488 assert(receive_config.external_decoders.empty()); 489 ExternalVideoDecoder decoder; 490 test::FakeDecoder fake_decoder; 491 decoder.decoder = &fake_decoder; 492 decoder.payload_type = send_config_.encoder_settings.payload_type; 493 receive_config.external_decoders.push_back(decoder); 494 receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0]; 495 receive_config.rtp.local_ssrc = kReceiverLocalSsrc; 496 receive_config.renderer = &observer; 497 // Enable the receiver side rtt calculation. 498 receive_config.rtp.rtcp_xr.receiver_reference_time_report = true; 499 VideoReceiveStream* receive_stream = 500 receiver_call->CreateVideoReceiveStream(receive_config); 501 502 // Start the test 503 receive_stream->Start(); 504 send_stream->Start(); 505 capturer->Start(); 506 507 EXPECT_EQ(kEventSignaled, observer.Wait()) 508 << "Timed out while waiting for estimated capture ntp time to be " 509 << "within bounds."; 510 511 capturer->Stop(); 512 send_stream->Stop(); 513 receive_stream->Stop(); 514 observer.StopSending(); 515 516 sender_call->DestroyVideoSendStream(send_stream); 517 receiver_call->DestroyVideoReceiveStream(receive_stream); 518 } 519 520 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { 521 FakeNetworkPipe::Config net_config; 522 net_config.queue_delay_ms = 100; 523 // TODO(wu): lower the threshold as the calculation/estimatation becomes more 524 // accurate. 525 const int kThresholdMs = 100; 526 const int kStartTimeMs = 10000; 527 const int kRunTimeMs = 20000; 528 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); 529 } 530 531 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) { 532 FakeNetworkPipe::Config net_config; 533 net_config.queue_delay_ms = 100; 534 net_config.delay_standard_deviation_ms = 10; 535 // TODO(wu): lower the threshold as the calculation/estimatation becomes more 536 // accurate. 537 const int kThresholdMs = 100; 538 const int kStartTimeMs = 10000; 539 const int kRunTimeMs = 20000; 540 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); 541 } 542 543 TEST_F(CallPerfTest, RegisterCpuOveruseObserver) { 544 // Verifies that either a normal or overuse callback is triggered. 545 class OveruseCallbackObserver : public test::RtpRtcpObserver, 546 public webrtc::OveruseCallback { 547 public: 548 OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {} 549 550 virtual void OnOveruse() OVERRIDE { 551 observation_complete_->Set(); 552 } 553 virtual void OnNormalUse() OVERRIDE { 554 observation_complete_->Set(); 555 } 556 }; 557 558 OveruseCallbackObserver observer; 559 Call::Config call_config(observer.SendTransport()); 560 call_config.overuse_callback = &observer; 561 scoped_ptr<Call> call(Call::Create(call_config)); 562 563 CreateTestConfig(call.get()); 564 RunVideoSendTest(call.get(), send_config_, &observer); 565 } 566 567 void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { 568 static const int kMaxEncodeBitrateKbps = 30; 569 static const int kMinTransmitBitrateBps = 150000; 570 static const int kMinAcceptableTransmitBitrate = 130; 571 static const int kMaxAcceptableTransmitBitrate = 170; 572 static const int kNumBitrateObservationsInRange = 100; 573 class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver { 574 public: 575 explicit BitrateObserver(bool using_min_transmit_bitrate) 576 : test::RtpRtcpObserver(kLongTimeoutMs), 577 send_stream_(NULL), 578 send_transport_receiver_(NULL), 579 using_min_transmit_bitrate_(using_min_transmit_bitrate), 580 num_bitrate_observations_in_range_(0) {} 581 582 virtual void SetReceivers(PacketReceiver* send_transport_receiver, 583 PacketReceiver* receive_transport_receiver) 584 OVERRIDE { 585 send_transport_receiver_ = send_transport_receiver; 586 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver); 587 } 588 589 void SetSendStream(VideoSendStream* send_stream) { 590 send_stream_ = send_stream; 591 } 592 593 private: 594 virtual DeliveryStatus DeliverPacket(const uint8_t* packet, 595 size_t length) OVERRIDE { 596 VideoSendStream::Stats stats = send_stream_->GetStats(); 597 if (stats.substreams.size() > 0) { 598 assert(stats.substreams.size() == 1); 599 int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000; 600 if (bitrate_kbps > 0) { 601 test::PrintResult( 602 "bitrate_stats_", 603 (using_min_transmit_bitrate_ ? "min_transmit_bitrate" 604 : "without_min_transmit_bitrate"), 605 "bitrate_kbps", 606 static_cast<size_t>(bitrate_kbps), 607 "kbps", 608 false); 609 if (using_min_transmit_bitrate_) { 610 if (bitrate_kbps > kMinAcceptableTransmitBitrate && 611 bitrate_kbps < kMaxAcceptableTransmitBitrate) { 612 ++num_bitrate_observations_in_range_; 613 } 614 } else { 615 // Expect bitrate stats to roughly match the max encode bitrate. 616 if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 && 617 bitrate_kbps < kMaxEncodeBitrateKbps + 5) { 618 ++num_bitrate_observations_in_range_; 619 } 620 } 621 if (num_bitrate_observations_in_range_ == 622 kNumBitrateObservationsInRange) 623 observation_complete_->Set(); 624 } 625 } 626 return send_transport_receiver_->DeliverPacket(packet, length); 627 } 628 629 VideoSendStream* send_stream_; 630 PacketReceiver* send_transport_receiver_; 631 const bool using_min_transmit_bitrate_; 632 int num_bitrate_observations_in_range_; 633 } observer(pad_to_min_bitrate); 634 635 scoped_ptr<Call> sender_call( 636 Call::Create(Call::Config(observer.SendTransport()))); 637 scoped_ptr<Call> receiver_call( 638 Call::Create(Call::Config(observer.ReceiveTransport()))); 639 640 CreateTestConfig(sender_call.get()); 641 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); 642 643 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver()); 644 645 if (pad_to_min_bitrate) { 646 send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; 647 } else { 648 assert(send_config_.rtp.min_transmit_bitrate_bps == 0); 649 } 650 651 VideoReceiveStream::Config receive_config = 652 receiver_call->GetDefaultReceiveConfig(); 653 receive_config.codecs.clear(); 654 VideoCodec codec = 655 test::CreateDecoderVideoCodec(send_config_.encoder_settings); 656 receive_config.codecs.push_back(codec); 657 test::FakeDecoder fake_decoder; 658 ExternalVideoDecoder decoder; 659 decoder.decoder = &fake_decoder; 660 decoder.payload_type = send_config_.encoder_settings.payload_type; 661 receive_config.external_decoders.push_back(decoder); 662 receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0]; 663 receive_config.rtp.local_ssrc = kReceiverLocalSsrc; 664 665 VideoSendStream* send_stream = 666 sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL); 667 VideoReceiveStream* receive_stream = 668 receiver_call->CreateVideoReceiveStream(receive_config); 669 scoped_ptr<test::FrameGeneratorCapturer> capturer( 670 test::FrameGeneratorCapturer::Create(send_stream->Input(), 671 video_streams_[0].width, 672 video_streams_[0].height, 673 30, 674 Clock::GetRealTimeClock())); 675 observer.SetSendStream(send_stream); 676 receive_stream->Start(); 677 send_stream->Start(); 678 capturer->Start(); 679 680 EXPECT_EQ(kEventSignaled, observer.Wait()) 681 << "Timeout while waiting for send-bitrate stats."; 682 683 send_stream->Stop(); 684 receive_stream->Stop(); 685 observer.StopSending(); 686 capturer->Stop(); 687 sender_call->DestroyVideoSendStream(send_stream); 688 receiver_call->DestroyVideoReceiveStream(receive_stream); 689 } 690 691 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } 692 693 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { 694 TestMinTransmitBitrate(false); 695 } 696 697 } // namespace webrtc 698