blob: 31cfab5f9a9f8921e644f8112bb976d04ecc3fa7 [file] [log] [blame]
pbos@webrtc.org1d096902013-12-13 12:48:05 +00001/*
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"
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +000019#include "webrtc/common.h"
20#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
pbos@webrtc.org1d096902013-12-13 12:48:05 +000021#include "webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h"
22#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
23#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
25#include "webrtc/system_wrappers/interface/scoped_ptr.h"
26#include "webrtc/test/direct_transport.h"
27#include "webrtc/test/fake_audio_device.h"
28#include "webrtc/test/fake_decoder.h"
29#include "webrtc/test/fake_encoder.h"
30#include "webrtc/test/frame_generator.h"
31#include "webrtc/test/frame_generator_capturer.h"
32#include "webrtc/test/rtp_rtcp_observer.h"
33#include "webrtc/test/testsupport/fileutils.h"
34#include "webrtc/test/testsupport/perf_test.h"
35#include "webrtc/video/transport_adapter.h"
36#include "webrtc/voice_engine/include/voe_base.h"
37#include "webrtc/voice_engine/include/voe_codec.h"
38#include "webrtc/voice_engine/include/voe_network.h"
39#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
40#include "webrtc/voice_engine/include/voe_video_sync.h"
41
42namespace webrtc {
43
44static unsigned int kLongTimeoutMs = 120 * 1000;
45static const uint32_t kSendSsrc = 0x654321;
46static const uint32_t kReceiverLocalSsrc = 0x123456;
47static const uint8_t kSendPayloadType = 125;
48
49class CallPerfTest : public ::testing::Test {
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000050 public:
51 CallPerfTest()
52 : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000053
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000054 protected:
55 VideoSendStream::Config GetSendTestConfig(Call* call) {
56 VideoSendStream::Config config = call->GetDefaultSendConfig();
57 config.encoder = &fake_encoder_;
58 config.internal_source = false;
59 config.rtp.ssrcs.push_back(kSendSsrc);
60 test::FakeEncoder::SetCodecSettings(&config.codec, 1);
61 config.codec.plType = kSendPayloadType;
62 return config;
63 }
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000064
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000065 void RunVideoSendTest(Call* call,
66 const VideoSendStream::Config& config,
67 test::RtpRtcpObserver* observer) {
68 send_stream_ = call->CreateVideoSendStream(config);
69 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
70 test::FrameGeneratorCapturer::Create(
71 send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
72 send_stream_->StartSending();
73 frame_generator_capturer->Start();
74
75 EXPECT_EQ(kEventSignaled, observer->Wait());
76
77 observer->StopSending();
78 frame_generator_capturer->Stop();
79 send_stream_->StopSending();
80 call->DestroyVideoSendStream(send_stream_);
81 }
82
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000083 void TestMinTransmitBitrate(bool pad_to_min_bitrate);
84
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000085 VideoSendStream* send_stream_;
86 test::FakeEncoder fake_encoder_;
pbos@webrtc.org1d096902013-12-13 12:48:05 +000087};
88
89class SyncRtcpObserver : public test::RtpRtcpObserver {
90 public:
stefan@webrtc.orgfaada6e2013-12-18 20:28:25 +000091 explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
92 : test::RtpRtcpObserver(kLongTimeoutMs, config),
pbos@webrtc.org1d096902013-12-13 12:48:05 +000093 critical_section_(CriticalSectionWrapper::CreateCriticalSection()) {}
94
95 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
96 RTCPUtility::RTCPParserV2 parser(packet, length, true);
97 EXPECT_TRUE(parser.IsValid());
98
99 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
100 packet_type != RTCPUtility::kRtcpNotValidCode;
101 packet_type = parser.Iterate()) {
102 if (packet_type == RTCPUtility::kRtcpSrCode) {
103 const RTCPUtility::RTCPPacket& packet = parser.Packet();
104 synchronization::RtcpMeasurement ntp_rtp_pair(
105 packet.SR.NTPMostSignificant,
106 packet.SR.NTPLeastSignificant,
107 packet.SR.RTPTimestamp);
108 StoreNtpRtpPair(ntp_rtp_pair);
109 }
110 }
111 return SEND_PACKET;
112 }
113
114 int64_t RtpTimestampToNtp(uint32_t timestamp) const {
115 CriticalSectionScoped cs(critical_section_.get());
116 int64_t timestamp_in_ms = -1;
117 if (ntp_rtp_pairs_.size() == 2) {
118 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
119 // RTCP sender where it sends RTCP SR before any RTP packets, which leads
120 // to a bogus NTP/RTP mapping.
121 synchronization::RtpToNtpMs(timestamp, ntp_rtp_pairs_, &timestamp_in_ms);
122 return timestamp_in_ms;
123 }
124 return -1;
125 }
126
127 private:
128 void StoreNtpRtpPair(synchronization::RtcpMeasurement ntp_rtp_pair) {
129 CriticalSectionScoped cs(critical_section_.get());
130 for (synchronization::RtcpList::iterator it = ntp_rtp_pairs_.begin();
131 it != ntp_rtp_pairs_.end();
132 ++it) {
133 if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
134 ntp_rtp_pair.ntp_frac == it->ntp_frac) {
135 // This RTCP has already been added to the list.
136 return;
137 }
138 }
139 // We need two RTCP SR reports to map between RTP and NTP. More than two
140 // will not improve the mapping.
141 if (ntp_rtp_pairs_.size() == 2) {
142 ntp_rtp_pairs_.pop_back();
143 }
144 ntp_rtp_pairs_.push_front(ntp_rtp_pair);
145 }
146
147 scoped_ptr<CriticalSectionWrapper> critical_section_;
148 synchronization::RtcpList ntp_rtp_pairs_;
149};
150
151class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
152 static const int kInSyncThresholdMs = 50;
153 static const int kStartupTimeMs = 2000;
154 static const int kMinRunTimeMs = 30000;
155
156 public:
157 VideoRtcpAndSyncObserver(Clock* clock,
158 int voe_channel,
159 VoEVideoSync* voe_sync,
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000160 SyncRtcpObserver* audio_observer,
161 bool using_new_acm)
stefan@webrtc.orgfaada6e2013-12-18 20:28:25 +0000162 : SyncRtcpObserver(FakeNetworkPipe::Config()),
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000163 clock_(clock),
164 voe_channel_(voe_channel),
165 voe_sync_(voe_sync),
166 audio_observer_(audio_observer),
167 creation_time_ms_(clock_->TimeInMilliseconds()),
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000168 first_time_in_sync_(-1),
169 using_new_acm_(using_new_acm) {}
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000170
171 virtual void RenderFrame(const I420VideoFrame& video_frame,
172 int time_to_render_ms) OVERRIDE {
173 int64_t now_ms = clock_->TimeInMilliseconds();
174 uint32_t playout_timestamp = 0;
175 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
176 return;
177 int64_t latest_audio_ntp =
178 audio_observer_->RtpTimestampToNtp(playout_timestamp);
179 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
180 if (latest_audio_ntp < 0 || latest_video_ntp < 0)
181 return;
182 int time_until_render_ms =
183 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
184 latest_video_ntp += time_until_render_ms;
185 int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
186 std::stringstream ss;
187 ss << stream_offset;
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000188 std::stringstream acm_type;
189 if (using_new_acm_) {
190 acm_type << "_acm2";
191 }
192 webrtc::test::PrintResult("stream_offset",
193 acm_type.str(),
194 "synchronization",
195 ss.str(),
196 "ms",
197 false);
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000198 int64_t time_since_creation = now_ms - creation_time_ms_;
199 // During the first couple of seconds audio and video can falsely be
200 // estimated as being synchronized. We don't want to trigger on those.
201 if (time_since_creation < kStartupTimeMs)
202 return;
pbos@webrtc.orgb5f30292014-03-13 08:53:39 +0000203 if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000204 if (first_time_in_sync_ == -1) {
205 first_time_in_sync_ = now_ms;
206 webrtc::test::PrintResult("sync_convergence_time",
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000207 acm_type.str(),
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000208 "synchronization",
209 time_since_creation,
210 "ms",
211 false);
212 }
213 if (time_since_creation > kMinRunTimeMs)
214 observation_complete_->Set();
215 }
216 }
217
218 private:
219 Clock* clock_;
220 int voe_channel_;
221 VoEVideoSync* voe_sync_;
222 SyncRtcpObserver* audio_observer_;
223 int64_t creation_time_ms_;
224 int64_t first_time_in_sync_;
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000225 bool using_new_acm_;
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000226};
227
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000228class ParamCallPerfTest : public CallPerfTest,
229 public ::testing::WithParamInterface<bool> {
230 public:
231 ParamCallPerfTest() : CallPerfTest(), use_new_acm_(GetParam()) {}
232
233 protected:
234 bool use_new_acm_;
235};
236
237TEST_P(ParamCallPerfTest, PlaysOutAudioAndVideoInSync) {
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000238 VoiceEngine* voice_engine = VoiceEngine::Create();
239 VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
240 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
241 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
242 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
243 const std::string audio_filename =
244 test::ResourcePath("voice_engine/audio_long16", "pcm");
245 ASSERT_STRNE("", audio_filename.c_str());
246 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
247 audio_filename);
248 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000249 Config config;
250 if (use_new_acm_) {
251 config.Set<webrtc::AudioCodingModuleFactory>(
252 new webrtc::NewAudioCodingModuleFactory());
253 } else {
254 config.Set<webrtc::AudioCodingModuleFactory>(
255 new webrtc::AudioCodingModuleFactory());
256 }
257 int channel = voe_base->CreateChannel(config);
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000258
stefan@webrtc.orgfaada6e2013-12-18 20:28:25 +0000259 FakeNetworkPipe::Config net_config;
260 net_config.queue_delay_ms = 500;
261 SyncRtcpObserver audio_observer(net_config);
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000262 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(),
263 channel,
264 voe_sync,
265 &audio_observer,
266 use_new_acm_);
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000267
268 Call::Config receiver_config(observer.ReceiveTransport());
269 receiver_config.voice_engine = voice_engine;
270 scoped_ptr<Call> sender_call(
271 Call::Create(Call::Config(observer.SendTransport())));
272 scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
273 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
274 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
275
276 class VoicePacketReceiver : public PacketReceiver {
277 public:
278 VoicePacketReceiver(int channel, VoENetwork* voe_network)
279 : channel_(channel),
280 voe_network_(voe_network),
281 parser_(RtpHeaderParser::Create()) {}
282 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
283 int ret;
284 if (parser_->IsRtcp(packet, static_cast<int>(length))) {
285 ret = voe_network_->ReceivedRTCPPacket(
286 channel_, packet, static_cast<unsigned int>(length));
287 } else {
288 ret = voe_network_->ReceivedRTPPacket(
289 channel_, packet, static_cast<unsigned int>(length));
290 }
291 return ret == 0;
292 }
293
294 private:
295 int channel_;
296 VoENetwork* voe_network_;
297 scoped_ptr<RtpHeaderParser> parser_;
298 } voe_packet_receiver(channel, voe_network);
299
300 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
301
302 internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000303 transport_adapter.Enable();
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000304 EXPECT_EQ(0,
305 voe_network->RegisterExternalTransport(channel, transport_adapter));
306
307 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
308
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000309 test::FakeDecoder fake_decoder;
310
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000311 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000312
313 VideoReceiveStream::Config receive_config =
314 receiver_call->GetDefaultReceiveConfig();
315 receive_config.codecs.clear();
316 receive_config.codecs.push_back(send_config.codec);
317 ExternalVideoDecoder decoder;
318 decoder.decoder = &fake_decoder;
319 decoder.payload_type = send_config.codec.plType;
320 receive_config.external_decoders.push_back(decoder);
321 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
322 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
323 receive_config.renderer = &observer;
324 receive_config.audio_channel_id = channel;
325
326 VideoSendStream* send_stream =
327 sender_call->CreateVideoSendStream(send_config);
328 VideoReceiveStream* receive_stream =
329 receiver_call->CreateVideoReceiveStream(receive_config);
330 scoped_ptr<test::FrameGeneratorCapturer> capturer(
331 test::FrameGeneratorCapturer::Create(send_stream->Input(),
332 send_config.codec.width,
333 send_config.codec.height,
334 30,
335 Clock::GetRealTimeClock()));
336 receive_stream->StartReceiving();
337 send_stream->StartSending();
338 capturer->Start();
339
340 fake_audio_device.Start();
341 EXPECT_EQ(0, voe_base->StartPlayout(channel));
342 EXPECT_EQ(0, voe_base->StartReceive(channel));
343 EXPECT_EQ(0, voe_base->StartSend(channel));
344
345 EXPECT_EQ(kEventSignaled, observer.Wait())
346 << "Timed out while waiting for audio and video to be synchronized.";
347
348 EXPECT_EQ(0, voe_base->StopSend(channel));
349 EXPECT_EQ(0, voe_base->StopReceive(channel));
350 EXPECT_EQ(0, voe_base->StopPlayout(channel));
351 fake_audio_device.Stop();
352
353 capturer->Stop();
354 send_stream->StopSending();
355 receive_stream->StopReceiving();
356 observer.StopSending();
357 audio_observer.StopSending();
358
359 voe_base->DeleteChannel(channel);
360 voe_base->Release();
361 voe_codec->Release();
362 voe_network->Release();
363 voe_sync->Release();
364 sender_call->DestroyVideoSendStream(send_stream);
365 receiver_call->DestroyVideoReceiveStream(receive_stream);
366 VoiceEngine::Delete(voice_engine);
367}
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000368
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000369// Test with both ACM1 and ACM2.
370INSTANTIATE_TEST_CASE_P(SwitchAcm, ParamCallPerfTest, ::testing::Bool());
371
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000372TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
373 // Verifies that either a normal or overuse callback is triggered.
374 class OveruseCallbackObserver : public test::RtpRtcpObserver,
375 public webrtc::OveruseCallback {
376 public:
377 OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
378
379 virtual void OnOveruse() OVERRIDE {
380 observation_complete_->Set();
381 }
382 virtual void OnNormalUse() OVERRIDE {
383 observation_complete_->Set();
384 }
385 };
386
387 OveruseCallbackObserver observer;
388 Call::Config call_config(observer.SendTransport());
389 call_config.overuse_callback = &observer;
390 scoped_ptr<Call> call(Call::Create(call_config));
391
392 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
393 RunVideoSendTest(call.get(), send_config, &observer);
394}
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000395
396void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
397 static const int kMaxEncodeBitrateKbps = 30;
398 static const int kMinTransmitBitrateKbps = 150;
399 static const int kMinAcceptableTransmitBitrate = 130;
400 static const int kMaxAcceptableTransmitBitrate = 170;
401 static const int kNumBitrateObservationsInRange = 100;
402 class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver {
403 public:
404 explicit BitrateObserver(bool using_min_transmit_bitrate)
405 : test::RtpRtcpObserver(kLongTimeoutMs),
406 send_stream_(NULL),
407 send_transport_receiver_(NULL),
408 using_min_transmit_bitrate_(using_min_transmit_bitrate),
409 num_bitrate_observations_in_range_(0) {}
410
411 virtual void SetReceivers(PacketReceiver* send_transport_receiver,
412 PacketReceiver* receive_transport_receiver)
413 OVERRIDE {
414 send_transport_receiver_ = send_transport_receiver;
415 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
416 }
417
418 void SetSendStream(VideoSendStream* send_stream) {
419 send_stream_ = send_stream;
420 }
421
422 private:
423 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
424 VideoSendStream::Stats stats = send_stream_->GetStats();
425 if (stats.substreams.size() > 0) {
426 assert(stats.substreams.size() == 1);
427 int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000;
428 if (bitrate_kbps > 0) {
429 test::PrintResult(
430 "bitrate_stats_",
431 (using_min_transmit_bitrate_ ? "min_transmit_bitrate"
432 : "without_min_transmit_bitrate"),
433 "bitrate_kbps",
434 static_cast<size_t>(bitrate_kbps),
435 "kbps",
436 false);
437 if (using_min_transmit_bitrate_) {
438 if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
439 bitrate_kbps < kMaxAcceptableTransmitBitrate) {
440 ++num_bitrate_observations_in_range_;
441 }
442 } else {
443 // Expect bitrate stats to roughly match the max encode bitrate.
444 if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 &&
445 bitrate_kbps < kMaxEncodeBitrateKbps + 5) {
446 ++num_bitrate_observations_in_range_;
447 }
448 }
449 if (num_bitrate_observations_in_range_ ==
450 kNumBitrateObservationsInRange)
451 observation_complete_->Set();
452 }
453 }
454 return send_transport_receiver_->DeliverPacket(packet, length);
455 }
456
457 VideoSendStream* send_stream_;
458 PacketReceiver* send_transport_receiver_;
459 const bool using_min_transmit_bitrate_;
460 int num_bitrate_observations_in_range_;
461 } observer(pad_to_min_bitrate);
462
463 scoped_ptr<Call> sender_call(
464 Call::Create(Call::Config(observer.SendTransport())));
465 scoped_ptr<Call> receiver_call(
466 Call::Create(Call::Config(observer.ReceiveTransport())));
467
468 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
469 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
470
471 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
472
473 send_config.pacing = true;
474 if (pad_to_min_bitrate) {
475 send_config.rtp.min_transmit_bitrate_kbps = kMinTransmitBitrateKbps;
476 } else {
477 assert(send_config.rtp.min_transmit_bitrate_kbps == 0);
478 }
479
480 VideoReceiveStream::Config receive_config =
481 receiver_call->GetDefaultReceiveConfig();
482 receive_config.codecs.clear();
483 receive_config.codecs.push_back(send_config.codec);
484 test::FakeDecoder fake_decoder;
485 ExternalVideoDecoder decoder;
486 decoder.decoder = &fake_decoder;
487 decoder.payload_type = send_config.codec.plType;
488 receive_config.external_decoders.push_back(decoder);
489 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
490 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
491
492 VideoSendStream* send_stream =
493 sender_call->CreateVideoSendStream(send_config);
494 VideoReceiveStream* receive_stream =
495 receiver_call->CreateVideoReceiveStream(receive_config);
496 scoped_ptr<test::FrameGeneratorCapturer> capturer(
497 test::FrameGeneratorCapturer::Create(send_stream->Input(),
498 send_config.codec.width,
499 send_config.codec.height,
500 30,
501 Clock::GetRealTimeClock()));
502 observer.SetSendStream(send_stream);
503 receive_stream->StartReceiving();
504 send_stream->StartSending();
505 capturer->Start();
506
507 EXPECT_EQ(kEventSignaled, observer.Wait())
508 << "Timeout while waiting for send-bitrate stats.";
509
510 send_stream->StopSending();
511 receive_stream->StopReceiving();
512 observer.StopSending();
513 capturer->Stop();
514 sender_call->DestroyVideoSendStream(send_stream);
515 receiver_call->DestroyVideoReceiveStream(receive_stream);
516}
517
518TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
519
520TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
521 TestMinTransmitBitrate(false);
522}
523
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000524} // namespace webrtc