1 /*
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 <algorithm>
11 #include <sstream>
12 #include <string>
13 
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/scoped_ptr.h"
18 #include "webrtc/base/thread_annotations.h"
19 #include "webrtc/call.h"
20 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.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/rtp_to_ntp.h"
25 #include "webrtc/test/call_test.h"
26 #include "webrtc/test/direct_transport.h"
27 #include "webrtc/test/encoder_settings.h"
28 #include "webrtc/test/fake_audio_device.h"
29 #include "webrtc/test/fake_decoder.h"
30 #include "webrtc/test/fake_encoder.h"
31 #include "webrtc/test/frame_generator.h"
32 #include "webrtc/test/frame_generator_capturer.h"
33 #include "webrtc/test/rtp_rtcp_observer.h"
34 #include "webrtc/test/testsupport/fileutils.h"
35 #include "webrtc/test/testsupport/perf_test.h"
36 #include "webrtc/video/transport_adapter.h"
37 #include "webrtc/voice_engine/include/voe_base.h"
38 #include "webrtc/voice_engine/include/voe_codec.h"
39 #include "webrtc/voice_engine/include/voe_network.h"
40 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
41 #include "webrtc/voice_engine/include/voe_video_sync.h"
42 
43 namespace webrtc {
44 
45 class CallPerfTest : public test::CallTest {
46  protected:
47   void TestAudioVideoSync(bool fec);
48 
49   void TestCpuOveruse(LoadObserver::Load tested_load, int encode_delay_ms);
50 
51   void TestMinTransmitBitrate(bool pad_to_min_bitrate);
52 
53   void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
54                           int threshold_ms,
55                           int start_time_ms,
56                           int run_time_ms);
57 };
58 
59 class SyncRtcpObserver : public test::RtpRtcpObserver {
60  public:
SyncRtcpObserver(const FakeNetworkPipe::Config & config)61   explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
62       : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs, config),
63         crit_(CriticalSectionWrapper::CreateCriticalSection()) {}
64 
OnSendRtcp(const uint8_t * packet,size_t length)65   Action OnSendRtcp(const uint8_t* packet, size_t length) override {
66     RTCPUtility::RTCPParserV2 parser(packet, length, true);
67     EXPECT_TRUE(parser.IsValid());
68 
69     for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
70          packet_type != RTCPUtility::kRtcpNotValidCode;
71          packet_type = parser.Iterate()) {
72       if (packet_type == RTCPUtility::kRtcpSrCode) {
73         const RTCPUtility::RTCPPacket& packet = parser.Packet();
74         RtcpMeasurement ntp_rtp_pair(
75             packet.SR.NTPMostSignificant,
76             packet.SR.NTPLeastSignificant,
77             packet.SR.RTPTimestamp);
78         StoreNtpRtpPair(ntp_rtp_pair);
79       }
80     }
81     return SEND_PACKET;
82   }
83 
RtpTimestampToNtp(uint32_t timestamp) const84   int64_t RtpTimestampToNtp(uint32_t timestamp) const {
85     CriticalSectionScoped lock(crit_.get());
86     int64_t timestamp_in_ms = -1;
87     if (ntp_rtp_pairs_.size() == 2) {
88       // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
89       // RTCP sender where it sends RTCP SR before any RTP packets, which leads
90       // to a bogus NTP/RTP mapping.
91       RtpToNtpMs(timestamp, ntp_rtp_pairs_, &timestamp_in_ms);
92       return timestamp_in_ms;
93     }
94     return -1;
95   }
96 
97  private:
StoreNtpRtpPair(RtcpMeasurement ntp_rtp_pair)98   void StoreNtpRtpPair(RtcpMeasurement ntp_rtp_pair) {
99     CriticalSectionScoped lock(crit_.get());
100     for (RtcpList::iterator it = ntp_rtp_pairs_.begin();
101          it != ntp_rtp_pairs_.end();
102          ++it) {
103       if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
104           ntp_rtp_pair.ntp_frac == it->ntp_frac) {
105         // This RTCP has already been added to the list.
106         return;
107       }
108     }
109     // We need two RTCP SR reports to map between RTP and NTP. More than two
110     // will not improve the mapping.
111     if (ntp_rtp_pairs_.size() == 2) {
112       ntp_rtp_pairs_.pop_back();
113     }
114     ntp_rtp_pairs_.push_front(ntp_rtp_pair);
115   }
116 
117   const rtc::scoped_ptr<CriticalSectionWrapper> crit_;
118   RtcpList ntp_rtp_pairs_ GUARDED_BY(crit_);
119 };
120 
121 class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
122   static const int kInSyncThresholdMs = 50;
123   static const int kStartupTimeMs = 2000;
124   static const int kMinRunTimeMs = 30000;
125 
126  public:
VideoRtcpAndSyncObserver(Clock * clock,int voe_channel,VoEVideoSync * voe_sync,SyncRtcpObserver * audio_observer)127   VideoRtcpAndSyncObserver(Clock* clock,
128                            int voe_channel,
129                            VoEVideoSync* voe_sync,
130                            SyncRtcpObserver* audio_observer)
131       : SyncRtcpObserver(FakeNetworkPipe::Config()),
132         clock_(clock),
133         voe_channel_(voe_channel),
134         voe_sync_(voe_sync),
135         audio_observer_(audio_observer),
136         creation_time_ms_(clock_->TimeInMilliseconds()),
137         first_time_in_sync_(-1) {}
138 
RenderFrame(const I420VideoFrame & video_frame,int time_to_render_ms)139   void RenderFrame(const I420VideoFrame& video_frame,
140                    int time_to_render_ms) override {
141     int64_t now_ms = clock_->TimeInMilliseconds();
142     uint32_t playout_timestamp = 0;
143     if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
144       return;
145     int64_t latest_audio_ntp =
146         audio_observer_->RtpTimestampToNtp(playout_timestamp);
147     int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
148     if (latest_audio_ntp < 0 || latest_video_ntp < 0)
149       return;
150     int time_until_render_ms =
151         std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
152     latest_video_ntp += time_until_render_ms;
153     int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
154     std::stringstream ss;
155     ss << stream_offset;
156     webrtc::test::PrintResult("stream_offset",
157                               "",
158                               "synchronization",
159                               ss.str(),
160                               "ms",
161                               false);
162     int64_t time_since_creation = now_ms - creation_time_ms_;
163     // During the first couple of seconds audio and video can falsely be
164     // estimated as being synchronized. We don't want to trigger on those.
165     if (time_since_creation < kStartupTimeMs)
166       return;
167     if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
168       if (first_time_in_sync_ == -1) {
169         first_time_in_sync_ = now_ms;
170         webrtc::test::PrintResult("sync_convergence_time",
171                                   "",
172                                   "synchronization",
173                                   time_since_creation,
174                                   "ms",
175                                   false);
176       }
177       if (time_since_creation > kMinRunTimeMs)
178         observation_complete_->Set();
179     }
180   }
181 
IsTextureSupported() const182   bool IsTextureSupported() const override { return false; }
183 
184  private:
185   Clock* const clock_;
186   int voe_channel_;
187   VoEVideoSync* voe_sync_;
188   SyncRtcpObserver* audio_observer_;
189   int64_t creation_time_ms_;
190   int64_t first_time_in_sync_;
191 };
192 
TestAudioVideoSync(bool fec)193 void CallPerfTest::TestAudioVideoSync(bool fec) {
194   class AudioPacketReceiver : public PacketReceiver {
195    public:
196     AudioPacketReceiver(int channel, VoENetwork* voe_network)
197         : channel_(channel),
198           voe_network_(voe_network),
199           parser_(RtpHeaderParser::Create()) {}
200     DeliveryStatus DeliverPacket(const uint8_t* packet,
201                                  size_t length) override {
202       int ret;
203       if (parser_->IsRtcp(packet, length)) {
204         ret = voe_network_->ReceivedRTCPPacket(channel_, packet, length);
205       } else {
206         ret = voe_network_->ReceivedRTPPacket(channel_, packet, length,
207                                               PacketTime());
208       }
209       return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
210     }
211 
212    private:
213     int channel_;
214     VoENetwork* voe_network_;
215     rtc::scoped_ptr<RtpHeaderParser> parser_;
216   };
217 
218   VoiceEngine* voice_engine = VoiceEngine::Create();
219   VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
220   VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
221   VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
222   VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
223   const std::string audio_filename =
224       test::ResourcePath("voice_engine/audio_long16", "pcm");
225   ASSERT_STRNE("", audio_filename.c_str());
226   test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
227                                           audio_filename);
228   EXPECT_EQ(0, voe_base->Init(&fake_audio_device, nullptr));
229   int channel = voe_base->CreateChannel();
230 
231   FakeNetworkPipe::Config net_config;
232   net_config.queue_delay_ms = 500;
233   net_config.loss_percent = 5;
234   SyncRtcpObserver audio_observer(net_config);
235   VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(),
236                                     channel,
237                                     voe_sync,
238                                     &audio_observer);
239 
240   Call::Config receiver_config(observer.ReceiveTransport());
241   receiver_config.voice_engine = voice_engine;
242   CreateCalls(Call::Config(observer.SendTransport()), receiver_config);
243 
244   CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
245   EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
246 
247   AudioPacketReceiver voe_packet_receiver(channel, voe_network);
248   audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
249 
250   internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
251   transport_adapter.Enable();
252   EXPECT_EQ(0,
253             voe_network->RegisterExternalTransport(channel, transport_adapter));
254 
255   observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
256 
257   test::FakeDecoder fake_decoder;
258 
259   CreateSendConfig(1);
260   CreateMatchingReceiveConfigs();
261 
262   send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
263   if (fec) {
264     send_config_.rtp.fec.red_payload_type = kRedPayloadType;
265     send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
266     receive_configs_[0].rtp.fec.red_payload_type = kRedPayloadType;
267     receive_configs_[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
268   }
269   receive_configs_[0].rtp.nack.rtp_history_ms = 1000;
270   receive_configs_[0].renderer = &observer;
271   receive_configs_[0].audio_channel_id = channel;
272 
273   CreateStreams();
274 
275   CreateFrameGeneratorCapturer();
276 
277   Start();
278 
279   fake_audio_device.Start();
280   EXPECT_EQ(0, voe_base->StartPlayout(channel));
281   EXPECT_EQ(0, voe_base->StartReceive(channel));
282   EXPECT_EQ(0, voe_base->StartSend(channel));
283 
284   EXPECT_EQ(kEventSignaled, observer.Wait())
285       << "Timed out while waiting for audio and video to be synchronized.";
286 
287   EXPECT_EQ(0, voe_base->StopSend(channel));
288   EXPECT_EQ(0, voe_base->StopReceive(channel));
289   EXPECT_EQ(0, voe_base->StopPlayout(channel));
290   fake_audio_device.Stop();
291 
292   Stop();
293   observer.StopSending();
294   audio_observer.StopSending();
295 
296   voe_base->DeleteChannel(channel);
297   voe_base->Release();
298   voe_codec->Release();
299   voe_network->Release();
300   voe_sync->Release();
301 
302   DestroyStreams();
303 
304   VoiceEngine::Delete(voice_engine);
305 }
306 
TEST_F(CallPerfTest,PlaysOutAudioAndVideoInSync)307 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
308   TestAudioVideoSync(false);
309 }
310 
TEST_F(CallPerfTest,PlaysOutAudioAndVideoInSyncWithFec)311 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithFec) {
312   TestAudioVideoSync(true);
313 }
314 
TestCaptureNtpTime(const FakeNetworkPipe::Config & net_config,int threshold_ms,int start_time_ms,int run_time_ms)315 void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
316                                       int threshold_ms,
317                                       int start_time_ms,
318                                       int run_time_ms) {
319   class CaptureNtpTimeObserver : public test::EndToEndTest,
320                                  public VideoRenderer {
321    public:
322     CaptureNtpTimeObserver(const FakeNetworkPipe::Config& config,
323                            int threshold_ms,
324                            int start_time_ms,
325                            int run_time_ms)
326         : EndToEndTest(kLongTimeoutMs, config),
327           clock_(Clock::GetRealTimeClock()),
328           threshold_ms_(threshold_ms),
329           start_time_ms_(start_time_ms),
330           run_time_ms_(run_time_ms),
331           creation_time_ms_(clock_->TimeInMilliseconds()),
332           capturer_(nullptr),
333           rtp_start_timestamp_set_(false),
334           rtp_start_timestamp_(0) {}
335 
336    private:
337     void RenderFrame(const I420VideoFrame& video_frame,
338                      int time_to_render_ms) override {
339       if (video_frame.ntp_time_ms() <= 0) {
340         // Haven't got enough RTCP SR in order to calculate the capture ntp
341         // time.
342         return;
343       }
344 
345       int64_t now_ms = clock_->TimeInMilliseconds();
346       int64_t time_since_creation = now_ms - creation_time_ms_;
347       if (time_since_creation < start_time_ms_) {
348         // Wait for |start_time_ms_| before start measuring.
349         return;
350       }
351 
352       if (time_since_creation > run_time_ms_) {
353         observation_complete_->Set();
354       }
355 
356       FrameCaptureTimeList::iterator iter =
357           capture_time_list_.find(video_frame.timestamp());
358       EXPECT_TRUE(iter != capture_time_list_.end());
359 
360       // The real capture time has been wrapped to uint32_t before converted
361       // to rtp timestamp in the sender side. So here we convert the estimated
362       // capture time to a uint32_t 90k timestamp also for comparing.
363       uint32_t estimated_capture_timestamp =
364           90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
365       uint32_t real_capture_timestamp = iter->second;
366       int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
367       time_offset_ms = time_offset_ms / 90;
368       std::stringstream ss;
369       ss << time_offset_ms;
370 
371       webrtc::test::PrintResult(
372           "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true);
373       EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
374     }
375 
376     bool IsTextureSupported() const override { return false; }
377 
378     virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
379       RTPHeader header;
380       EXPECT_TRUE(parser_->Parse(packet, length, &header));
381 
382       if (!rtp_start_timestamp_set_) {
383         // Calculate the rtp timestamp offset in order to calculate the real
384         // capture time.
385         uint32_t first_capture_timestamp =
386             90 * static_cast<uint32_t>(capturer_->first_frame_capture_time());
387         rtp_start_timestamp_ = header.timestamp - first_capture_timestamp;
388         rtp_start_timestamp_set_ = true;
389       }
390 
391       uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
392       capture_time_list_.insert(
393           capture_time_list_.end(),
394           std::make_pair(header.timestamp, capture_timestamp));
395       return SEND_PACKET;
396     }
397 
398     void OnFrameGeneratorCapturerCreated(
399         test::FrameGeneratorCapturer* frame_generator_capturer) override {
400       capturer_ = frame_generator_capturer;
401     }
402 
403     void ModifyConfigs(VideoSendStream::Config* send_config,
404                        std::vector<VideoReceiveStream::Config>* receive_configs,
405                        VideoEncoderConfig* encoder_config) override {
406       (*receive_configs)[0].renderer = this;
407       // Enable the receiver side rtt calculation.
408       (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
409     }
410 
411     void PerformTest() override {
412       EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
413                                            "estimated capture NTP time to be "
414                                            "within bounds.";
415     }
416 
417     Clock* clock_;
418     int threshold_ms_;
419     int start_time_ms_;
420     int run_time_ms_;
421     int64_t creation_time_ms_;
422     test::FrameGeneratorCapturer* capturer_;
423     bool rtp_start_timestamp_set_;
424     uint32_t rtp_start_timestamp_;
425     typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
426     FrameCaptureTimeList capture_time_list_;
427   } test(net_config, threshold_ms, start_time_ms, run_time_ms);
428 
429   RunBaseTest(&test);
430 }
431 
TEST_F(CallPerfTest,CaptureNtpTimeWithNetworkDelay)432 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) {
433   FakeNetworkPipe::Config net_config;
434   net_config.queue_delay_ms = 100;
435   // TODO(wu): lower the threshold as the calculation/estimatation becomes more
436   // accurate.
437   const int kThresholdMs = 100;
438   const int kStartTimeMs = 10000;
439   const int kRunTimeMs = 20000;
440   TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs);
441 }
442 
TEST_F(CallPerfTest,CaptureNtpTimeWithNetworkJitter)443 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) {
444   FakeNetworkPipe::Config net_config;
445   net_config.queue_delay_ms = 100;
446   net_config.delay_standard_deviation_ms = 10;
447   // TODO(wu): lower the threshold as the calculation/estimatation becomes more
448   // accurate.
449   const int kThresholdMs = 100;
450   const int kStartTimeMs = 10000;
451   const int kRunTimeMs = 20000;
452   TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs);
453 }
454 
TestCpuOveruse(LoadObserver::Load tested_load,int encode_delay_ms)455 void CallPerfTest::TestCpuOveruse(LoadObserver::Load tested_load,
456                                   int encode_delay_ms) {
457   class LoadObserver : public test::SendTest, public webrtc::LoadObserver {
458    public:
459     LoadObserver(LoadObserver::Load tested_load, int encode_delay_ms)
460         : SendTest(kLongTimeoutMs),
461           tested_load_(tested_load),
462           encoder_(Clock::GetRealTimeClock(), encode_delay_ms) {}
463 
464     void OnLoadUpdate(Load load) override {
465       if (load == tested_load_)
466         observation_complete_->Set();
467     }
468 
469     Call::Config GetSenderCallConfig() override {
470       Call::Config config(SendTransport());
471       config.overuse_callback = this;
472       return config;
473     }
474 
475     void ModifyConfigs(VideoSendStream::Config* send_config,
476                        std::vector<VideoReceiveStream::Config>* receive_configs,
477                        VideoEncoderConfig* encoder_config) override {
478       send_config->encoder_settings.encoder = &encoder_;
479     }
480 
481     void PerformTest() override {
482       EXPECT_EQ(kEventSignaled, Wait())
483           << "Timed out before receiving an overuse callback.";
484     }
485 
486     LoadObserver::Load tested_load_;
487     test::DelayedEncoder encoder_;
488   } test(tested_load, encode_delay_ms);
489 
490   RunBaseTest(&test);
491 }
492 
TEST_F(CallPerfTest,ReceivesCpuUnderuse)493 TEST_F(CallPerfTest, ReceivesCpuUnderuse) {
494   const int kEncodeDelayMs = 2;
495   TestCpuOveruse(LoadObserver::kUnderuse, kEncodeDelayMs);
496 }
497 
TEST_F(CallPerfTest,ReceivesCpuOveruse)498 TEST_F(CallPerfTest, ReceivesCpuOveruse) {
499   const int kEncodeDelayMs = 35;
500   TestCpuOveruse(LoadObserver::kOveruse, kEncodeDelayMs);
501 }
502 
TestMinTransmitBitrate(bool pad_to_min_bitrate)503 void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
504   static const int kMaxEncodeBitrateKbps = 30;
505   static const int kMinTransmitBitrateBps = 150000;
506   static const int kMinAcceptableTransmitBitrate = 130;
507   static const int kMaxAcceptableTransmitBitrate = 170;
508   static const int kNumBitrateObservationsInRange = 100;
509   class BitrateObserver : public test::EndToEndTest, public PacketReceiver {
510    public:
511     explicit BitrateObserver(bool using_min_transmit_bitrate)
512         : EndToEndTest(kLongTimeoutMs),
513           send_stream_(nullptr),
514           send_transport_receiver_(nullptr),
515           pad_to_min_bitrate_(using_min_transmit_bitrate),
516           num_bitrate_observations_in_range_(0) {}
517 
518    private:
519     void SetReceivers(PacketReceiver* send_transport_receiver,
520                       PacketReceiver* receive_transport_receiver) override {
521       send_transport_receiver_ = send_transport_receiver;
522       test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
523     }
524 
525     DeliveryStatus DeliverPacket(const uint8_t* packet,
526                                  size_t length) override {
527       VideoSendStream::Stats stats = send_stream_->GetStats();
528       if (stats.substreams.size() > 0) {
529         DCHECK_EQ(1u, stats.substreams.size());
530         int bitrate_kbps =
531             stats.substreams.begin()->second.total_bitrate_bps / 1000;
532         if (bitrate_kbps > 0) {
533           test::PrintResult(
534               "bitrate_stats_",
535               (pad_to_min_bitrate_ ? "min_transmit_bitrate"
536                                    : "without_min_transmit_bitrate"),
537               "bitrate_kbps",
538               static_cast<size_t>(bitrate_kbps),
539               "kbps",
540               false);
541           if (pad_to_min_bitrate_) {
542             if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
543                 bitrate_kbps < kMaxAcceptableTransmitBitrate) {
544               ++num_bitrate_observations_in_range_;
545             }
546           } else {
547             // Expect bitrate stats to roughly match the max encode bitrate.
548             if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 &&
549                 bitrate_kbps < kMaxEncodeBitrateKbps + 5) {
550               ++num_bitrate_observations_in_range_;
551             }
552           }
553           if (num_bitrate_observations_in_range_ ==
554               kNumBitrateObservationsInRange)
555             observation_complete_->Set();
556         }
557       }
558       return send_transport_receiver_->DeliverPacket(packet, length);
559     }
560 
561     void OnStreamsCreated(
562         VideoSendStream* send_stream,
563         const std::vector<VideoReceiveStream*>& receive_streams) override {
564       send_stream_ = send_stream;
565     }
566 
567     void ModifyConfigs(VideoSendStream::Config* send_config,
568                        std::vector<VideoReceiveStream::Config>* receive_configs,
569                        VideoEncoderConfig* encoder_config) override {
570       if (pad_to_min_bitrate_) {
571         encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
572       } else {
573         DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps);
574       }
575     }
576 
577     void PerformTest() override {
578       EXPECT_EQ(kEventSignaled, Wait())
579           << "Timeout while waiting for send-bitrate stats.";
580     }
581 
582     VideoSendStream* send_stream_;
583     PacketReceiver* send_transport_receiver_;
584     const bool pad_to_min_bitrate_;
585     int num_bitrate_observations_in_range_;
586   } test(pad_to_min_bitrate);
587 
588   fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
589   RunBaseTest(&test);
590 }
591 
TEST_F(CallPerfTest,PadsToMinTransmitBitrate)592 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
593 
TEST_F(CallPerfTest,NoPadWithoutMinTransmitBitrate)594 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
595   TestMinTransmitBitrate(false);
596 }
597 
TEST_F(CallPerfTest,KeepsHighBitrateWhenReconfiguringSender)598 TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) {
599   static const uint32_t kInitialBitrateKbps = 400;
600   static const uint32_t kReconfigureThresholdKbps = 600;
601   static const uint32_t kPermittedReconfiguredBitrateDiffKbps = 100;
602 
603   class BitrateObserver : public test::EndToEndTest, public test::FakeEncoder {
604    public:
605     BitrateObserver()
606         : EndToEndTest(kDefaultTimeoutMs),
607           FakeEncoder(Clock::GetRealTimeClock()),
608           time_to_reconfigure_(webrtc::EventWrapper::Create()),
609           encoder_inits_(0) {}
610 
611     int32_t InitEncode(const VideoCodec* config,
612                        int32_t number_of_cores,
613                        size_t max_payload_size) override {
614       if (encoder_inits_ == 0) {
615         EXPECT_EQ(kInitialBitrateKbps, config->startBitrate)
616             << "Encoder not initialized at expected bitrate.";
617       }
618       ++encoder_inits_;
619       if (encoder_inits_ == 2) {
620         EXPECT_GE(last_set_bitrate_, kReconfigureThresholdKbps);
621         EXPECT_NEAR(config->startBitrate,
622                     last_set_bitrate_,
623                     kPermittedReconfiguredBitrateDiffKbps)
624             << "Encoder reconfigured with bitrate too far away from last set.";
625         observation_complete_->Set();
626       }
627       return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
628     }
629 
630     int32_t SetRates(uint32_t new_target_bitrate_kbps,
631                      uint32_t framerate) override {
632       last_set_bitrate_ = new_target_bitrate_kbps;
633       if (encoder_inits_ == 1 &&
634           new_target_bitrate_kbps > kReconfigureThresholdKbps) {
635         time_to_reconfigure_->Set();
636       }
637       return FakeEncoder::SetRates(new_target_bitrate_kbps, framerate);
638     }
639 
640     Call::Config GetSenderCallConfig() override {
641       Call::Config config = EndToEndTest::GetSenderCallConfig();
642       config.bitrate_config.start_bitrate_bps = kInitialBitrateKbps * 1000;
643       return config;
644     }
645 
646     void ModifyConfigs(VideoSendStream::Config* send_config,
647                        std::vector<VideoReceiveStream::Config>* receive_configs,
648                        VideoEncoderConfig* encoder_config) override {
649       send_config->encoder_settings.encoder = this;
650       encoder_config->streams[0].min_bitrate_bps = 50000;
651       encoder_config->streams[0].target_bitrate_bps =
652           encoder_config->streams[0].max_bitrate_bps = 2000000;
653 
654       encoder_config_ = *encoder_config;
655     }
656 
657     void OnStreamsCreated(
658         VideoSendStream* send_stream,
659         const std::vector<VideoReceiveStream*>& receive_streams) override {
660       send_stream_ = send_stream;
661     }
662 
663     void PerformTest() override {
664       ASSERT_EQ(kEventSignaled, time_to_reconfigure_->Wait(kDefaultTimeoutMs))
665           << "Timed out before receiving an initial high bitrate.";
666       encoder_config_.streams[0].width *= 2;
667       encoder_config_.streams[0].height *= 2;
668       EXPECT_TRUE(send_stream_->ReconfigureVideoEncoder(encoder_config_));
669       EXPECT_EQ(kEventSignaled, Wait())
670           << "Timed out while waiting for a couple of high bitrate estimates "
671              "after reconfiguring the send stream.";
672     }
673 
674    private:
675     rtc::scoped_ptr<webrtc::EventWrapper> time_to_reconfigure_;
676     int encoder_inits_;
677     uint32_t last_set_bitrate_;
678     VideoSendStream* send_stream_;
679     VideoEncoderConfig encoder_config_;
680   } test;
681 
682   RunBaseTest(&test);
683 }
684 
685 }  // namespace webrtc
686