blob: 46611a1826dac35c3d7ead092258d04c289a08bf [file] [log] [blame]
pbos@webrtc.orgf94ccd42013-12-13 12:48:051/*
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 */
asaperssona637d2c2016-03-15 08:00:4710
pbos@webrtc.orgf94ccd42013-12-13 12:48:0511#include <algorithm>
asaperssona637d2c2016-03-15 08:00:4712#include <limits>
kwiberg4185d512016-03-12 14:10:4413#include <memory>
pbos@webrtc.orgf94ccd42013-12-13 12:48:0514#include <string>
15
ossuf26202b2017-05-02 13:46:3016#include "webrtc/api/audio_codecs/builtin_audio_encoder_factory.h"
ossu31212ba2016-12-07 12:52:5817#include "webrtc/call/call.h"
Stefan Holmer36189cd2017-09-01 13:29:2818#include "webrtc/call/video_config.h"
skvlad14ccce82016-10-07 18:53:0519#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
kjellander0c1546c2015-11-26 12:44:5420#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
aleloid85b51d2016-11-17 14:48:4821#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
Henrik Kjellander36a14b52015-11-04 07:31:5222#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
Edward Lemur76de83e2017-07-06 17:44:3423#include "webrtc/rtc_base/checks.h"
eladalon0f007ea2017-08-22 11:02:5224#include "webrtc/rtc_base/ptr_util.h"
Edward Lemur76de83e2017-07-06 17:44:3425#include "webrtc/rtc_base/thread_annotations.h"
asapersson8256c472016-05-20 13:29:4626#include "webrtc/system_wrappers/include/metrics_default.h"
pbos@webrtc.orgeb67a6b2014-06-27 08:47:5227#include "webrtc/test/call_test.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0528#include "webrtc/test/direct_transport.h"
danilchapa4777ed2016-02-10 18:54:4729#include "webrtc/test/drifting_clock.h"
pbos@webrtc.orge2a7a772014-03-19 08:43:5730#include "webrtc/test/encoder_settings.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0531#include "webrtc/test/fake_audio_device.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0532#include "webrtc/test/fake_encoder.h"
sprang7950bab2017-04-03 06:53:0433#include "webrtc/test/field_trial.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0534#include "webrtc/test/frame_generator.h"
35#include "webrtc/test/frame_generator_capturer.h"
kwiberg36a24792016-10-01 05:29:4336#include "webrtc/test/gtest.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0537#include "webrtc/test/rtp_rtcp_observer.h"
eladalon0f007ea2017-08-22 11:02:5238#include "webrtc/test/single_threaded_task_queue.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0539#include "webrtc/test/testsupport/fileutils.h"
40#include "webrtc/test/testsupport/perf_test.h"
charujain5daa11f2016-11-03 11:21:4241#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0542#include "webrtc/voice_engine/include/voe_base.h"
pbos@webrtc.orgf94ccd42013-12-13 12:48:0543
danilchapa4777ed2016-02-10 18:54:4744using webrtc::test::DriftingClock;
45using webrtc::test::FakeAudioDevice;
46
pbos@webrtc.orgf94ccd42013-12-13 12:48:0547namespace webrtc {
48
pbos@webrtc.orgeb67a6b2014-06-27 08:47:5249class CallPerfTest : public test::CallTest {
asapersson@webrtc.org8ef65482014-01-31 10:05:0750 protected:
Danil Chapovalova96ea332016-02-15 10:14:5851 enum class FecMode {
52 kOn, kOff
53 };
54 enum class CreateOrder {
55 kAudioFirst, kVideoFirst
56 };
57 void TestAudioVideoSync(FecMode fec,
58 CreateOrder create_first,
danilchapa4777ed2016-02-10 18:54:4759 float video_ntp_speed,
60 float video_rtp_speed,
61 float audio_rtp_speed);
stefan@webrtc.orgd01c4912014-09-04 06:48:1462
pbos@webrtc.org3f83f9c2014-03-13 12:52:2763 void TestMinTransmitBitrate(bool pad_to_min_bitrate);
64
wu@webrtc.org093fc0b2014-04-24 22:10:2465 void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
66 int threshold_ms,
67 int start_time_ms,
68 int run_time_ms);
pbos@webrtc.orgf94ccd42013-12-13 12:48:0569};
70
asaperssona637d2c2016-03-15 08:00:4771class VideoRtcpAndSyncObserver : public test::RtpRtcpObserver,
nissea2761a52016-03-23 11:48:1072 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.orgf94ccd42013-12-13 12:48:0573 static const int kInSyncThresholdMs = 50;
74 static const int kStartupTimeMs = 2000;
75 static const int kMinRunTimeMs = 30000;
76
77 public:
asaperssona637d2c2016-03-15 08:00:4778 explicit VideoRtcpAndSyncObserver(Clock* clock)
79 : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs),
80 clock_(clock),
pbos@webrtc.orgf94ccd42013-12-13 12:48:0581 creation_time_ms_(clock_->TimeInMilliseconds()),
asaperssona637d2c2016-03-15 08:00:4782 first_time_in_sync_(-1),
83 receive_stream_(nullptr) {}
pbos@webrtc.orgf94ccd42013-12-13 12:48:0584
nissef8e52ce2016-03-21 08:27:5685 void OnFrame(const VideoFrame& video_frame) override {
asaperssona637d2c2016-03-15 08:00:4786 VideoReceiveStream::Stats stats;
87 {
88 rtc::CritScope lock(&crit_);
89 if (receive_stream_)
90 stats = receive_stream_->GetStats();
91 }
92 if (stats.sync_offset_ms == std::numeric_limits<int>::max())
93 return;
94
pbos@webrtc.orgf94ccd42013-12-13 12:48:0595 int64_t now_ms = clock_->TimeInMilliseconds();
pbos@webrtc.orgf94ccd42013-12-13 12:48:0596 int64_t time_since_creation = now_ms - creation_time_ms_;
97 // During the first couple of seconds audio and video can falsely be
98 // estimated as being synchronized. We don't want to trigger on those.
99 if (time_since_creation < kStartupTimeMs)
100 return;
asaperssona637d2c2016-03-15 08:00:47101 if (std::abs(stats.sync_offset_ms) < kInSyncThresholdMs) {
pbos@webrtc.orgf94ccd42013-12-13 12:48:05102 if (first_time_in_sync_ == -1) {
103 first_time_in_sync_ = now_ms;
104 webrtc::test::PrintResult("sync_convergence_time",
henrik.lundin@webrtc.org6cee2ba2014-04-22 08:36:33105 "",
pbos@webrtc.orgf94ccd42013-12-13 12:48:05106 "synchronization",
107 time_since_creation,
108 "ms",
109 false);
110 }
111 if (time_since_creation > kMinRunTimeMs)
Peter Boström1cddafe2015-12-10 12:02:50112 observation_complete_.Set();
pbos@webrtc.orgf94ccd42013-12-13 12:48:05113 }
Danil Chapovalov8e697aa2016-06-16 07:58:44114 if (first_time_in_sync_ != -1)
115 sync_offset_ms_list_.push_back(stats.sync_offset_ms);
pbos@webrtc.orgf94ccd42013-12-13 12:48:05116 }
117
asaperssona637d2c2016-03-15 08:00:47118 void set_receive_stream(VideoReceiveStream* receive_stream) {
119 rtc::CritScope lock(&crit_);
120 receive_stream_ = receive_stream;
121 }
122
danilchapdfd2f302016-06-03 16:27:37123 void PrintResults() {
124 test::PrintResultList("stream_offset", "", "synchronization",
125 test::ValuesToString(sync_offset_ms_list_), "ms",
126 false);
127 }
128
pbos@webrtc.orgf94ccd42013-12-13 12:48:05129 private:
pbos@webrtc.orgc476e642014-04-28 13:00:21130 Clock* const clock_;
stefanf5a44e82015-10-27 15:29:42131 const int64_t creation_time_ms_;
pbos@webrtc.orgf94ccd42013-12-13 12:48:05132 int64_t first_time_in_sync_;
asaperssona637d2c2016-03-15 08:00:47133 rtc::CriticalSection crit_;
danilchap642a0742017-09-09 11:17:22134 VideoReceiveStream* receive_stream_ RTC_GUARDED_BY(crit_);
danilchapdfd2f302016-06-03 16:27:37135 std::vector<int> sync_offset_ms_list_;
pbos@webrtc.orgf94ccd42013-12-13 12:48:05136};
137
Danil Chapovalova96ea332016-02-15 10:14:58138void CallPerfTest::TestAudioVideoSync(FecMode fec,
139 CreateOrder create_first,
danilchapa4777ed2016-02-10 18:54:47140 float video_ntp_speed,
141 float video_rtp_speed,
142 float audio_rtp_speed) {
pbos495b3502015-07-15 15:02:58143 const char* kSyncGroup = "av_sync";
Stefan Holmerf95302f2015-12-07 09:26:18144 const uint32_t kAudioSendSsrc = 1234;
145 const uint32_t kAudioRecvSsrc = 5678;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52146
eladalon0f007ea2017-08-22 11:02:52147 int send_channel_id;
148 int recv_channel_id;
asaperssona637d2c2016-03-15 08:00:47149
mflodman823f9082016-04-29 07:57:13150 FakeNetworkPipe::Config audio_net_config;
151 audio_net_config.queue_delay_ms = 500;
152 audio_net_config.loss_percent = 5;
minyueb9f62aa2017-04-10 23:57:57153
eladalon0f007ea2017-08-22 11:02:52154 rtc::scoped_refptr<AudioProcessing> audio_processing;
155 VoiceEngine* voice_engine;
156 VoEBase* voe_base;
157 std::unique_ptr<FakeAudioDevice> fake_audio_device;
158 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock());
159
minyueb9f62aa2017-04-10 23:57:57160 std::map<uint8_t, MediaType> audio_pt_map;
161 std::map<uint8_t, MediaType> video_pt_map;
minyueb9f62aa2017-04-10 23:57:57162
eladalon0f007ea2017-08-22 11:02:52163 std::unique_ptr<test::PacketTransport> audio_send_transport;
164 std::unique_ptr<test::PacketTransport> video_send_transport;
165 std::unique_ptr<test::PacketTransport> receive_transport;
mflodman823f9082016-04-29 07:57:13166
eladalon0f007ea2017-08-22 11:02:52167 AudioSendStream* audio_send_stream;
Stefan Holmerf95302f2015-12-07 09:26:18168 AudioReceiveStream* audio_receive_stream;
eladalon0f007ea2017-08-22 11:02:52169 std::unique_ptr<DriftingClock> drifting_clock;
pbos495b3502015-07-15 15:02:58170
eladalon0f007ea2017-08-22 11:02:52171 task_queue_.SendTask([&]() {
172 metrics::Reset();
173 audio_processing = AudioProcessing::Create();
174 voice_engine = VoiceEngine::Create();
175 voe_base = VoEBase::GetInterface(voice_engine);
176 fake_audio_device = rtc::MakeUnique<FakeAudioDevice>(
177 FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000),
178 FakeAudioDevice::CreateDiscardRenderer(48000), audio_rtp_speed);
179 EXPECT_EQ(0, voe_base->Init(fake_audio_device.get(), audio_processing.get(),
180 decoder_factory_));
181 VoEBase::ChannelConfig config;
182 config.enable_voice_pacing = true;
183 send_channel_id = voe_base->CreateChannel(config);
184 recv_channel_id = voe_base->CreateChannel();
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52185
eladalon0f007ea2017-08-22 11:02:52186 AudioState::Config send_audio_state_config;
187 send_audio_state_config.voice_engine = voice_engine;
188 send_audio_state_config.audio_mixer = AudioMixerImpl::Create();
189 send_audio_state_config.audio_processing = audio_processing;
190 Call::Config sender_config(event_log_.get());
pbos@webrtc.orgf94ccd42013-12-13 12:48:05191
eladalon0f007ea2017-08-22 11:02:52192 sender_config.audio_state = AudioState::Create(send_audio_state_config);
193 Call::Config receiver_config(event_log_.get());
194 receiver_config.audio_state = sender_config.audio_state;
195 CreateCalls(sender_config, receiver_config);
196
197 std::copy_if(std::begin(payload_type_map_), std::end(payload_type_map_),
198 std::inserter(audio_pt_map, audio_pt_map.end()),
199 [](const std::pair<const uint8_t, MediaType>& pair) {
200 return pair.second == MediaType::AUDIO;
201 });
202 std::copy_if(std::begin(payload_type_map_), std::end(payload_type_map_),
203 std::inserter(video_pt_map, video_pt_map.end()),
204 [](const std::pair<const uint8_t, MediaType>& pair) {
205 return pair.second == MediaType::VIDEO;
206 });
207
208 audio_send_transport = rtc::MakeUnique<test::PacketTransport>(
209 &task_queue_, sender_call_.get(), &observer,
210 test::PacketTransport::kSender, audio_pt_map, audio_net_config);
211 audio_send_transport->SetReceiver(receiver_call_->Receiver());
212
213 video_send_transport = rtc::MakeUnique<test::PacketTransport>(
214 &task_queue_, sender_call_.get(), &observer,
215 test::PacketTransport::kSender, video_pt_map,
216 FakeNetworkPipe::Config());
217 video_send_transport->SetReceiver(receiver_call_->Receiver());
218
219 receive_transport = rtc::MakeUnique<test::PacketTransport>(
220 &task_queue_, receiver_call_.get(), &observer,
221 test::PacketTransport::kReceiver, payload_type_map_,
222 FakeNetworkPipe::Config());
223 receive_transport->SetReceiver(sender_call_->Receiver());
224
225 CreateSendConfig(1, 0, 0, video_send_transport.get());
226 CreateMatchingReceiveConfigs(receive_transport.get());
227
228 AudioSendStream::Config audio_send_config(audio_send_transport.get());
229 audio_send_config.voe_channel_id = send_channel_id;
230 audio_send_config.rtp.ssrc = kAudioSendSsrc;
231 audio_send_config.send_codec_spec =
232 rtc::Optional<AudioSendStream::Config::SendCodecSpec>(
233 {kAudioSendPayloadType, {"ISAC", 16000, 1}});
234 audio_send_config.encoder_factory = CreateBuiltinAudioEncoderFactory();
235 audio_send_stream = sender_call_->CreateAudioSendStream(audio_send_config);
236
237 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
238 if (fec == FecMode::kOn) {
239 video_send_config_.rtp.ulpfec.red_payload_type = kRedPayloadType;
240 video_send_config_.rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
241 video_receive_configs_[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
242 video_receive_configs_[0].rtp.ulpfec.ulpfec_payload_type =
243 kUlpfecPayloadType;
244 }
245 video_receive_configs_[0].rtp.nack.rtp_history_ms = 1000;
246 video_receive_configs_[0].renderer = &observer;
247 video_receive_configs_[0].sync_group = kSyncGroup;
248
249 AudioReceiveStream::Config audio_recv_config;
250 audio_recv_config.rtp.remote_ssrc = kAudioSendSsrc;
251 audio_recv_config.rtp.local_ssrc = kAudioRecvSsrc;
252 audio_recv_config.voe_channel_id = recv_channel_id;
253 audio_recv_config.sync_group = kSyncGroup;
254 audio_recv_config.decoder_factory = decoder_factory_;
255 audio_recv_config.decoder_map = {
256 {kAudioSendPayloadType, {"ISAC", 16000, 1}}};
257
258 if (create_first == CreateOrder::kAudioFirst) {
259 audio_receive_stream =
260 receiver_call_->CreateAudioReceiveStream(audio_recv_config);
261 CreateVideoStreams();
262 } else {
263 CreateVideoStreams();
264 audio_receive_stream =
265 receiver_call_->CreateAudioReceiveStream(audio_recv_config);
266 }
267 EXPECT_EQ(1u, video_receive_streams_.size());
268 observer.set_receive_stream(video_receive_streams_[0]);
269 drifting_clock = rtc::MakeUnique<DriftingClock>(clock_, video_ntp_speed);
270 CreateFrameGeneratorCapturerWithDrift(drifting_clock.get(), video_rtp_speed,
271 kDefaultFramerate, kDefaultWidth,
272 kDefaultHeight);
273
274 Start();
275
276 audio_send_stream->Start();
277 audio_receive_stream->Start();
278 });
pbos@webrtc.orgf94ccd42013-12-13 12:48:05279
Peter Boström1cddafe2015-12-10 12:02:50280 EXPECT_TRUE(observer.Wait())
pbos@webrtc.orgf94ccd42013-12-13 12:48:05281 << "Timed out while waiting for audio and video to be synchronized.";
282
eladalon0f007ea2017-08-22 11:02:52283 task_queue_.SendTask([&]() {
284 audio_send_stream->Stop();
285 audio_receive_stream->Stop();
pbos@webrtc.orgf94ccd42013-12-13 12:48:05286
eladalon0f007ea2017-08-22 11:02:52287 Stop();
pbos@webrtc.orgf94ccd42013-12-13 12:48:05288
eladalon0f007ea2017-08-22 11:02:52289 DestroyStreams();
Stefan Holmerf95302f2015-12-07 09:26:18290
eladalon0f007ea2017-08-22 11:02:52291 video_send_transport.reset();
292 audio_send_transport.reset();
293 receive_transport.reset();
Stefan Holmerf95302f2015-12-07 09:26:18294
eladalon0f007ea2017-08-22 11:02:52295 sender_call_->DestroyAudioSendStream(audio_send_stream);
296 receiver_call_->DestroyAudioReceiveStream(audio_receive_stream);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52297
eladalon0f007ea2017-08-22 11:02:52298 voe_base->DeleteChannel(send_channel_id);
299 voe_base->DeleteChannel(recv_channel_id);
300 voe_base->Release();
Fredrik Solenberg10762d32015-10-22 08:49:27301
eladalon0f007ea2017-08-22 11:02:52302 DestroyCalls();
303
304 VoiceEngine::Delete(voice_engine);
305
306 fake_audio_device.reset();
307 });
asaperssona637d2c2016-03-15 08:00:47308
danilchapdfd2f302016-06-03 16:27:37309 observer.PrintResults();
ilnik28121522017-02-21 13:20:28310
311 // In quick test synchronization may not be achieved in time.
spranga6c8c292017-03-01 14:20:56312 if (!field_trial::IsEnabled("WebRTC-QuickPerfTest")) {
ilnik28121522017-02-21 13:20:28313 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
314 }
pbos@webrtc.orgf94ccd42013-12-13 12:48:05315}
asapersson@webrtc.org8ef65482014-01-31 10:05:07316
danilchap9c0599f2016-02-29 20:17:04317TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoNtpDrift) {
Danil Chapovalova96ea332016-02-15 10:14:58318 TestAudioVideoSync(FecMode::kOff, CreateOrder::kAudioFirst,
319 DriftingClock::PercentsFaster(10.0f),
danilchapa4777ed2016-02-10 18:54:47320 DriftingClock::kNoDrift, DriftingClock::kNoDrift);
321}
322
danilchapa4777ed2016-02-10 18:54:47323TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithAudioFasterThanVideoDrift) {
Danil Chapovalova96ea332016-02-15 10:14:58324 TestAudioVideoSync(FecMode::kOff, CreateOrder::kAudioFirst,
325 DriftingClock::kNoDrift,
danilchapa4777ed2016-02-10 18:54:47326 DriftingClock::PercentsSlower(30.0f),
327 DriftingClock::PercentsFaster(30.0f));
328}
329
330TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoFasterThanAudioDrift) {
Danil Chapovalova96ea332016-02-15 10:14:58331 TestAudioVideoSync(FecMode::kOn, CreateOrder::kVideoFirst,
332 DriftingClock::kNoDrift,
danilchapa4777ed2016-02-10 18:54:47333 DriftingClock::PercentsFaster(30.0f),
334 DriftingClock::PercentsSlower(30.0f));
stefan@webrtc.orgd01c4912014-09-04 06:48:14335}
336
wu@webrtc.org093fc0b2014-04-24 22:10:24337void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
338 int threshold_ms,
339 int start_time_ms,
340 int run_time_ms) {
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52341 class CaptureNtpTimeObserver : public test::EndToEndTest,
nissea2761a52016-03-23 11:48:10342 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52343 public:
stefan26f9c182016-01-08 14:47:13344 CaptureNtpTimeObserver(const FakeNetworkPipe::Config& net_config,
345 int threshold_ms,
346 int start_time_ms,
347 int run_time_ms)
stefanf5a44e82015-10-27 15:29:42348 : EndToEndTest(kLongTimeoutMs),
stefan26f9c182016-01-08 14:47:13349 net_config_(net_config),
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52350 clock_(Clock::GetRealTimeClock()),
351 threshold_ms_(threshold_ms),
352 start_time_ms_(start_time_ms),
353 run_time_ms_(run_time_ms),
354 creation_time_ms_(clock_->TimeInMilliseconds()),
pbos@webrtc.org6eaf09a2015-03-23 13:12:24355 capturer_(nullptr),
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52356 rtp_start_timestamp_set_(false),
357 rtp_start_timestamp_(0) {}
wu@webrtc.org093fc0b2014-04-24 22:10:24358
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52359 private:
eladalon0f007ea2017-08-22 11:02:52360 test::PacketTransport* CreateSendTransport(
361 test::SingleThreadedTaskQueueForTesting* task_queue,
362 Call* sender_call) override {
363 return new test::PacketTransport(task_queue, sender_call, this,
minyueb9f62aa2017-04-10 23:57:57364 test::PacketTransport::kSender,
365 payload_type_map_, net_config_);
stefan26f9c182016-01-08 14:47:13366 }
367
eladalon0f007ea2017-08-22 11:02:52368 test::PacketTransport* CreateReceiveTransport(
369 test::SingleThreadedTaskQueueForTesting* task_queue) override {
370 return new test::PacketTransport(task_queue, nullptr, this,
minyueb9f62aa2017-04-10 23:57:57371 test::PacketTransport::kReceiver,
372 payload_type_map_, net_config_);
Stefan Holmercbbb3b12016-01-13 07:58:38373 }
374
nissef8e52ce2016-03-21 08:27:56375 void OnFrame(const VideoFrame& video_frame) override {
stefanf5a44e82015-10-27 15:29:42376 rtc::CritScope lock(&crit_);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52377 if (video_frame.ntp_time_ms() <= 0) {
378 // Haven't got enough RTCP SR in order to calculate the capture ntp
379 // time.
380 return;
381 }
wu@webrtc.org093fc0b2014-04-24 22:10:24382
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52383 int64_t now_ms = clock_->TimeInMilliseconds();
384 int64_t time_since_creation = now_ms - creation_time_ms_;
385 if (time_since_creation < start_time_ms_) {
386 // Wait for |start_time_ms_| before start measuring.
387 return;
388 }
wu@webrtc.org093fc0b2014-04-24 22:10:24389
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52390 if (time_since_creation > run_time_ms_) {
Peter Boström1cddafe2015-12-10 12:02:50391 observation_complete_.Set();
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52392 }
wu@webrtc.org093fc0b2014-04-24 22:10:24393
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52394 FrameCaptureTimeList::iterator iter =
395 capture_time_list_.find(video_frame.timestamp());
396 EXPECT_TRUE(iter != capture_time_list_.end());
wu@webrtc.org093fc0b2014-04-24 22:10:24397
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52398 // The real capture time has been wrapped to uint32_t before converted
399 // to rtp timestamp in the sender side. So here we convert the estimated
400 // capture time to a uint32_t 90k timestamp also for comparing.
401 uint32_t estimated_capture_timestamp =
402 90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
403 uint32_t real_capture_timestamp = iter->second;
404 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
405 time_offset_ms = time_offset_ms / 90;
danilchapdfd2f302016-06-03 16:27:37406 time_offset_ms_list_.push_back(time_offset_ms);
wu@webrtc.org093fc0b2014-04-24 22:10:24407
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52408 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
409 }
wu@webrtc.org093fc0b2014-04-24 22:10:24410
nisse44dc40f2016-04-29 13:09:15411 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf5a44e82015-10-27 15:29:42412 rtc::CritScope lock(&crit_);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52413 RTPHeader header;
pbos@webrtc.org6aae61c2014-07-08 12:10:51414 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52415
416 if (!rtp_start_timestamp_set_) {
417 // Calculate the rtp timestamp offset in order to calculate the real
418 // capture time.
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;
423 }
424
425 uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
426 capture_time_list_.insert(
427 capture_time_list_.end(),
428 std::make_pair(header.timestamp, capture_timestamp));
429 return SEND_PACKET;
430 }
431
kjellander@webrtc.org860ac532015-03-04 12:58:35432 void OnFrameGeneratorCapturerCreated(
433 test::FrameGeneratorCapturer* frame_generator_capturer) override {
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52434 capturer_ = frame_generator_capturer;
435 }
436
stefan19cc2832015-12-21 11:14:00437 void ModifyVideoConfigs(
438 VideoSendStream::Config* send_config,
439 std::vector<VideoReceiveStream::Config>* receive_configs,
440 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org88b558f2014-06-30 13:19:09441 (*receive_configs)[0].renderer = this;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52442 // Enable the receiver side rtt calculation.
pbos@webrtc.org88b558f2014-06-30 13:19:09443 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52444 }
445
kjellander@webrtc.org860ac532015-03-04 12:58:35446 void PerformTest() override {
Peter Boström1cddafe2015-12-10 12:02:50447 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
448 "estimated capture NTP time to be "
449 "within bounds.";
danilchapdfd2f302016-06-03 16:27:37450 test::PrintResultList("capture_ntp_time", "", "real - estimated",
451 test::ValuesToString(time_offset_ms_list_), "ms",
452 true);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52453 }
454
stefanf5a44e82015-10-27 15:29:42455 rtc::CriticalSection crit_;
stefan26f9c182016-01-08 14:47:13456 const FakeNetworkPipe::Config net_config_;
stefanf5a44e82015-10-27 15:29:42457 Clock* const clock_;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52458 int threshold_ms_;
459 int start_time_ms_;
460 int run_time_ms_;
461 int64_t creation_time_ms_;
462 test::FrameGeneratorCapturer* capturer_;
463 bool rtp_start_timestamp_set_;
464 uint32_t rtp_start_timestamp_;
465 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
danilchap642a0742017-09-09 11:17:22466 FrameCaptureTimeList capture_time_list_ RTC_GUARDED_BY(&crit_);
danilchapdfd2f302016-06-03 16:27:37467 std::vector<int> time_offset_ms_list_;
stefan26f9c182016-01-08 14:47:13468 } test(net_config, threshold_ms, start_time_ms, run_time_ms);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52469
stefan26f9c182016-01-08 14:47:13470 RunBaseTest(&test);
wu@webrtc.org093fc0b2014-04-24 22:10:24471}
472
wu@webrtc.org1ef9cee2014-05-29 05:03:52473TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) {
wu@webrtc.org093fc0b2014-04-24 22:10:24474 FakeNetworkPipe::Config net_config;
475 net_config.queue_delay_ms = 100;
476 // TODO(wu): lower the threshold as the calculation/estimatation becomes more
477 // accurate.
wu@webrtc.org1ef9cee2014-05-29 05:03:52478 const int kThresholdMs = 100;
wu@webrtc.org093fc0b2014-04-24 22:10:24479 const int kStartTimeMs = 10000;
480 const int kRunTimeMs = 20000;
481 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs);
482}
483
wu@webrtc.org1cbc3602014-05-05 17:42:43484TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) {
wu@webrtc.org093fc0b2014-04-24 22:10:24485 FakeNetworkPipe::Config net_config;
wu@webrtc.org1cbc3602014-05-05 17:42:43486 net_config.queue_delay_ms = 100;
wu@webrtc.org093fc0b2014-04-24 22:10:24487 net_config.delay_standard_deviation_ms = 10;
488 // TODO(wu): lower the threshold as the calculation/estimatation becomes more
489 // accurate.
wu@webrtc.org1cbc3602014-05-05 17:42:43490 const int kThresholdMs = 100;
wu@webrtc.org093fc0b2014-04-24 22:10:24491 const int kStartTimeMs = 10000;
492 const int kRunTimeMs = 20000;
493 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs);
494}
kthelgason5afd9202017-02-27 08:15:31495
perkj27e68162016-11-01 18:45:46496TEST_F(CallPerfTest, ReceivesCpuOveruseAndUnderuse) {
sprang7950bab2017-04-03 06:53:04497 // Minimal normal usage at the start, then 30s overuse to allow filter to
498 // settle, and then 80s underuse to allow plenty of time for rampup again.
499 test::ScopedFieldTrials fake_overuse_settings(
500 "WebRTC-ForceSimulatedOveruseIntervalMs/1-30000-80000/");
501
perkj27e68162016-11-01 18:45:46502 class LoadObserver : public test::SendTest,
503 public test::FrameGeneratorCapturer::SinkWantsObserver {
asapersson@webrtc.org8ef65482014-01-31 10:05:07504 public:
sprang7950bab2017-04-03 06:53:04505 LoadObserver() : SendTest(kLongTimeoutMs), test_phase_(TestPhase::kStart) {}
asapersson@webrtc.org8ef65482014-01-31 10:05:07506
perkj27e68162016-11-01 18:45:46507 void OnFrameGeneratorCapturerCreated(
508 test::FrameGeneratorCapturer* frame_generator_capturer) override {
509 frame_generator_capturer->SetSinkWantsObserver(this);
kthelgason5afd9202017-02-27 08:15:31510 // Set a high initial resolution to be sure that we can scale down.
511 frame_generator_capturer->ChangeResolution(1920, 1080);
perkj27e68162016-11-01 18:45:46512 }
513
514 // OnSinkWantsChanged is called when FrameGeneratorCapturer::AddOrUpdateSink
515 // is called.
sprang7950bab2017-04-03 06:53:04516 // TODO(sprang): Add integration test for maintain-framerate mode?
perkj27e68162016-11-01 18:45:46517 void OnSinkWantsChanged(rtc::VideoSinkInterface<VideoFrame>* sink,
518 const rtc::VideoSinkWants& wants) override {
519 // First expect CPU overuse. Then expect CPU underuse when the encoder
520 // delay has been decreased.
sprang7950bab2017-04-03 06:53:04521 switch (test_phase_) {
522 case TestPhase::kStart:
523 if (wants.max_pixel_count < std::numeric_limits<int>::max()) {
mflodman783ce682017-08-03 15:27:51524 // On adapting down, VideoStreamEncoder::VideoSourceProxy will set
525 // only the max pixel count, leaving the target unset.
sprang7950bab2017-04-03 06:53:04526 test_phase_ = TestPhase::kAdaptedDown;
527 } else {
528 ADD_FAILURE() << "Got unexpected adaptation request, max res = "
529 << wants.max_pixel_count << ", target res = "
530 << wants.target_pixel_count.value_or(-1)
531 << ", max fps = " << wants.max_framerate_fps;
532 }
533 break;
534 case TestPhase::kAdaptedDown:
535 // On adapting up, the adaptation counter will again be at zero, and
536 // so all constraints will be reset.
537 if (wants.max_pixel_count == std::numeric_limits<int>::max() &&
538 !wants.target_pixel_count) {
539 test_phase_ = TestPhase::kAdaptedUp;
540 observation_complete_.Set();
541 } else {
542 ADD_FAILURE() << "Got unexpected adaptation request, max res = "
543 << wants.max_pixel_count << ", target res = "
544 << wants.target_pixel_count.value_or(-1)
545 << ", max fps = " << wants.max_framerate_fps;
546 }
547 break;
548 case TestPhase::kAdaptedUp:
549 ADD_FAILURE() << "Got unexpected adaptation request, max res = "
550 << wants.max_pixel_count << ", target res = "
551 << wants.target_pixel_count.value_or(-1)
552 << ", max fps = " << wants.max_framerate_fps;
perkj27e68162016-11-01 18:45:46553 }
asapersson@webrtc.org8ef65482014-01-31 10:05:07554 }
asapersson@webrtc.org8ef65482014-01-31 10:05:07555
stefan19cc2832015-12-21 11:14:00556 void ModifyVideoConfigs(
557 VideoSendStream::Config* send_config,
558 std::vector<VideoReceiveStream::Config>* receive_configs,
559 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org0c17c5e2014-11-20 10:19:46560 }
561
kjellander@webrtc.org860ac532015-03-04 12:58:35562 void PerformTest() override {
Peter Boström1cddafe2015-12-10 12:02:50563 EXPECT_TRUE(Wait()) << "Timed out before receiving an overuse callback.";
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52564 }
asapersson@webrtc.org0c17c5e2014-11-20 10:19:46565
sprang7950bab2017-04-03 06:53:04566 enum class TestPhase { kStart, kAdaptedDown, kAdaptedUp } test_phase_;
perkj27e68162016-11-01 18:45:46567 } test;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52568
stefan26f9c182016-01-08 14:47:13569 RunBaseTest(&test);
asapersson@webrtc.org8ef65482014-01-31 10:05:07570}
pbos@webrtc.org3f83f9c2014-03-13 12:52:27571
572void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
573 static const int kMaxEncodeBitrateKbps = 30;
pbos@webrtc.org1d61e3a2014-03-19 10:59:52574 static const int kMinTransmitBitrateBps = 150000;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27575 static const int kMinAcceptableTransmitBitrate = 130;
576 static const int kMaxAcceptableTransmitBitrate = 170;
577 static const int kNumBitrateObservationsInRange = 100;
sprang374a5702015-08-03 11:38:41578 static const int kAcceptableBitrateErrorMargin = 15; // +- 7
stefanf5a44e82015-10-27 15:29:42579 class BitrateObserver : public test::EndToEndTest {
pbos@webrtc.org3f83f9c2014-03-13 12:52:27580 public:
581 explicit BitrateObserver(bool using_min_transmit_bitrate)
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52582 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org6eaf09a2015-03-23 13:12:24583 send_stream_(nullptr),
Danil Chapovalov8e697aa2016-06-16 07:58:44584 converged_(false),
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52585 pad_to_min_bitrate_(using_min_transmit_bitrate),
Danil Chapovalov8e697aa2016-06-16 07:58:44586 min_acceptable_bitrate_(using_min_transmit_bitrate
587 ? kMinAcceptableTransmitBitrate
588 : (kMaxEncodeBitrateKbps -
589 kAcceptableBitrateErrorMargin / 2)),
590 max_acceptable_bitrate_(using_min_transmit_bitrate
591 ? kMaxAcceptableTransmitBitrate
592 : (kMaxEncodeBitrateKbps +
593 kAcceptableBitrateErrorMargin / 2)),
pbos@webrtc.org3f83f9c2014-03-13 12:52:27594 num_bitrate_observations_in_range_(0) {}
595
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52596 private:
stefanf5a44e82015-10-27 15:29:42597 // TODO(holmer): Run this with a timer instead of once per packet.
598 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org3f83f9c2014-03-13 12:52:27599 VideoSendStream::Stats stats = send_stream_->GetStats();
600 if (stats.substreams.size() > 0) {
kwiberg4cb29f62016-11-28 23:21:39601 RTC_DCHECK_EQ(1, stats.substreams.size());
stefan@webrtc.org52322672014-11-05 14:05:29602 int bitrate_kbps =
603 stats.substreams.begin()->second.total_bitrate_bps / 1000;
Danil Chapovalov8e697aa2016-06-16 07:58:44604 if (bitrate_kbps > min_acceptable_bitrate_ &&
605 bitrate_kbps < max_acceptable_bitrate_) {
606 converged_ = true;
607 ++num_bitrate_observations_in_range_;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27608 if (num_bitrate_observations_in_range_ ==
609 kNumBitrateObservationsInRange)
Peter Boström1cddafe2015-12-10 12:02:50610 observation_complete_.Set();
pbos@webrtc.org3f83f9c2014-03-13 12:52:27611 }
Danil Chapovalov8e697aa2016-06-16 07:58:44612 if (converged_)
613 bitrate_kbps_list_.push_back(bitrate_kbps);
pbos@webrtc.org3f83f9c2014-03-13 12:52:27614 }
stefanf5a44e82015-10-27 15:29:42615 return SEND_PACKET;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27616 }
617
stefan19cc2832015-12-21 11:14:00618 void OnVideoStreamsCreated(
pbos@webrtc.org88b558f2014-06-30 13:19:09619 VideoSendStream* send_stream,
kjellander@webrtc.org860ac532015-03-04 12:58:35620 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52621 send_stream_ = send_stream;
622 }
623
stefan19cc2832015-12-21 11:14:00624 void ModifyVideoConfigs(
625 VideoSendStream::Config* send_config,
626 std::vector<VideoReceiveStream::Config>* receive_configs,
627 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52628 if (pad_to_min_bitrate_) {
pbos@webrtc.org23668752014-10-24 09:23:21629 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52630 } else {
henrikg5c075c82015-09-17 07:24:34631 RTC_DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52632 }
633 }
634
kjellander@webrtc.org860ac532015-03-04 12:58:35635 void PerformTest() override {
Peter Boström1cddafe2015-12-10 12:02:50636 EXPECT_TRUE(Wait()) << "Timeout while waiting for send-bitrate stats.";
danilchapdfd2f302016-06-03 16:27:37637 test::PrintResultList(
638 "bitrate_stats_",
639 (pad_to_min_bitrate_ ? "min_transmit_bitrate"
640 : "without_min_transmit_bitrate"),
Danil Chapovalov8e697aa2016-06-16 07:58:44641 "bitrate_kbps", test::ValuesToString(bitrate_kbps_list_), "kbps",
danilchapdfd2f302016-06-03 16:27:37642 false);
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52643 }
644
pbos@webrtc.org3f83f9c2014-03-13 12:52:27645 VideoSendStream* send_stream_;
Danil Chapovalov8e697aa2016-06-16 07:58:44646 bool converged_;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52647 const bool pad_to_min_bitrate_;
Danil Chapovalov8e697aa2016-06-16 07:58:44648 const int min_acceptable_bitrate_;
649 const int max_acceptable_bitrate_;
pbos@webrtc.org3f83f9c2014-03-13 12:52:27650 int num_bitrate_observations_in_range_;
Danil Chapovalov8e697aa2016-06-16 07:58:44651 std::vector<size_t> bitrate_kbps_list_;
pbos@webrtc.orgeb67a6b2014-06-27 08:47:52652 } test(pad_to_min_bitrate);
pbos@webrtc.org3f83f9c2014-03-13 12:52:27653
pbos@webrtc.org3f83f9c2014-03-13 12:52:27654 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
stefan26f9c182016-01-08 14:47:13655 RunBaseTest(&test);
pbos@webrtc.org3f83f9c2014-03-13 12:52:27656}
657
658TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
659
660TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
661 TestMinTransmitBitrate(false);
662}
663
pbos@webrtc.org1c079a92014-10-22 12:15:24664TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) {
665 static const uint32_t kInitialBitrateKbps = 400;
666 static const uint32_t kReconfigureThresholdKbps = 600;
667 static const uint32_t kPermittedReconfiguredBitrateDiffKbps = 100;
668
perkj730a9e72016-10-03 06:45:26669 class VideoStreamFactory
670 : public VideoEncoderConfig::VideoStreamFactoryInterface {
671 public:
672 VideoStreamFactory() {}
673
674 private:
675 std::vector<VideoStream> CreateEncoderStreams(
676 int width,
677 int height,
678 const VideoEncoderConfig& encoder_config) override {
679 std::vector<VideoStream> streams =
680 test::CreateVideoStreams(width, height, encoder_config);
681 streams[0].min_bitrate_bps = 50000;
682 streams[0].target_bitrate_bps = streams[0].max_bitrate_bps = 2000000;
683 return streams;
684 }
685 };
686
pbos@webrtc.org1c079a92014-10-22 12:15:24687 class BitrateObserver : public test::EndToEndTest, public test::FakeEncoder {
688 public:
689 BitrateObserver()
690 : EndToEndTest(kDefaultTimeoutMs),
691 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström1cddafe2015-12-10 12:02:50692 time_to_reconfigure_(false, false),
sprang374a5702015-08-03 11:38:41693 encoder_inits_(0),
Erik Språngfafcfc02016-11-16 15:41:30694 last_set_bitrate_kbps_(0),
695 send_stream_(nullptr),
696 frame_generator_(nullptr) {}
pbos@webrtc.org1c079a92014-10-22 12:15:24697
kjellander@webrtc.org860ac532015-03-04 12:58:35698 int32_t InitEncode(const VideoCodec* config,
699 int32_t number_of_cores,
700 size_t max_payload_size) override {
perkj730a9e72016-10-03 06:45:26701 ++encoder_inits_;
702 if (encoder_inits_ == 1) {
emircan8e031082016-10-28 21:06:29703 // First time initialization. Frame size is known.
Perd70ef592016-10-30 20:37:57704 // |expected_bitrate| is affected by bandwidth estimation before the
705 // first frame arrives to the encoder.
Erik Språngfafcfc02016-11-16 15:41:30706 uint32_t expected_bitrate = last_set_bitrate_kbps_ > 0
707 ? last_set_bitrate_kbps_
708 : kInitialBitrateKbps;
Perd70ef592016-10-30 20:37:57709 EXPECT_EQ(expected_bitrate, config->startBitrate)
710 << "Encoder not initialized at expected bitrate.";
perkj730a9e72016-10-03 06:45:26711 EXPECT_EQ(kDefaultWidth, config->width);
712 EXPECT_EQ(kDefaultHeight, config->height);
Perd70ef592016-10-30 20:37:57713 } else if (encoder_inits_ == 2) {
perkj730a9e72016-10-03 06:45:26714 EXPECT_EQ(2 * kDefaultWidth, config->width);
715 EXPECT_EQ(2 * kDefaultHeight, config->height);
Erik Språngfafcfc02016-11-16 15:41:30716 EXPECT_GE(last_set_bitrate_kbps_, kReconfigureThresholdKbps);
Stefan Holmer0e65b342017-02-06 16:17:57717 EXPECT_GT(
718 config->startBitrate,
719 last_set_bitrate_kbps_ - kPermittedReconfiguredBitrateDiffKbps)
pbos@webrtc.org1c079a92014-10-22 12:15:24720 << "Encoder reconfigured with bitrate too far away from last set.";
Peter Boström1cddafe2015-12-10 12:02:50721 observation_complete_.Set();
pbos@webrtc.org1c079a92014-10-22 12:15:24722 }
723 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
724 }
725
Erik Språngfafcfc02016-11-16 15:41:30726 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
727 uint32_t framerate) override {
728 last_set_bitrate_kbps_ = rate_allocation.get_sum_kbps();
Perd70ef592016-10-30 20:37:57729 if (encoder_inits_ == 1 &&
Erik Språngfafcfc02016-11-16 15:41:30730 rate_allocation.get_sum_kbps() > kReconfigureThresholdKbps) {
Peter Boström1cddafe2015-12-10 12:02:50731 time_to_reconfigure_.Set();
pbos@webrtc.org1c079a92014-10-22 12:15:24732 }
Erik Språngfafcfc02016-11-16 15:41:30733 return FakeEncoder::SetRateAllocation(rate_allocation, framerate);
pbos@webrtc.org1c079a92014-10-22 12:15:24734 }
735
kjellander@webrtc.org860ac532015-03-04 12:58:35736 Call::Config GetSenderCallConfig() override {
pbos@webrtc.org1c079a92014-10-22 12:15:24737 Call::Config config = EndToEndTest::GetSenderCallConfig();
philipelcdb94392017-04-10 10:54:05738 config.event_log = event_log_.get();
Stefan Holmerca55fa12015-03-26 10:11:06739 config.bitrate_config.start_bitrate_bps = kInitialBitrateKbps * 1000;
pbos@webrtc.org1c079a92014-10-22 12:15:24740 return config;
741 }
742
stefan19cc2832015-12-21 11:14:00743 void ModifyVideoConfigs(
744 VideoSendStream::Config* send_config,
745 std::vector<VideoReceiveStream::Config>* receive_configs,
746 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org1c079a92014-10-22 12:15:24747 send_config->encoder_settings.encoder = this;
Perd70ef592016-10-30 20:37:57748 encoder_config->max_bitrate_bps = 2 * kReconfigureThresholdKbps * 1000;
perkj730a9e72016-10-03 06:45:26749 encoder_config->video_stream_factory =
750 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org1c079a92014-10-22 12:15:24751
perkj3f65eaf2016-09-01 08:17:40752 encoder_config_ = encoder_config->Copy();
pbos@webrtc.org1c079a92014-10-22 12:15:24753 }
754
stefan19cc2832015-12-21 11:14:00755 void OnVideoStreamsCreated(
pbos@webrtc.org1c079a92014-10-22 12:15:24756 VideoSendStream* send_stream,
kjellander@webrtc.org860ac532015-03-04 12:58:35757 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org1c079a92014-10-22 12:15:24758 send_stream_ = send_stream;
759 }
760
perkj730a9e72016-10-03 06:45:26761 void OnFrameGeneratorCapturerCreated(
762 test::FrameGeneratorCapturer* frame_generator_capturer) override {
763 frame_generator_ = frame_generator_capturer;
764 }
765
kjellander@webrtc.org860ac532015-03-04 12:58:35766 void PerformTest() override {
Peter Boström1cddafe2015-12-10 12:02:50767 ASSERT_TRUE(time_to_reconfigure_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org1c079a92014-10-22 12:15:24768 << "Timed out before receiving an initial high bitrate.";
perkj730a9e72016-10-03 06:45:26769 frame_generator_->ChangeResolution(kDefaultWidth * 2, kDefaultHeight * 2);
perkj3f65eaf2016-09-01 08:17:40770 send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
Peter Boström1cddafe2015-12-10 12:02:50771 EXPECT_TRUE(Wait())
pbos@webrtc.org1c079a92014-10-22 12:15:24772 << "Timed out while waiting for a couple of high bitrate estimates "
773 "after reconfiguring the send stream.";
774 }
775
776 private:
Peter Boström1cddafe2015-12-10 12:02:50777 rtc::Event time_to_reconfigure_;
pbos@webrtc.org1c079a92014-10-22 12:15:24778 int encoder_inits_;
Erik Språngfafcfc02016-11-16 15:41:30779 uint32_t last_set_bitrate_kbps_;
pbos@webrtc.org1c079a92014-10-22 12:15:24780 VideoSendStream* send_stream_;
perkj730a9e72016-10-03 06:45:26781 test::FrameGeneratorCapturer* frame_generator_;
pbos@webrtc.org1c079a92014-10-22 12:15:24782 VideoEncoderConfig encoder_config_;
783 } test;
784
stefan26f9c182016-01-08 14:47:13785 RunBaseTest(&test);
pbos@webrtc.org1c079a92014-10-22 12:15:24786}
787
pbos@webrtc.orgf94ccd42013-12-13 12:48:05788} // namespace webrtc