blob: f7768fb57e60e823a9c5912afaa3caa490f2e268 [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/modules/audio_coding/main/interface/audio_coding_module.h"
pbos@webrtc.org1d096902013-12-13 12:48:05 +000020#include "webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h"
21#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
22#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
23#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24#include "webrtc/system_wrappers/interface/scoped_ptr.h"
25#include "webrtc/test/direct_transport.h"
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +000026#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org1d096902013-12-13 12:48:05 +000027#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();
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000057 config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +000058 config.encoder_settings = test::CreateEncoderSettings(
59 &fake_encoder_, "FAKE", kSendPayloadType, 1);
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000060 return config;
61 }
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000062
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000063 void RunVideoSendTest(Call* call,
64 const VideoSendStream::Config& config,
65 test::RtpRtcpObserver* observer) {
66 send_stream_ = call->CreateVideoSendStream(config);
67 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
68 test::FrameGeneratorCapturer::Create(
69 send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
70 send_stream_->StartSending();
71 frame_generator_capturer->Start();
72
73 EXPECT_EQ(kEventSignaled, observer->Wait());
74
75 observer->StopSending();
76 frame_generator_capturer->Stop();
77 send_stream_->StopSending();
78 call->DestroyVideoSendStream(send_stream_);
79 }
80
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000081 void TestMinTransmitBitrate(bool pad_to_min_bitrate);
82
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +000083 VideoSendStream* send_stream_;
84 test::FakeEncoder fake_encoder_;
pbos@webrtc.org1d096902013-12-13 12:48:05 +000085};
86
87class SyncRtcpObserver : public test::RtpRtcpObserver {
88 public:
stefan@webrtc.orgfaada6e2013-12-18 20:28:25 +000089 explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
90 : test::RtpRtcpObserver(kLongTimeoutMs, config),
pbos@webrtc.org1d096902013-12-13 12:48:05 +000091 critical_section_(CriticalSectionWrapper::CreateCriticalSection()) {}
92
93 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
94 RTCPUtility::RTCPParserV2 parser(packet, length, true);
95 EXPECT_TRUE(parser.IsValid());
96
97 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
98 packet_type != RTCPUtility::kRtcpNotValidCode;
99 packet_type = parser.Iterate()) {
100 if (packet_type == RTCPUtility::kRtcpSrCode) {
101 const RTCPUtility::RTCPPacket& packet = parser.Packet();
102 synchronization::RtcpMeasurement ntp_rtp_pair(
103 packet.SR.NTPMostSignificant,
104 packet.SR.NTPLeastSignificant,
105 packet.SR.RTPTimestamp);
106 StoreNtpRtpPair(ntp_rtp_pair);
107 }
108 }
109 return SEND_PACKET;
110 }
111
112 int64_t RtpTimestampToNtp(uint32_t timestamp) const {
113 CriticalSectionScoped cs(critical_section_.get());
114 int64_t timestamp_in_ms = -1;
115 if (ntp_rtp_pairs_.size() == 2) {
116 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
117 // RTCP sender where it sends RTCP SR before any RTP packets, which leads
118 // to a bogus NTP/RTP mapping.
119 synchronization::RtpToNtpMs(timestamp, ntp_rtp_pairs_, &timestamp_in_ms);
120 return timestamp_in_ms;
121 }
122 return -1;
123 }
124
125 private:
126 void StoreNtpRtpPair(synchronization::RtcpMeasurement ntp_rtp_pair) {
127 CriticalSectionScoped cs(critical_section_.get());
128 for (synchronization::RtcpList::iterator it = ntp_rtp_pairs_.begin();
129 it != ntp_rtp_pairs_.end();
130 ++it) {
131 if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
132 ntp_rtp_pair.ntp_frac == it->ntp_frac) {
133 // This RTCP has already been added to the list.
134 return;
135 }
136 }
137 // We need two RTCP SR reports to map between RTP and NTP. More than two
138 // will not improve the mapping.
139 if (ntp_rtp_pairs_.size() == 2) {
140 ntp_rtp_pairs_.pop_back();
141 }
142 ntp_rtp_pairs_.push_front(ntp_rtp_pair);
143 }
144
145 scoped_ptr<CriticalSectionWrapper> critical_section_;
146 synchronization::RtcpList ntp_rtp_pairs_;
147};
148
149class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
150 static const int kInSyncThresholdMs = 50;
151 static const int kStartupTimeMs = 2000;
152 static const int kMinRunTimeMs = 30000;
153
154 public:
155 VideoRtcpAndSyncObserver(Clock* clock,
156 int voe_channel,
157 VoEVideoSync* voe_sync,
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000158 SyncRtcpObserver* audio_observer)
stefan@webrtc.orgfaada6e2013-12-18 20:28:25 +0000159 : SyncRtcpObserver(FakeNetworkPipe::Config()),
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000160 clock_(clock),
161 voe_channel_(voe_channel),
162 voe_sync_(voe_sync),
163 audio_observer_(audio_observer),
164 creation_time_ms_(clock_->TimeInMilliseconds()),
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000165 first_time_in_sync_(-1) {}
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000166
167 virtual void RenderFrame(const I420VideoFrame& video_frame,
168 int time_to_render_ms) OVERRIDE {
169 int64_t now_ms = clock_->TimeInMilliseconds();
170 uint32_t playout_timestamp = 0;
171 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
172 return;
173 int64_t latest_audio_ntp =
174 audio_observer_->RtpTimestampToNtp(playout_timestamp);
175 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
176 if (latest_audio_ntp < 0 || latest_video_ntp < 0)
177 return;
178 int time_until_render_ms =
179 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
180 latest_video_ntp += time_until_render_ms;
181 int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
182 std::stringstream ss;
183 ss << stream_offset;
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000184 webrtc::test::PrintResult("stream_offset",
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000185 "",
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000186 "synchronization",
187 ss.str(),
188 "ms",
189 false);
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000190 int64_t time_since_creation = now_ms - creation_time_ms_;
191 // During the first couple of seconds audio and video can falsely be
192 // estimated as being synchronized. We don't want to trigger on those.
193 if (time_since_creation < kStartupTimeMs)
194 return;
pbos@webrtc.orgb5f30292014-03-13 08:53:39 +0000195 if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000196 if (first_time_in_sync_ == -1) {
197 first_time_in_sync_ = now_ms;
198 webrtc::test::PrintResult("sync_convergence_time",
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000199 "",
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000200 "synchronization",
201 time_since_creation,
202 "ms",
203 false);
204 }
205 if (time_since_creation > kMinRunTimeMs)
206 observation_complete_->Set();
207 }
208 }
209
210 private:
211 Clock* clock_;
212 int voe_channel_;
213 VoEVideoSync* voe_sync_;
214 SyncRtcpObserver* audio_observer_;
215 int64_t creation_time_ms_;
216 int64_t first_time_in_sync_;
217};
218
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000219TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000220 VoiceEngine* voice_engine = VoiceEngine::Create();
221 VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
222 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
223 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
224 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
225 const std::string audio_filename =
226 test::ResourcePath("voice_engine/audio_long16", "pcm");
227 ASSERT_STRNE("", audio_filename.c_str());
228 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
229 audio_filename);
230 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000231 int channel = voe_base->CreateChannel();
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000232
stefan@webrtc.orgfaada6e2013-12-18 20:28:25 +0000233 FakeNetworkPipe::Config net_config;
234 net_config.queue_delay_ms = 500;
235 SyncRtcpObserver audio_observer(net_config);
henrik.lundin@webrtc.orged865b52014-03-06 10:28:07 +0000236 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(),
237 channel,
238 voe_sync,
henrik.lundin@webrtc.orgd144bb62014-04-22 08:36:33 +0000239 &audio_observer);
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000240
241 Call::Config receiver_config(observer.ReceiveTransport());
242 receiver_config.voice_engine = voice_engine;
243 scoped_ptr<Call> sender_call(
244 Call::Create(Call::Config(observer.SendTransport())));
245 scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
246 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
247 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
248
249 class VoicePacketReceiver : public PacketReceiver {
250 public:
251 VoicePacketReceiver(int channel, VoENetwork* voe_network)
252 : channel_(channel),
253 voe_network_(voe_network),
254 parser_(RtpHeaderParser::Create()) {}
255 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
256 int ret;
257 if (parser_->IsRtcp(packet, static_cast<int>(length))) {
258 ret = voe_network_->ReceivedRTCPPacket(
259 channel_, packet, static_cast<unsigned int>(length));
260 } else {
261 ret = voe_network_->ReceivedRTPPacket(
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +0000262 channel_, packet, static_cast<unsigned int>(length), PacketTime());
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000263 }
264 return ret == 0;
265 }
266
267 private:
268 int channel_;
269 VoENetwork* voe_network_;
270 scoped_ptr<RtpHeaderParser> parser_;
271 } voe_packet_receiver(channel, voe_network);
272
273 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
274
275 internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000276 transport_adapter.Enable();
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000277 EXPECT_EQ(0,
278 voe_network->RegisterExternalTransport(channel, transport_adapter));
279
280 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
281
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000282 test::FakeDecoder fake_decoder;
283
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000284 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000285
286 VideoReceiveStream::Config receive_config =
287 receiver_call->GetDefaultReceiveConfig();
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000288 assert(receive_config.codecs.empty());
289 VideoCodec codec =
290 test::CreateDecoderVideoCodec(send_config.encoder_settings);
291 receive_config.codecs.push_back(codec);
292 assert(receive_config.external_decoders.empty());
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000293 ExternalVideoDecoder decoder;
294 decoder.decoder = &fake_decoder;
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000295 decoder.payload_type = send_config.encoder_settings.payload_type;
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000296 receive_config.external_decoders.push_back(decoder);
297 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
298 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
299 receive_config.renderer = &observer;
300 receive_config.audio_channel_id = channel;
301
302 VideoSendStream* send_stream =
303 sender_call->CreateVideoSendStream(send_config);
304 VideoReceiveStream* receive_stream =
305 receiver_call->CreateVideoReceiveStream(receive_config);
306 scoped_ptr<test::FrameGeneratorCapturer> capturer(
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000307 test::FrameGeneratorCapturer::Create(
308 send_stream->Input(),
309 send_config.encoder_settings.streams[0].width,
310 send_config.encoder_settings.streams[0].height,
311 30,
312 Clock::GetRealTimeClock()));
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000313 receive_stream->StartReceiving();
314 send_stream->StartSending();
315 capturer->Start();
316
317 fake_audio_device.Start();
318 EXPECT_EQ(0, voe_base->StartPlayout(channel));
319 EXPECT_EQ(0, voe_base->StartReceive(channel));
320 EXPECT_EQ(0, voe_base->StartSend(channel));
321
322 EXPECT_EQ(kEventSignaled, observer.Wait())
323 << "Timed out while waiting for audio and video to be synchronized.";
324
325 EXPECT_EQ(0, voe_base->StopSend(channel));
326 EXPECT_EQ(0, voe_base->StopReceive(channel));
327 EXPECT_EQ(0, voe_base->StopPlayout(channel));
328 fake_audio_device.Stop();
329
330 capturer->Stop();
331 send_stream->StopSending();
332 receive_stream->StopReceiving();
333 observer.StopSending();
334 audio_observer.StopSending();
335
336 voe_base->DeleteChannel(channel);
337 voe_base->Release();
338 voe_codec->Release();
339 voe_network->Release();
340 voe_sync->Release();
341 sender_call->DestroyVideoSendStream(send_stream);
342 receiver_call->DestroyVideoReceiveStream(receive_stream);
343 VoiceEngine::Delete(voice_engine);
344}
asapersson@webrtc.orgbdc5ed22014-01-31 10:05:07 +0000345
346TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
347 // Verifies that either a normal or overuse callback is triggered.
348 class OveruseCallbackObserver : public test::RtpRtcpObserver,
349 public webrtc::OveruseCallback {
350 public:
351 OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
352
353 virtual void OnOveruse() OVERRIDE {
354 observation_complete_->Set();
355 }
356 virtual void OnNormalUse() OVERRIDE {
357 observation_complete_->Set();
358 }
359 };
360
361 OveruseCallbackObserver observer;
362 Call::Config call_config(observer.SendTransport());
363 call_config.overuse_callback = &observer;
364 scoped_ptr<Call> call(Call::Create(call_config));
365
366 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
367 RunVideoSendTest(call.get(), send_config, &observer);
368}
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000369
370void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
371 static const int kMaxEncodeBitrateKbps = 30;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000372 static const int kMinTransmitBitrateBps = 150000;
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000373 static const int kMinAcceptableTransmitBitrate = 130;
374 static const int kMaxAcceptableTransmitBitrate = 170;
375 static const int kNumBitrateObservationsInRange = 100;
376 class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver {
377 public:
378 explicit BitrateObserver(bool using_min_transmit_bitrate)
379 : test::RtpRtcpObserver(kLongTimeoutMs),
380 send_stream_(NULL),
381 send_transport_receiver_(NULL),
382 using_min_transmit_bitrate_(using_min_transmit_bitrate),
383 num_bitrate_observations_in_range_(0) {}
384
385 virtual void SetReceivers(PacketReceiver* send_transport_receiver,
386 PacketReceiver* receive_transport_receiver)
387 OVERRIDE {
388 send_transport_receiver_ = send_transport_receiver;
389 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
390 }
391
392 void SetSendStream(VideoSendStream* send_stream) {
393 send_stream_ = send_stream;
394 }
395
396 private:
397 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
398 VideoSendStream::Stats stats = send_stream_->GetStats();
399 if (stats.substreams.size() > 0) {
400 assert(stats.substreams.size() == 1);
401 int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000;
402 if (bitrate_kbps > 0) {
403 test::PrintResult(
404 "bitrate_stats_",
405 (using_min_transmit_bitrate_ ? "min_transmit_bitrate"
406 : "without_min_transmit_bitrate"),
407 "bitrate_kbps",
408 static_cast<size_t>(bitrate_kbps),
409 "kbps",
410 false);
411 if (using_min_transmit_bitrate_) {
412 if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
413 bitrate_kbps < kMaxAcceptableTransmitBitrate) {
414 ++num_bitrate_observations_in_range_;
415 }
416 } else {
417 // Expect bitrate stats to roughly match the max encode bitrate.
418 if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 &&
419 bitrate_kbps < kMaxEncodeBitrateKbps + 5) {
420 ++num_bitrate_observations_in_range_;
421 }
422 }
423 if (num_bitrate_observations_in_range_ ==
424 kNumBitrateObservationsInRange)
425 observation_complete_->Set();
426 }
427 }
428 return send_transport_receiver_->DeliverPacket(packet, length);
429 }
430
431 VideoSendStream* send_stream_;
432 PacketReceiver* send_transport_receiver_;
433 const bool using_min_transmit_bitrate_;
434 int num_bitrate_observations_in_range_;
435 } observer(pad_to_min_bitrate);
436
437 scoped_ptr<Call> sender_call(
438 Call::Create(Call::Config(observer.SendTransport())));
439 scoped_ptr<Call> receiver_call(
440 Call::Create(Call::Config(observer.ReceiveTransport())));
441
442 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
443 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
444
445 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
446
447 send_config.pacing = true;
448 if (pad_to_min_bitrate) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000449 send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000450 } else {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000451 assert(send_config.rtp.min_transmit_bitrate_bps == 0);
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000452 }
453
454 VideoReceiveStream::Config receive_config =
455 receiver_call->GetDefaultReceiveConfig();
456 receive_config.codecs.clear();
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000457 VideoCodec codec =
458 test::CreateDecoderVideoCodec(send_config.encoder_settings);
459 receive_config.codecs.push_back(codec);
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000460 test::FakeDecoder fake_decoder;
461 ExternalVideoDecoder decoder;
462 decoder.decoder = &fake_decoder;
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000463 decoder.payload_type = send_config.encoder_settings.payload_type;
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000464 receive_config.external_decoders.push_back(decoder);
465 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
466 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
467
468 VideoSendStream* send_stream =
469 sender_call->CreateVideoSendStream(send_config);
470 VideoReceiveStream* receive_stream =
471 receiver_call->CreateVideoReceiveStream(receive_config);
472 scoped_ptr<test::FrameGeneratorCapturer> capturer(
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000473 test::FrameGeneratorCapturer::Create(
474 send_stream->Input(),
475 send_config.encoder_settings.streams[0].width,
476 send_config.encoder_settings.streams[0].height,
477 30,
478 Clock::GetRealTimeClock()));
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000479 observer.SetSendStream(send_stream);
480 receive_stream->StartReceiving();
481 send_stream->StartSending();
482 capturer->Start();
483
484 EXPECT_EQ(kEventSignaled, observer.Wait())
485 << "Timeout while waiting for send-bitrate stats.";
486
487 send_stream->StopSending();
488 receive_stream->StopReceiving();
489 observer.StopSending();
490 capturer->Stop();
491 sender_call->DestroyVideoSendStream(send_stream);
492 receiver_call->DestroyVideoReceiveStream(receive_stream);
493}
494
495TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
496
497TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
498 TestMinTransmitBitrate(false);
499}
500
pbos@webrtc.org1d096902013-12-13 12:48:05 +0000501} // namespace webrtc