2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
16 #include "testing/gtest/include/gtest/gtest.h"
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"
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;
50 class CallPerfTest : public ::testing::Test {
53 : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
56 VideoSendStream::Config GetSendTestConfig(Call* call) {
57 VideoSendStream::Config config = call->GetDefaultSendConfig();
58 config.rtp.ssrcs.push_back(kSendSsrc);
59 config.encoder_settings = test::CreateEncoderSettings(
60 &fake_encoder_, "FAKE", kSendPayloadType, 1);
64 void RunVideoSendTest(Call* call,
65 const VideoSendStream::Config& config,
66 test::RtpRtcpObserver* observer) {
67 send_stream_ = call->CreateVideoSendStream(config);
68 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
69 test::FrameGeneratorCapturer::Create(
70 send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
71 send_stream_->Start();
72 frame_generator_capturer->Start();
74 EXPECT_EQ(kEventSignaled, observer->Wait());
76 observer->StopSending();
77 frame_generator_capturer->Stop();
79 call->DestroyVideoSendStream(send_stream_);
82 void TestMinTransmitBitrate(bool pad_to_min_bitrate);
84 void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
89 VideoSendStream* send_stream_;
90 test::FakeEncoder fake_encoder_;
93 class SyncRtcpObserver : public test::RtpRtcpObserver {
95 explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
96 : test::RtpRtcpObserver(kLongTimeoutMs, config),
97 crit_(CriticalSectionWrapper::CreateCriticalSection()) {}
99 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
100 RTCPUtility::RTCPParserV2 parser(packet, length, true);
101 EXPECT_TRUE(parser.IsValid());
103 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
104 packet_type != RTCPUtility::kRtcpNotValidCode;
105 packet_type = parser.Iterate()) {
106 if (packet_type == RTCPUtility::kRtcpSrCode) {
107 const RTCPUtility::RTCPPacket& packet = parser.Packet();
108 RtcpMeasurement ntp_rtp_pair(
109 packet.SR.NTPMostSignificant,
110 packet.SR.NTPLeastSignificant,
111 packet.SR.RTPTimestamp);
112 StoreNtpRtpPair(ntp_rtp_pair);
118 int64_t RtpTimestampToNtp(uint32_t timestamp) const {
119 CriticalSectionScoped lock(crit_.get());
120 int64_t timestamp_in_ms = -1;
121 if (ntp_rtp_pairs_.size() == 2) {
122 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
123 // RTCP sender where it sends RTCP SR before any RTP packets, which leads
124 // to a bogus NTP/RTP mapping.
125 RtpToNtpMs(timestamp, ntp_rtp_pairs_, ×tamp_in_ms);
126 return timestamp_in_ms;
132 void StoreNtpRtpPair(RtcpMeasurement ntp_rtp_pair) {
133 CriticalSectionScoped lock(crit_.get());
134 for (RtcpList::iterator it = ntp_rtp_pairs_.begin();
135 it != ntp_rtp_pairs_.end();
137 if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
138 ntp_rtp_pair.ntp_frac == it->ntp_frac) {
139 // This RTCP has already been added to the list.
143 // We need two RTCP SR reports to map between RTP and NTP. More than two
144 // will not improve the mapping.
145 if (ntp_rtp_pairs_.size() == 2) {
146 ntp_rtp_pairs_.pop_back();
148 ntp_rtp_pairs_.push_front(ntp_rtp_pair);
151 const scoped_ptr<CriticalSectionWrapper> crit_;
152 RtcpList ntp_rtp_pairs_ GUARDED_BY(crit_);
155 class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
156 static const int kInSyncThresholdMs = 50;
157 static const int kStartupTimeMs = 2000;
158 static const int kMinRunTimeMs = 30000;
161 VideoRtcpAndSyncObserver(Clock* clock,
163 VoEVideoSync* voe_sync,
164 SyncRtcpObserver* audio_observer)
165 : SyncRtcpObserver(FakeNetworkPipe::Config()),
167 voe_channel_(voe_channel),
169 audio_observer_(audio_observer),
170 creation_time_ms_(clock_->TimeInMilliseconds()),
171 first_time_in_sync_(-1) {}
173 virtual void RenderFrame(const I420VideoFrame& video_frame,
174 int time_to_render_ms) OVERRIDE {
175 int64_t now_ms = clock_->TimeInMilliseconds();
176 uint32_t playout_timestamp = 0;
177 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
179 int64_t latest_audio_ntp =
180 audio_observer_->RtpTimestampToNtp(playout_timestamp);
181 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
182 if (latest_audio_ntp < 0 || latest_video_ntp < 0)
184 int time_until_render_ms =
185 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
186 latest_video_ntp += time_until_render_ms;
187 int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
188 std::stringstream ss;
190 webrtc::test::PrintResult("stream_offset",
196 int64_t time_since_creation = now_ms - creation_time_ms_;
197 // During the first couple of seconds audio and video can falsely be
198 // estimated as being synchronized. We don't want to trigger on those.
199 if (time_since_creation < kStartupTimeMs)
201 if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
202 if (first_time_in_sync_ == -1) {
203 first_time_in_sync_ = now_ms;
204 webrtc::test::PrintResult("sync_convergence_time",
211 if (time_since_creation > kMinRunTimeMs)
212 observation_complete_->Set();
219 VoEVideoSync* voe_sync_;
220 SyncRtcpObserver* audio_observer_;
221 int64_t creation_time_ms_;
222 int64_t first_time_in_sync_;
225 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
226 VoiceEngine* voice_engine = VoiceEngine::Create();
227 VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
228 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
229 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
230 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
231 const std::string audio_filename =
232 test::ResourcePath("voice_engine/audio_long16", "pcm");
233 ASSERT_STRNE("", audio_filename.c_str());
234 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
236 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
237 int channel = voe_base->CreateChannel();
239 FakeNetworkPipe::Config net_config;
240 net_config.queue_delay_ms = 500;
241 SyncRtcpObserver audio_observer(net_config);
242 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(),
247 Call::Config receiver_config(observer.ReceiveTransport());
248 receiver_config.voice_engine = voice_engine;
249 scoped_ptr<Call> sender_call(
250 Call::Create(Call::Config(observer.SendTransport())));
251 scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
252 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
253 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
255 class VoicePacketReceiver : public PacketReceiver {
257 VoicePacketReceiver(int channel, VoENetwork* voe_network)
259 voe_network_(voe_network),
260 parser_(RtpHeaderParser::Create()) {}
261 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
263 if (parser_->IsRtcp(packet, static_cast<int>(length))) {
264 ret = voe_network_->ReceivedRTCPPacket(
265 channel_, packet, static_cast<unsigned int>(length));
267 ret = voe_network_->ReceivedRTPPacket(
268 channel_, packet, static_cast<unsigned int>(length), PacketTime());
275 VoENetwork* voe_network_;
276 scoped_ptr<RtpHeaderParser> parser_;
277 } voe_packet_receiver(channel, voe_network);
279 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
281 internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
282 transport_adapter.Enable();
284 voe_network->RegisterExternalTransport(channel, transport_adapter));
286 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
288 test::FakeDecoder fake_decoder;
290 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
292 VideoReceiveStream::Config receive_config =
293 receiver_call->GetDefaultReceiveConfig();
294 assert(receive_config.codecs.empty());
296 test::CreateDecoderVideoCodec(send_config.encoder_settings);
297 receive_config.codecs.push_back(codec);
298 assert(receive_config.external_decoders.empty());
299 ExternalVideoDecoder decoder;
300 decoder.decoder = &fake_decoder;
301 decoder.payload_type = send_config.encoder_settings.payload_type;
302 receive_config.external_decoders.push_back(decoder);
303 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
304 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
305 receive_config.renderer = &observer;
306 receive_config.audio_channel_id = channel;
308 VideoSendStream* send_stream =
309 sender_call->CreateVideoSendStream(send_config);
310 VideoReceiveStream* receive_stream =
311 receiver_call->CreateVideoReceiveStream(receive_config);
312 scoped_ptr<test::FrameGeneratorCapturer> capturer(
313 test::FrameGeneratorCapturer::Create(
314 send_stream->Input(),
315 send_config.encoder_settings.streams[0].width,
316 send_config.encoder_settings.streams[0].height,
318 Clock::GetRealTimeClock()));
319 receive_stream->Start();
320 send_stream->Start();
323 fake_audio_device.Start();
324 EXPECT_EQ(0, voe_base->StartPlayout(channel));
325 EXPECT_EQ(0, voe_base->StartReceive(channel));
326 EXPECT_EQ(0, voe_base->StartSend(channel));
328 EXPECT_EQ(kEventSignaled, observer.Wait())
329 << "Timed out while waiting for audio and video to be synchronized.";
331 EXPECT_EQ(0, voe_base->StopSend(channel));
332 EXPECT_EQ(0, voe_base->StopReceive(channel));
333 EXPECT_EQ(0, voe_base->StopPlayout(channel));
334 fake_audio_device.Stop();
338 receive_stream->Stop();
339 observer.StopSending();
340 audio_observer.StopSending();
342 voe_base->DeleteChannel(channel);
344 voe_codec->Release();
345 voe_network->Release();
347 sender_call->DestroyVideoSendStream(send_stream);
348 receiver_call->DestroyVideoReceiveStream(receive_stream);
349 VoiceEngine::Delete(voice_engine);
352 class CaptureNtpTimeObserver : public test::RtpRtcpObserver,
353 public VideoRenderer {
355 CaptureNtpTimeObserver(Clock* clock,
356 const FakeNetworkPipe::Config& config,
360 : RtpRtcpObserver(kLongTimeoutMs, config),
362 threshold_ms_(threshold_ms),
363 start_time_ms_(start_time_ms),
364 run_time_ms_(run_time_ms),
365 creation_time_ms_(clock_->TimeInMilliseconds()),
367 rtp_start_timestamp_set_(false),
368 rtp_start_timestamp_(0) {}
370 virtual void RenderFrame(const I420VideoFrame& video_frame,
371 int time_to_render_ms) OVERRIDE {
372 if (video_frame.ntp_time_ms() <= 0) {
373 // Haven't got enough RTCP SR in order to calculate the capture ntp time.
377 int64_t now_ms = clock_->TimeInMilliseconds();
378 int64_t time_since_creation = now_ms - creation_time_ms_;
379 if (time_since_creation < start_time_ms_) {
380 // Wait for |start_time_ms_| before start measuring.
384 if (time_since_creation > run_time_ms_) {
385 observation_complete_->Set();
388 FrameCaptureTimeList::iterator iter =
389 capture_time_list_.find(video_frame.timestamp());
390 EXPECT_TRUE(iter != capture_time_list_.end());
392 // The real capture time has been wrapped to uint32_t before converted
393 // to rtp timestamp in the sender side. So here we convert the estimated
394 // capture time to a uint32_t 90k timestamp also for comparing.
395 uint32_t estimated_capture_timestamp =
396 90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
397 uint32_t real_capture_timestamp = iter->second;
398 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
399 time_offset_ms = time_offset_ms / 90;
400 std::stringstream ss;
401 ss << time_offset_ms;
403 webrtc::test::PrintResult("capture_ntp_time",
409 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
412 virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
414 EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
416 if (!rtp_start_timestamp_set_) {
417 // Calculate the rtp timestamp offset in order to calculate the real
419 uint32_t first_capture_timestamp =
420 90 * static_cast<uint32_t>(capturer_->first_frame_capture_time());
421 rtp_start_timestamp_ = header.timestamp - first_capture_timestamp;
422 rtp_start_timestamp_set_ = true;
425 uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
426 capture_time_list_.insert(capture_time_list_.end(),
427 std::make_pair(header.timestamp,
432 void SetCapturer(test::FrameGeneratorCapturer* capturer) {
433 capturer_ = capturer;
441 int64_t creation_time_ms_;
442 test::FrameGeneratorCapturer* capturer_;
443 bool rtp_start_timestamp_set_;
444 uint32_t rtp_start_timestamp_;
445 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
446 FrameCaptureTimeList capture_time_list_;
449 void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
453 CaptureNtpTimeObserver observer(Clock::GetRealTimeClock(),
459 // Sender/receiver call.
460 Call::Config receiver_config(observer.ReceiveTransport());
461 scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
462 scoped_ptr<Call> sender_call(
463 Call::Create(Call::Config(observer.SendTransport())));
464 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
466 // Configure send stream.
467 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
468 VideoSendStream* send_stream =
469 sender_call->CreateVideoSendStream(send_config);
470 scoped_ptr<test::FrameGeneratorCapturer> capturer(
471 test::FrameGeneratorCapturer::Create(
472 send_stream->Input(),
473 send_config.encoder_settings.streams[0].width,
474 send_config.encoder_settings.streams[0].height,
476 Clock::GetRealTimeClock()));
477 observer.SetCapturer(capturer.get());
479 // Configure receive stream.
480 VideoReceiveStream::Config receive_config =
481 receiver_call->GetDefaultReceiveConfig();
482 assert(receive_config.codecs.empty());
484 test::CreateDecoderVideoCodec(send_config.encoder_settings);
485 receive_config.codecs.push_back(codec);
486 assert(receive_config.external_decoders.empty());
487 ExternalVideoDecoder decoder;
488 test::FakeDecoder fake_decoder;
489 decoder.decoder = &fake_decoder;
490 decoder.payload_type = send_config.encoder_settings.payload_type;
491 receive_config.external_decoders.push_back(decoder);
492 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
493 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
494 receive_config.renderer = &observer;
495 // Enable the receiver side rtt calculation.
496 receive_config.rtp.rtcp_xr.receiver_reference_time_report = true;
497 VideoReceiveStream* receive_stream =
498 receiver_call->CreateVideoReceiveStream(receive_config);
501 receive_stream->Start();
502 send_stream->Start();
505 EXPECT_EQ(kEventSignaled, observer.Wait())
506 << "Timed out while waiting for estimated capture ntp time to be "
511 receive_stream->Stop();
512 observer.StopSending();
514 sender_call->DestroyVideoSendStream(send_stream);
515 receiver_call->DestroyVideoReceiveStream(receive_stream);
518 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) {
519 FakeNetworkPipe::Config net_config;
520 net_config.queue_delay_ms = 100;
521 // TODO(wu): lower the threshold as the calculation/estimatation becomes more
523 const int kThresholdMs = 30;
524 const int kStartTimeMs = 10000;
525 const int kRunTimeMs = 20000;
526 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs);
529 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) {
530 FakeNetworkPipe::Config net_config;
531 net_config.queue_delay_ms = 100;
532 net_config.delay_standard_deviation_ms = 10;
533 // TODO(wu): lower the threshold as the calculation/estimatation becomes more
535 const int kThresholdMs = 100;
536 const int kStartTimeMs = 10000;
537 const int kRunTimeMs = 20000;
538 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs);
541 TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
542 // Verifies that either a normal or overuse callback is triggered.
543 class OveruseCallbackObserver : public test::RtpRtcpObserver,
544 public webrtc::OveruseCallback {
546 OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
548 virtual void OnOveruse() OVERRIDE {
549 observation_complete_->Set();
551 virtual void OnNormalUse() OVERRIDE {
552 observation_complete_->Set();
556 OveruseCallbackObserver observer;
557 Call::Config call_config(observer.SendTransport());
558 call_config.overuse_callback = &observer;
559 scoped_ptr<Call> call(Call::Create(call_config));
561 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
562 RunVideoSendTest(call.get(), send_config, &observer);
565 void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
566 static const int kMaxEncodeBitrateKbps = 30;
567 static const int kMinTransmitBitrateBps = 150000;
568 static const int kMinAcceptableTransmitBitrate = 130;
569 static const int kMaxAcceptableTransmitBitrate = 170;
570 static const int kNumBitrateObservationsInRange = 100;
571 class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver {
573 explicit BitrateObserver(bool using_min_transmit_bitrate)
574 : test::RtpRtcpObserver(kLongTimeoutMs),
576 send_transport_receiver_(NULL),
577 using_min_transmit_bitrate_(using_min_transmit_bitrate),
578 num_bitrate_observations_in_range_(0) {}
580 virtual void SetReceivers(PacketReceiver* send_transport_receiver,
581 PacketReceiver* receive_transport_receiver)
583 send_transport_receiver_ = send_transport_receiver;
584 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
587 void SetSendStream(VideoSendStream* send_stream) {
588 send_stream_ = send_stream;
592 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
593 VideoSendStream::Stats stats = send_stream_->GetStats();
594 if (stats.substreams.size() > 0) {
595 assert(stats.substreams.size() == 1);
596 int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000;
597 if (bitrate_kbps > 0) {
600 (using_min_transmit_bitrate_ ? "min_transmit_bitrate"
601 : "without_min_transmit_bitrate"),
603 static_cast<size_t>(bitrate_kbps),
606 if (using_min_transmit_bitrate_) {
607 if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
608 bitrate_kbps < kMaxAcceptableTransmitBitrate) {
609 ++num_bitrate_observations_in_range_;
612 // Expect bitrate stats to roughly match the max encode bitrate.
613 if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 &&
614 bitrate_kbps < kMaxEncodeBitrateKbps + 5) {
615 ++num_bitrate_observations_in_range_;
618 if (num_bitrate_observations_in_range_ ==
619 kNumBitrateObservationsInRange)
620 observation_complete_->Set();
623 return send_transport_receiver_->DeliverPacket(packet, length);
626 VideoSendStream* send_stream_;
627 PacketReceiver* send_transport_receiver_;
628 const bool using_min_transmit_bitrate_;
629 int num_bitrate_observations_in_range_;
630 } observer(pad_to_min_bitrate);
632 scoped_ptr<Call> sender_call(
633 Call::Create(Call::Config(observer.SendTransport())));
634 scoped_ptr<Call> receiver_call(
635 Call::Create(Call::Config(observer.ReceiveTransport())));
637 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
638 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
640 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
642 send_config.pacing = true;
643 if (pad_to_min_bitrate) {
644 send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
646 assert(send_config.rtp.min_transmit_bitrate_bps == 0);
649 VideoReceiveStream::Config receive_config =
650 receiver_call->GetDefaultReceiveConfig();
651 receive_config.codecs.clear();
653 test::CreateDecoderVideoCodec(send_config.encoder_settings);
654 receive_config.codecs.push_back(codec);
655 test::FakeDecoder fake_decoder;
656 ExternalVideoDecoder decoder;
657 decoder.decoder = &fake_decoder;
658 decoder.payload_type = send_config.encoder_settings.payload_type;
659 receive_config.external_decoders.push_back(decoder);
660 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
661 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
663 VideoSendStream* send_stream =
664 sender_call->CreateVideoSendStream(send_config);
665 VideoReceiveStream* receive_stream =
666 receiver_call->CreateVideoReceiveStream(receive_config);
667 scoped_ptr<test::FrameGeneratorCapturer> capturer(
668 test::FrameGeneratorCapturer::Create(
669 send_stream->Input(),
670 send_config.encoder_settings.streams[0].width,
671 send_config.encoder_settings.streams[0].height,
673 Clock::GetRealTimeClock()));
674 observer.SetSendStream(send_stream);
675 receive_stream->Start();
676 send_stream->Start();
679 EXPECT_EQ(kEventSignaled, observer.Wait())
680 << "Timeout while waiting for send-bitrate stats.";
683 receive_stream->Stop();
684 observer.StopSending();
686 sender_call->DestroyVideoSendStream(send_stream);
687 receiver_call->DestroyVideoReceiveStream(receive_stream);
690 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
692 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
693 TestMinTransmitBitrate(false);
696 } // namespace webrtc