blob: 8ab07d1308ff1454639e0c5b462608c72d8693e7 [file] [log] [blame]
pbos@webrtc.orgf94ccd42013-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.org70e2ce92014-03-06 10:28:07 +000019#include "webrtc/common.h"
20#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
pbos@webrtc.orgf94ccd42013-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"
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +000027#include "webrtc/test/encoder_settings.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +000028#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
43namespace webrtc {
44
45static unsigned int kLongTimeoutMs = 120 * 1000;
46static const uint32_t kSendSsrc = 0x654321;
47static const uint32_t kReceiverLocalSsrc = 0x123456;
48static const uint8_t kSendPayloadType = 125;
49
50class CallPerfTest : public ::testing::Test {
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +000051 public:
52 CallPerfTest()
53 : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +000054
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +000055 protected:
56 VideoSendStream::Config GetSendTestConfig(Call* call) {
57 VideoSendStream::Config config = call->GetDefaultSendConfig();
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +000058 config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +000059 config.encoder_settings = test::CreateEncoderSettings(
60 &fake_encoder_, "FAKE", kSendPayloadType, 1);
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +000061 return config;
62 }
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +000063
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +000064 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_->StartSending();
72 frame_generator_capturer->Start();
73
74 EXPECT_EQ(kEventSignaled, observer->Wait());
75
76 observer->StopSending();
77 frame_generator_capturer->Stop();
78 send_stream_->StopSending();
79 call->DestroyVideoSendStream(send_stream_);
80 }
81
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +000082 void TestMinTransmitBitrate(bool pad_to_min_bitrate);
83
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +000084 VideoSendStream* send_stream_;
85 test::FakeEncoder fake_encoder_;
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +000086};
87
88class SyncRtcpObserver : public test::RtpRtcpObserver {
89 public:
stefan@webrtc.orgaacdb9f2013-12-18 20:28:25 +000090 explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
91 : test::RtpRtcpObserver(kLongTimeoutMs, config),
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +000092 critical_section_(CriticalSectionWrapper::CreateCriticalSection()) {}
93
94 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
95 RTCPUtility::RTCPParserV2 parser(packet, length, true);
96 EXPECT_TRUE(parser.IsValid());
97
98 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
99 packet_type != RTCPUtility::kRtcpNotValidCode;
100 packet_type = parser.Iterate()) {
101 if (packet_type == RTCPUtility::kRtcpSrCode) {
102 const RTCPUtility::RTCPPacket& packet = parser.Packet();
103 synchronization::RtcpMeasurement ntp_rtp_pair(
104 packet.SR.NTPMostSignificant,
105 packet.SR.NTPLeastSignificant,
106 packet.SR.RTPTimestamp);
107 StoreNtpRtpPair(ntp_rtp_pair);
108 }
109 }
110 return SEND_PACKET;
111 }
112
113 int64_t RtpTimestampToNtp(uint32_t timestamp) const {
114 CriticalSectionScoped cs(critical_section_.get());
115 int64_t timestamp_in_ms = -1;
116 if (ntp_rtp_pairs_.size() == 2) {
117 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
118 // RTCP sender where it sends RTCP SR before any RTP packets, which leads
119 // to a bogus NTP/RTP mapping.
120 synchronization::RtpToNtpMs(timestamp, ntp_rtp_pairs_, &timestamp_in_ms);
121 return timestamp_in_ms;
122 }
123 return -1;
124 }
125
126 private:
127 void StoreNtpRtpPair(synchronization::RtcpMeasurement ntp_rtp_pair) {
128 CriticalSectionScoped cs(critical_section_.get());
129 for (synchronization::RtcpList::iterator it = ntp_rtp_pairs_.begin();
130 it != ntp_rtp_pairs_.end();
131 ++it) {
132 if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
133 ntp_rtp_pair.ntp_frac == it->ntp_frac) {
134 // This RTCP has already been added to the list.
135 return;
136 }
137 }
138 // We need two RTCP SR reports to map between RTP and NTP. More than two
139 // will not improve the mapping.
140 if (ntp_rtp_pairs_.size() == 2) {
141 ntp_rtp_pairs_.pop_back();
142 }
143 ntp_rtp_pairs_.push_front(ntp_rtp_pair);
144 }
145
146 scoped_ptr<CriticalSectionWrapper> critical_section_;
147 synchronization::RtcpList ntp_rtp_pairs_;
148};
149
150class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
151 static const int kInSyncThresholdMs = 50;
152 static const int kStartupTimeMs = 2000;
153 static const int kMinRunTimeMs = 30000;
154
155 public:
156 VideoRtcpAndSyncObserver(Clock* clock,
157 int voe_channel,
158 VoEVideoSync* voe_sync,
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000159 SyncRtcpObserver* audio_observer,
160 bool using_new_acm)
stefan@webrtc.orgaacdb9f2013-12-18 20:28:25 +0000161 : SyncRtcpObserver(FakeNetworkPipe::Config()),
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000162 clock_(clock),
163 voe_channel_(voe_channel),
164 voe_sync_(voe_sync),
165 audio_observer_(audio_observer),
166 creation_time_ms_(clock_->TimeInMilliseconds()),
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000167 first_time_in_sync_(-1),
168 using_new_acm_(using_new_acm) {}
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000169
170 virtual void RenderFrame(const I420VideoFrame& video_frame,
171 int time_to_render_ms) OVERRIDE {
172 int64_t now_ms = clock_->TimeInMilliseconds();
173 uint32_t playout_timestamp = 0;
174 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
175 return;
176 int64_t latest_audio_ntp =
177 audio_observer_->RtpTimestampToNtp(playout_timestamp);
178 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
179 if (latest_audio_ntp < 0 || latest_video_ntp < 0)
180 return;
181 int time_until_render_ms =
182 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
183 latest_video_ntp += time_until_render_ms;
184 int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
185 std::stringstream ss;
186 ss << stream_offset;
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000187 std::stringstream acm_type;
188 if (using_new_acm_) {
189 acm_type << "_acm2";
190 }
191 webrtc::test::PrintResult("stream_offset",
192 acm_type.str(),
193 "synchronization",
194 ss.str(),
195 "ms",
196 false);
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000197 int64_t time_since_creation = now_ms - creation_time_ms_;
198 // During the first couple of seconds audio and video can falsely be
199 // estimated as being synchronized. We don't want to trigger on those.
200 if (time_since_creation < kStartupTimeMs)
201 return;
pbos@webrtc.org2a25b6c2014-03-13 08:53:39 +0000202 if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000203 if (first_time_in_sync_ == -1) {
204 first_time_in_sync_ = now_ms;
205 webrtc::test::PrintResult("sync_convergence_time",
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000206 acm_type.str(),
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000207 "synchronization",
208 time_since_creation,
209 "ms",
210 false);
211 }
212 if (time_since_creation > kMinRunTimeMs)
213 observation_complete_->Set();
214 }
215 }
216
217 private:
218 Clock* clock_;
219 int voe_channel_;
220 VoEVideoSync* voe_sync_;
221 SyncRtcpObserver* audio_observer_;
222 int64_t creation_time_ms_;
223 int64_t first_time_in_sync_;
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000224 bool using_new_acm_;
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000225};
226
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000227class ParamCallPerfTest : public CallPerfTest,
228 public ::testing::WithParamInterface<bool> {
229 public:
230 ParamCallPerfTest() : CallPerfTest(), use_new_acm_(GetParam()) {}
231
232 protected:
233 bool use_new_acm_;
234};
235
236TEST_P(ParamCallPerfTest, PlaysOutAudioAndVideoInSync) {
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000237 VoiceEngine* voice_engine = VoiceEngine::Create();
238 VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
239 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
240 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
241 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
242 const std::string audio_filename =
243 test::ResourcePath("voice_engine/audio_long16", "pcm");
244 ASSERT_STRNE("", audio_filename.c_str());
245 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
246 audio_filename);
247 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000248 Config config;
249 if (use_new_acm_) {
250 config.Set<webrtc::AudioCodingModuleFactory>(
251 new webrtc::NewAudioCodingModuleFactory());
252 } else {
253 config.Set<webrtc::AudioCodingModuleFactory>(
254 new webrtc::AudioCodingModuleFactory());
255 }
256 int channel = voe_base->CreateChannel(config);
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000257
stefan@webrtc.orgaacdb9f2013-12-18 20:28:25 +0000258 FakeNetworkPipe::Config net_config;
259 net_config.queue_delay_ms = 500;
260 SyncRtcpObserver audio_observer(net_config);
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000261 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(),
262 channel,
263 voe_sync,
264 &audio_observer,
265 use_new_acm_);
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000266
267 Call::Config receiver_config(observer.ReceiveTransport());
268 receiver_config.voice_engine = voice_engine;
269 scoped_ptr<Call> sender_call(
270 Call::Create(Call::Config(observer.SendTransport())));
271 scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
272 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
273 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
274
275 class VoicePacketReceiver : public PacketReceiver {
276 public:
277 VoicePacketReceiver(int channel, VoENetwork* voe_network)
278 : channel_(channel),
279 voe_network_(voe_network),
280 parser_(RtpHeaderParser::Create()) {}
281 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
282 int ret;
283 if (parser_->IsRtcp(packet, static_cast<int>(length))) {
284 ret = voe_network_->ReceivedRTCPPacket(
285 channel_, packet, static_cast<unsigned int>(length));
286 } else {
287 ret = voe_network_->ReceivedRTPPacket(
solenberg@webrtc.orgfec6b6e2014-03-24 10:38:25 +0000288 channel_, packet, static_cast<unsigned int>(length), PacketTime());
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000289 }
290 return ret == 0;
291 }
292
293 private:
294 int channel_;
295 VoENetwork* voe_network_;
296 scoped_ptr<RtpHeaderParser> parser_;
297 } voe_packet_receiver(channel, voe_network);
298
299 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
300
301 internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
sprang@webrtc.org0a298152014-01-27 13:03:02 +0000302 transport_adapter.Enable();
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000303 EXPECT_EQ(0,
304 voe_network->RegisterExternalTransport(channel, transport_adapter));
305
306 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
307
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000308 test::FakeDecoder fake_decoder;
309
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +0000310 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000311
312 VideoReceiveStream::Config receive_config =
313 receiver_call->GetDefaultReceiveConfig();
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000314 assert(receive_config.codecs.empty());
315 VideoCodec codec =
316 test::CreateDecoderVideoCodec(send_config.encoder_settings);
317 receive_config.codecs.push_back(codec);
318 assert(receive_config.external_decoders.empty());
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000319 ExternalVideoDecoder decoder;
320 decoder.decoder = &fake_decoder;
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000321 decoder.payload_type = send_config.encoder_settings.payload_type;
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000322 receive_config.external_decoders.push_back(decoder);
323 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
324 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
325 receive_config.renderer = &observer;
326 receive_config.audio_channel_id = channel;
327
328 VideoSendStream* send_stream =
329 sender_call->CreateVideoSendStream(send_config);
330 VideoReceiveStream* receive_stream =
331 receiver_call->CreateVideoReceiveStream(receive_config);
332 scoped_ptr<test::FrameGeneratorCapturer> capturer(
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000333 test::FrameGeneratorCapturer::Create(
334 send_stream->Input(),
335 send_config.encoder_settings.streams[0].width,
336 send_config.encoder_settings.streams[0].height,
337 30,
338 Clock::GetRealTimeClock()));
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000339 receive_stream->StartReceiving();
340 send_stream->StartSending();
341 capturer->Start();
342
343 fake_audio_device.Start();
344 EXPECT_EQ(0, voe_base->StartPlayout(channel));
345 EXPECT_EQ(0, voe_base->StartReceive(channel));
346 EXPECT_EQ(0, voe_base->StartSend(channel));
347
348 EXPECT_EQ(kEventSignaled, observer.Wait())
349 << "Timed out while waiting for audio and video to be synchronized.";
350
351 EXPECT_EQ(0, voe_base->StopSend(channel));
352 EXPECT_EQ(0, voe_base->StopReceive(channel));
353 EXPECT_EQ(0, voe_base->StopPlayout(channel));
354 fake_audio_device.Stop();
355
356 capturer->Stop();
357 send_stream->StopSending();
358 receive_stream->StopReceiving();
359 observer.StopSending();
360 audio_observer.StopSending();
361
362 voe_base->DeleteChannel(channel);
363 voe_base->Release();
364 voe_codec->Release();
365 voe_network->Release();
366 voe_sync->Release();
367 sender_call->DestroyVideoSendStream(send_stream);
368 receiver_call->DestroyVideoReceiveStream(receive_stream);
369 VoiceEngine::Delete(voice_engine);
370}
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +0000371
henrik.lundin@webrtc.org70e2ce92014-03-06 10:28:07 +0000372// Test with both ACM1 and ACM2.
373INSTANTIATE_TEST_CASE_P(SwitchAcm, ParamCallPerfTest, ::testing::Bool());
374
asapersson@webrtc.org8ef65482014-01-31 10:05:07 +0000375TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
376 // Verifies that either a normal or overuse callback is triggered.
377 class OveruseCallbackObserver : public test::RtpRtcpObserver,
378 public webrtc::OveruseCallback {
379 public:
380 OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
381
382 virtual void OnOveruse() OVERRIDE {
383 observation_complete_->Set();
384 }
385 virtual void OnNormalUse() OVERRIDE {
386 observation_complete_->Set();
387 }
388 };
389
390 OveruseCallbackObserver observer;
391 Call::Config call_config(observer.SendTransport());
392 call_config.overuse_callback = &observer;
393 scoped_ptr<Call> call(Call::Create(call_config));
394
395 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
396 RunVideoSendTest(call.get(), send_config, &observer);
397}
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000398
399void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
400 static const int kMaxEncodeBitrateKbps = 30;
pbos@webrtc.org1d61e3a2014-03-19 10:59:52 +0000401 static const int kMinTransmitBitrateBps = 150000;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000402 static const int kMinAcceptableTransmitBitrate = 130;
403 static const int kMaxAcceptableTransmitBitrate = 170;
404 static const int kNumBitrateObservationsInRange = 100;
405 class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver {
406 public:
407 explicit BitrateObserver(bool using_min_transmit_bitrate)
408 : test::RtpRtcpObserver(kLongTimeoutMs),
409 send_stream_(NULL),
410 send_transport_receiver_(NULL),
411 using_min_transmit_bitrate_(using_min_transmit_bitrate),
412 num_bitrate_observations_in_range_(0) {}
413
414 virtual void SetReceivers(PacketReceiver* send_transport_receiver,
415 PacketReceiver* receive_transport_receiver)
416 OVERRIDE {
417 send_transport_receiver_ = send_transport_receiver;
418 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
419 }
420
421 void SetSendStream(VideoSendStream* send_stream) {
422 send_stream_ = send_stream;
423 }
424
425 private:
426 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
427 VideoSendStream::Stats stats = send_stream_->GetStats();
428 if (stats.substreams.size() > 0) {
429 assert(stats.substreams.size() == 1);
430 int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000;
431 if (bitrate_kbps > 0) {
432 test::PrintResult(
433 "bitrate_stats_",
434 (using_min_transmit_bitrate_ ? "min_transmit_bitrate"
435 : "without_min_transmit_bitrate"),
436 "bitrate_kbps",
437 static_cast<size_t>(bitrate_kbps),
438 "kbps",
439 false);
440 if (using_min_transmit_bitrate_) {
441 if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
442 bitrate_kbps < kMaxAcceptableTransmitBitrate) {
443 ++num_bitrate_observations_in_range_;
444 }
445 } else {
446 // Expect bitrate stats to roughly match the max encode bitrate.
447 if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 &&
448 bitrate_kbps < kMaxEncodeBitrateKbps + 5) {
449 ++num_bitrate_observations_in_range_;
450 }
451 }
452 if (num_bitrate_observations_in_range_ ==
453 kNumBitrateObservationsInRange)
454 observation_complete_->Set();
455 }
456 }
457 return send_transport_receiver_->DeliverPacket(packet, length);
458 }
459
460 VideoSendStream* send_stream_;
461 PacketReceiver* send_transport_receiver_;
462 const bool using_min_transmit_bitrate_;
463 int num_bitrate_observations_in_range_;
464 } observer(pad_to_min_bitrate);
465
466 scoped_ptr<Call> sender_call(
467 Call::Create(Call::Config(observer.SendTransport())));
468 scoped_ptr<Call> receiver_call(
469 Call::Create(Call::Config(observer.ReceiveTransport())));
470
471 VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
472 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
473
474 observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
475
476 send_config.pacing = true;
477 if (pad_to_min_bitrate) {
pbos@webrtc.org1d61e3a2014-03-19 10:59:52 +0000478 send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000479 } else {
pbos@webrtc.org1d61e3a2014-03-19 10:59:52 +0000480 assert(send_config.rtp.min_transmit_bitrate_bps == 0);
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000481 }
482
483 VideoReceiveStream::Config receive_config =
484 receiver_call->GetDefaultReceiveConfig();
485 receive_config.codecs.clear();
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000486 VideoCodec codec =
487 test::CreateDecoderVideoCodec(send_config.encoder_settings);
488 receive_config.codecs.push_back(codec);
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000489 test::FakeDecoder fake_decoder;
490 ExternalVideoDecoder decoder;
491 decoder.decoder = &fake_decoder;
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000492 decoder.payload_type = send_config.encoder_settings.payload_type;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000493 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
497 VideoSendStream* send_stream =
498 sender_call->CreateVideoSendStream(send_config);
499 VideoReceiveStream* receive_stream =
500 receiver_call->CreateVideoReceiveStream(receive_config);
501 scoped_ptr<test::FrameGeneratorCapturer> capturer(
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000502 test::FrameGeneratorCapturer::Create(
503 send_stream->Input(),
504 send_config.encoder_settings.streams[0].width,
505 send_config.encoder_settings.streams[0].height,
506 30,
507 Clock::GetRealTimeClock()));
pbos@webrtc.org3f83f9c2014-03-13 12:52:27 +0000508 observer.SetSendStream(send_stream);
509 receive_stream->StartReceiving();
510 send_stream->StartSending();
511 capturer->Start();
512
513 EXPECT_EQ(kEventSignaled, observer.Wait())
514 << "Timeout while waiting for send-bitrate stats.";
515
516 send_stream->StopSending();
517 receive_stream->StopReceiving();
518 observer.StopSending();
519 capturer->Stop();
520 sender_call->DestroyVideoSendStream(send_stream);
521 receiver_call->DestroyVideoReceiveStream(receive_stream);
522}
523
524TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
525
526TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
527 TestMinTransmitBitrate(false);
528}
529
pbos@webrtc.orgf94ccd42013-12-13 12:48:05 +0000530} // namespace webrtc