• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2010 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 // If we don't have a WebRtcVideoFrame, just skip all of these tests.
29 #if defined(HAVE_WEBRTC_VIDEO)
30 #include <limits.h>  // For INT_MAX
31 #include <string>
32 #include <vector>
33 
34 #include "talk/media/base/fakevideocapturer.h"
35 #include "talk/media/base/mediachannel.h"
36 #include "talk/media/base/testutils.h"
37 #include "talk/media/base/videoadapter.h"
38 #include "webrtc/base/gunit.h"
39 #include "webrtc/base/logging.h"
40 #include "webrtc/base/sigslot.h"
41 
42 namespace cricket {
43 
44 namespace {
45 static const uint32_t kWaitTimeout = 3000U;       // 3 seconds.
46 static const uint32_t kShortWaitTimeout = 1000U;  // 1 second.
UpdateCpuLoad(CoordinatedVideoAdapter * adapter,int current_cpus,int max_cpus,float process_load,float system_load)47   void UpdateCpuLoad(CoordinatedVideoAdapter* adapter,
48     int current_cpus, int max_cpus, float process_load, float system_load) {
49     adapter->set_cpu_load_min_samples(1);
50     adapter->OnCpuLoadUpdated(current_cpus, max_cpus,
51                               process_load, system_load);
52   }
53 }
54 
55 class VideoAdapterTest : public testing::Test {
56  public:
SetUp()57   virtual void SetUp() {
58     capturer_.reset(new FakeVideoCapturer);
59     capture_format_ = capturer_->GetSupportedFormats()->at(0);
60     capture_format_.interval = VideoFormat::FpsToInterval(50);
61     adapter_.reset(new VideoAdapter());
62     adapter_->SetInputFormat(capture_format_);
63 
64     listener_.reset(new VideoCapturerListener(adapter_.get()));
65     capturer_->SignalFrameCaptured.connect(
66         listener_.get(), &VideoCapturerListener::OnFrameCaptured);
67   }
68 
TearDown()69   virtual void TearDown() {
70     // Explicitly disconnect the VideoCapturer before to avoid data races
71     // (frames delivered to VideoCapturerListener while it's being destructed).
72     capturer_->SignalFrameCaptured.disconnect_all();
73   }
74 
75  protected:
76   class VideoCapturerListener: public sigslot::has_slots<> {
77    public:
78     struct Stats {
79       int captured_frames;
80       int dropped_frames;
81       bool last_adapt_was_no_op;
82 
83       int adapted_width;
84       int adapted_height;
85     };
86 
VideoCapturerListener(VideoAdapter * adapter)87     explicit VideoCapturerListener(VideoAdapter* adapter)
88         : video_adapter_(adapter),
89           captured_frames_(0),
90           dropped_frames_(0),
91           last_adapt_was_no_op_(false) {
92     }
93 
OnFrameCaptured(VideoCapturer * capturer,const CapturedFrame * captured_frame)94     void OnFrameCaptured(VideoCapturer* capturer,
95                          const CapturedFrame* captured_frame) {
96       rtc::CritScope lock(&crit_);
97       const int in_width = captured_frame->width;
98       const int in_height = abs(captured_frame->height);
99       const VideoFormat adapted_format =
100           video_adapter_->AdaptFrameResolution(in_width, in_height);
101       if (!adapted_format.IsSize0x0()) {
102         adapted_format_ = adapted_format;
103         last_adapt_was_no_op_ = (in_width == adapted_format.width &&
104                                  in_height == adapted_format.height);
105       } else {
106         ++dropped_frames_;
107       }
108       ++captured_frames_;
109     }
110 
GetStats()111     Stats GetStats() {
112       rtc::CritScope lock(&crit_);
113       Stats stats;
114       stats.captured_frames = captured_frames_;
115       stats.dropped_frames = dropped_frames_;
116       stats.last_adapt_was_no_op = last_adapt_was_no_op_;
117       if (!adapted_format_.IsSize0x0()) {
118         stats.adapted_width = adapted_format_.width;
119         stats.adapted_height = adapted_format_.height;
120       } else {
121         stats.adapted_width = stats.adapted_height = -1;
122       }
123 
124       return stats;
125     }
126 
127    private:
128     rtc::CriticalSection crit_;
129     VideoAdapter* video_adapter_;
130     VideoFormat adapted_format_;
131     int captured_frames_;
132     int dropped_frames_;
133     bool last_adapt_was_no_op_;
134   };
135 
136   class CpuAdapterListener: public sigslot::has_slots<> {
137    public:
CpuAdapterListener()138     CpuAdapterListener() : received_cpu_signal_(false) {}
OnCpuAdaptationSignalled()139     void OnCpuAdaptationSignalled() { received_cpu_signal_ = true; }
received_cpu_signal()140     bool received_cpu_signal() { return received_cpu_signal_; }
141    private:
142     bool received_cpu_signal_;
143   };
144 
VerifyAdaptedResolution(const VideoCapturerListener::Stats & stats,int width,int height)145   void VerifyAdaptedResolution(const VideoCapturerListener::Stats& stats,
146                                int width,
147                                int height) {
148     EXPECT_EQ(width, stats.adapted_width);
149     EXPECT_EQ(height, stats.adapted_height);
150   }
151 
152   rtc::scoped_ptr<FakeVideoCapturer> capturer_;
153   rtc::scoped_ptr<VideoAdapter> adapter_;
154   rtc::scoped_ptr<VideoCapturerListener> listener_;
155   VideoFormat capture_format_;
156 };
157 
158 
159 // Test adapter remembers exact pixel count
TEST_F(VideoAdapterTest,AdaptNumPixels)160 TEST_F(VideoAdapterTest, AdaptNumPixels) {
161   adapter_->SetOutputNumPixels(123456);
162   EXPECT_EQ(123456, adapter_->GetOutputNumPixels());
163 }
164 
165 // Test adapter is constructed but not activated. Expect no frame drop and no
166 // resolution change.
TEST_F(VideoAdapterTest,AdaptInactive)167 TEST_F(VideoAdapterTest, AdaptInactive) {
168   // Output resolution is not set.
169   EXPECT_EQ(INT_MAX, adapter_->GetOutputNumPixels());
170 
171   // Call Adapter with some frames.
172   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
173   for (int i = 0; i < 10; ++i)
174     capturer_->CaptureFrame();
175 
176   // Verify no frame drop and no resolution change.
177   VideoCapturerListener::Stats stats = listener_->GetStats();
178   EXPECT_GE(stats.captured_frames, 10);
179   EXPECT_EQ(0, stats.dropped_frames);
180   VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
181 }
182 
183 // Do not adapt the frame rate or the resolution. Expect no frame drop and no
184 // resolution change.
TEST_F(VideoAdapterTest,AdaptNothing)185 TEST_F(VideoAdapterTest, AdaptNothing) {
186   adapter_->SetOutputFormat(capture_format_);
187   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
188   for (int i = 0; i < 10; ++i)
189     capturer_->CaptureFrame();
190 
191   // Verify no frame drop and no resolution change.
192   VideoCapturerListener::Stats stats = listener_->GetStats();
193   EXPECT_GE(stats.captured_frames, 10);
194   EXPECT_EQ(0, stats.dropped_frames);
195   VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
196   EXPECT_TRUE(stats.last_adapt_was_no_op);
197 }
198 
TEST_F(VideoAdapterTest,AdaptZeroInterval)199 TEST_F(VideoAdapterTest, AdaptZeroInterval) {
200   VideoFormat format = capturer_->GetSupportedFormats()->at(0);
201   format.interval = 0;
202   adapter_->SetInputFormat(format);
203   adapter_->SetOutputFormat(format);
204   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
205   for (int i = 0; i < 10; ++i)
206     capturer_->CaptureFrame();
207 
208   // Verify no crash and that frames aren't dropped.
209   VideoCapturerListener::Stats stats = listener_->GetStats();
210   EXPECT_GE(stats.captured_frames, 10);
211   EXPECT_EQ(0, stats.dropped_frames);
212   VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
213 }
214 
215 // Adapt the frame rate to be half of the capture rate at the beginning. Expect
216 // the number of dropped frames to be half of the number the captured frames.
TEST_F(VideoAdapterTest,AdaptFramerate)217 TEST_F(VideoAdapterTest, AdaptFramerate) {
218   VideoFormat request_format = capture_format_;
219   request_format.interval *= 2;
220   adapter_->SetOutputFormat(request_format);
221   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
222   for (int i = 0; i < 10; ++i)
223     capturer_->CaptureFrame();
224 
225   // Verify frame drop and no resolution change.
226   VideoCapturerListener::Stats stats = listener_->GetStats();
227   EXPECT_GE(stats.captured_frames, 10);
228   EXPECT_EQ(stats.captured_frames / 2, stats.dropped_frames);
229   VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
230 }
231 
232 // Adapt the frame rate to be half of the capture rate at the beginning. Expect
233 // the number of dropped frames to be half of the number the captured frames.
TEST_F(VideoAdapterTest,AdaptFramerateVariable)234 TEST_F(VideoAdapterTest, AdaptFramerateVariable) {
235   VideoFormat request_format = capture_format_;
236   request_format.interval = request_format.interval * 3 / 2;
237   adapter_->SetOutputFormat(request_format);
238   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
239   for (int i = 0; i < 30; ++i)
240     capturer_->CaptureFrame();
241 
242   // Verify frame drop and no resolution change.
243   VideoCapturerListener::Stats stats = listener_->GetStats();
244   EXPECT_GE(stats.captured_frames, 30);
245   // Verify 2 / 3 kept (20) and 1 / 3 dropped (10).
246   EXPECT_EQ(stats.captured_frames * 1 / 3, stats.dropped_frames);
247   VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
248 }
249 
250 // Adapt the frame rate to be half of the capture rate after capturing no less
251 // than 10 frames. Expect no frame dropped before adaptation and frame dropped
252 // after adaptation.
TEST_F(VideoAdapterTest,AdaptFramerateOntheFly)253 TEST_F(VideoAdapterTest, AdaptFramerateOntheFly) {
254   VideoFormat request_format = capture_format_;
255   adapter_->SetOutputFormat(request_format);
256   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
257   for (int i = 0; i < 10; ++i)
258     capturer_->CaptureFrame();
259 
260   // Verify no frame drop before adaptation.
261   EXPECT_EQ(0, listener_->GetStats().dropped_frames);
262 
263   // Adapat the frame rate.
264   request_format.interval *= 2;
265   adapter_->SetOutputFormat(request_format);
266 
267   for (int i = 0; i < 20; ++i)
268     capturer_->CaptureFrame();
269 
270   // Verify frame drop after adaptation.
271   EXPECT_GT(listener_->GetStats().dropped_frames, 0);
272 }
273 
274 // Set a very high output pixel resolution. Expect no resolution change.
TEST_F(VideoAdapterTest,AdaptFrameResolutionHighLimit)275 TEST_F(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
276   adapter_->SetOutputNumPixels(INT_MAX);
277   VideoFormat adapted_format = adapter_->AdaptFrameResolution(
278       capture_format_.width, capture_format_.height);
279   EXPECT_EQ(capture_format_.width, adapted_format.width);
280   EXPECT_EQ(capture_format_.height, adapted_format.height);
281 
282   adapter_->SetOutputNumPixels(987654321);
283   adapted_format = capture_format_,
284   adapter_->AdaptFrameResolution(capture_format_.width, capture_format_.height);
285   EXPECT_EQ(capture_format_.width, adapted_format.width);
286   EXPECT_EQ(capture_format_.height, adapted_format.height);
287 }
288 
289 // Adapt the frame resolution to be the same as capture resolution. Expect no
290 // resolution change.
TEST_F(VideoAdapterTest,AdaptFrameResolutionIdentical)291 TEST_F(VideoAdapterTest, AdaptFrameResolutionIdentical) {
292   adapter_->SetOutputFormat(capture_format_);
293   const VideoFormat adapted_format = adapter_->AdaptFrameResolution(
294       capture_format_.width, capture_format_.height);
295   EXPECT_EQ(capture_format_.width, adapted_format.width);
296   EXPECT_EQ(capture_format_.height, adapted_format.height);
297 }
298 
299 // Adapt the frame resolution to be a quarter of the capture resolution. Expect
300 // resolution change.
TEST_F(VideoAdapterTest,AdaptFrameResolutionQuarter)301 TEST_F(VideoAdapterTest, AdaptFrameResolutionQuarter) {
302   VideoFormat request_format = capture_format_;
303   request_format.width /= 2;
304   request_format.height /= 2;
305   adapter_->SetOutputFormat(request_format);
306   const VideoFormat adapted_format = adapter_->AdaptFrameResolution(
307       request_format.width, request_format.height);
308   EXPECT_EQ(request_format.width, adapted_format.width);
309   EXPECT_EQ(request_format.height, adapted_format.height);
310 }
311 
312 // Adapt the pixel resolution to 0. Expect frame drop.
TEST_F(VideoAdapterTest,AdaptFrameResolutionDrop)313 TEST_F(VideoAdapterTest, AdaptFrameResolutionDrop) {
314   adapter_->SetOutputNumPixels(0);
315   EXPECT_TRUE(
316       adapter_->AdaptFrameResolution(capture_format_.width,
317                                      capture_format_.height).IsSize0x0());
318 }
319 
320 // Adapt the frame resolution to be a quarter of the capture resolution at the
321 // beginning. Expect resolution change.
TEST_F(VideoAdapterTest,AdaptResolution)322 TEST_F(VideoAdapterTest, AdaptResolution) {
323   VideoFormat request_format = capture_format_;
324   request_format.width /= 2;
325   request_format.height /= 2;
326   adapter_->SetOutputFormat(request_format);
327   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
328   for (int i = 0; i < 10; ++i)
329     capturer_->CaptureFrame();
330 
331   // Verify no frame drop and resolution change.
332   VideoCapturerListener::Stats stats = listener_->GetStats();
333   EXPECT_EQ(0, stats.dropped_frames);
334   VerifyAdaptedResolution(stats, request_format.width, request_format.height);
335 }
336 
337 // Adapt the frame resolution to half width. Expect resolution change.
TEST_F(VideoAdapterTest,AdaptResolutionNarrow)338 TEST_F(VideoAdapterTest, AdaptResolutionNarrow) {
339   VideoFormat request_format = capture_format_;
340   request_format.width /= 2;
341   adapter_->set_scale_third(true);
342   adapter_->SetOutputFormat(request_format);
343   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
344   for (int i = 0; i < 10; ++i)
345     capturer_->CaptureFrame();
346 
347   // Verify resolution change.
348   VerifyAdaptedResolution(listener_->GetStats(),
349                           capture_format_.width * 2 / 3,
350                           capture_format_.height * 2 / 3);
351 }
352 
353 // Adapt the frame resolution to half height. Expect resolution change.
TEST_F(VideoAdapterTest,AdaptResolutionWide)354 TEST_F(VideoAdapterTest, AdaptResolutionWide) {
355   VideoFormat request_format = capture_format_;
356   request_format.height /= 2;
357   adapter_->set_scale_third(true);
358   adapter_->SetOutputFormat(request_format);
359   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
360   for (int i = 0; i < 10; ++i)
361     capturer_->CaptureFrame();
362 
363   // Verify resolution change.
364   VerifyAdaptedResolution(listener_->GetStats(),
365                           capture_format_.width * 2 / 3,
366                           capture_format_.height * 2 / 3);
367 }
368 
369 // Adapt the frame resolution to be a quarter of the capture resolution after
370 // capturing no less than 10 frames. Expect no resolution change before
371 // adaptation and resolution change after adaptation.
TEST_F(VideoAdapterTest,AdaptResolutionOnTheFly)372 TEST_F(VideoAdapterTest, AdaptResolutionOnTheFly) {
373   VideoFormat request_format = capture_format_;
374   adapter_->SetOutputFormat(request_format);
375   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
376   for (int i = 0; i < 10; ++i)
377     capturer_->CaptureFrame();
378 
379   // Verify no resolution change before adaptation.
380   VerifyAdaptedResolution(
381       listener_->GetStats(), request_format.width, request_format.height);
382 
383   // Adapt the frame resolution.
384   request_format.width /= 2;
385   request_format.height /= 2;
386   adapter_->SetOutputFormat(request_format);
387   for (int i = 0; i < 10; ++i)
388     capturer_->CaptureFrame();
389 
390   // Verify resolution change after adaptation.
391   VerifyAdaptedResolution(
392       listener_->GetStats(), request_format.width, request_format.height);
393 }
394 
395 // Drop all frames.
TEST_F(VideoAdapterTest,DropAllFrames)396 TEST_F(VideoAdapterTest, DropAllFrames) {
397   VideoFormat format;  // with resolution 0x0.
398   adapter_->SetOutputFormat(format);
399   EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
400   for (int i = 0; i < 10; ++i)
401     capturer_->CaptureFrame();
402 
403   // Verify all frames are dropped.
404   VideoCapturerListener::Stats stats = listener_->GetStats();
405   EXPECT_GE(stats.captured_frames, 10);
406   EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
407 }
408 
TEST(CoordinatedVideoAdapterTest,TestCoordinatedWithoutCpuAdaptation)409 TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithoutCpuAdaptation) {
410   CoordinatedVideoAdapter adapter;
411   adapter.set_cpu_adaptation(false);
412 
413   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
414   adapter.SetInputFormat(format);
415   adapter.set_scale_third(true);
416   EXPECT_EQ(format, adapter.input_format());
417   EXPECT_TRUE(adapter.output_format().IsSize0x0());
418 
419   // Server format request 640x400.
420   format.height = 400;
421   adapter.OnOutputFormatRequest(format);
422   EXPECT_EQ(640, adapter.output_format().width);
423   EXPECT_EQ(400, adapter.output_format().height);
424 
425   // Server format request 1280x720, higher than input. Adapt nothing.
426   format.width = 1280;
427   format.height = 720;
428   adapter.OnOutputFormatRequest(format);
429   EXPECT_EQ(640, adapter.output_format().width);
430   EXPECT_EQ(400, adapter.output_format().height);
431 
432   // Cpu load is high, but cpu adaptation is disabled. Adapt nothing.
433   adapter.OnCpuLoadUpdated(1, 1, 0.99f, 0.99f);
434   EXPECT_EQ(640, adapter.output_format().width);
435   EXPECT_EQ(400, adapter.output_format().height);
436 
437   // Encoder resolution request: downgrade with different size. Adapt nothing.
438   adapter.OnEncoderResolutionRequest(320, 200,
439                                      CoordinatedVideoAdapter::DOWNGRADE);
440   EXPECT_EQ(640, adapter.output_format().width);
441   EXPECT_EQ(400, adapter.output_format().height);
442 
443   // Encoder resolution request: downgrade.
444   adapter.OnEncoderResolutionRequest(640, 400,
445                                      CoordinatedVideoAdapter::DOWNGRADE);
446   EXPECT_EQ(480, adapter.output_format().width);
447   EXPECT_EQ(300, adapter.output_format().height);
448 
449   // Encoder resolution request: downgrade. But GD off. Adapt nothing.
450   adapter.set_gd_adaptation(false);
451   adapter.OnEncoderResolutionRequest(480, 300,
452                                      CoordinatedVideoAdapter::DOWNGRADE);
453   EXPECT_EQ(480, adapter.output_format().width);
454   EXPECT_EQ(300, adapter.output_format().height);
455   adapter.set_gd_adaptation(true);
456 
457   // Encoder resolution request: downgrade.
458   adapter.OnEncoderResolutionRequest(480, 300,
459                                      CoordinatedVideoAdapter::DOWNGRADE);
460   EXPECT_EQ(320, adapter.output_format().width);
461   EXPECT_EQ(200, adapter.output_format().height);
462 
463   // Encoder resolution request: keep. Adapt nothing.
464   adapter.OnEncoderResolutionRequest(320, 200,
465                                      CoordinatedVideoAdapter::KEEP);
466   EXPECT_EQ(320, adapter.output_format().width);
467   EXPECT_EQ(200, adapter.output_format().height);
468 
469   // Encoder resolution request: upgrade.
470   adapter.OnEncoderResolutionRequest(320, 200,
471                                      CoordinatedVideoAdapter::UPGRADE);
472   EXPECT_EQ(480, adapter.output_format().width);
473   EXPECT_EQ(300, adapter.output_format().height);
474 
475   // Server format request 0x0.
476   format.width = 0;
477   format.height = 0;
478   adapter.OnOutputFormatRequest(format);
479   EXPECT_TRUE(adapter.output_format().IsSize0x0());
480 
481   // Server format request 320x200.
482   format.width = 320;
483   format.height = 200;
484   adapter.OnOutputFormatRequest(format);
485   EXPECT_EQ(320, adapter.output_format().width);
486   EXPECT_EQ(200, adapter.output_format().height);
487 
488   // Server format request 160x100. But view disabled. Adapt nothing.
489   adapter.set_view_adaptation(false);
490   format.width = 160;
491   format.height = 100;
492   adapter.OnOutputFormatRequest(format);
493   EXPECT_EQ(320, adapter.output_format().width);
494   EXPECT_EQ(200, adapter.output_format().height);
495   adapter.set_view_adaptation(true);
496 
497   // Enable View Switch. Expect adapt down.
498   adapter.set_view_switch(true);
499   format.width = 160;
500   format.height = 100;
501   adapter.OnOutputFormatRequest(format);
502   EXPECT_EQ(160, adapter.output_format().width);
503   EXPECT_EQ(100, adapter.output_format().height);
504 
505   // Encoder resolution request: upgrade. Adapt nothing.
506   adapter.OnEncoderResolutionRequest(160, 100,
507                                      CoordinatedVideoAdapter::UPGRADE);
508   EXPECT_EQ(160, adapter.output_format().width);
509   EXPECT_EQ(100, adapter.output_format().height);
510 
511   // Request View of 2 / 3. Expect adapt down.
512   adapter.set_view_switch(true);
513   format.width = (640 * 2 + 1) / 3;
514   format.height = (400 * 2 + 1) / 3;
515   adapter.OnOutputFormatRequest(format);
516   EXPECT_EQ((640 * 2 + 1) / 3, adapter.output_format().width);
517   EXPECT_EQ((400 * 2 + 1) / 3, adapter.output_format().height);
518 
519 
520   // Request View of 3 / 8. Expect adapt down.
521   adapter.set_view_switch(true);
522   format.width = 640 * 3 / 8;
523   format.height = 400 * 3 / 8;
524   adapter.OnOutputFormatRequest(format);
525   EXPECT_EQ(640 * 3 / 8, adapter.output_format().width);
526   EXPECT_EQ(400 * 3 / 8, adapter.output_format().height);
527 
528   // View Switch back up. Expect adapt.
529   format.width = 320;
530   format.height = 200;
531   adapter.OnOutputFormatRequest(format);
532   EXPECT_EQ(320, adapter.output_format().width);
533   EXPECT_EQ(200, adapter.output_format().height);
534 
535   adapter.set_view_switch(false);
536 
537   // Encoder resolution request: upgrade. Constrained by server request.
538   adapter.OnEncoderResolutionRequest(320, 200,
539                                      CoordinatedVideoAdapter::UPGRADE);
540   EXPECT_EQ(320, adapter.output_format().width);
541   EXPECT_EQ(200, adapter.output_format().height);
542 
543   // Server format request 480x300.
544   format.width = 480;
545   format.height = 300;
546   adapter.OnOutputFormatRequest(format);
547   EXPECT_EQ(480, adapter.output_format().width);
548   EXPECT_EQ(300, adapter.output_format().height);
549 }
550 
TEST(CoordinatedVideoAdapterTest,TestCoordinatedWithCpuAdaptation)551 TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithCpuAdaptation) {
552   CoordinatedVideoAdapter adapter;
553   adapter.set_cpu_adaptation(true);
554   EXPECT_FALSE(adapter.cpu_smoothing());
555   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
556   adapter.SetInputFormat(format);
557 
558   // Server format request 640x400.
559   format.height = 400;
560   adapter.OnOutputFormatRequest(format);
561   EXPECT_EQ(640, adapter.output_format().width);
562   EXPECT_EQ(400, adapter.output_format().height);
563 
564   // Process load is medium, but system load is high. Downgrade.
565   UpdateCpuLoad(&adapter, 1, 1, 0.55f, 0.98f);
566   EXPECT_EQ(480, adapter.output_format().width);
567   EXPECT_EQ(300, adapter.output_format().height);
568 
569   // CPU high, but cpu adaptation disabled. Adapt nothing.
570   adapter.set_cpu_adaptation(false);
571   adapter.OnCpuLoadUpdated(1, 1, 0.55f, 0.98f);
572   EXPECT_EQ(480, adapter.output_format().width);
573   EXPECT_EQ(300, adapter.output_format().height);
574   adapter.set_cpu_adaptation(true);
575 
576   // System load is high, but time has not elaspsed. Adapt nothing.
577   adapter.set_cpu_load_min_samples(2);
578   adapter.OnCpuLoadUpdated(1, 1, 0.55f, 0.98f);
579   EXPECT_EQ(480, adapter.output_format().width);
580   EXPECT_EQ(300, adapter.output_format().height);
581 
582   // Process load is medium, but system load is high. Downgrade.
583   UpdateCpuLoad(&adapter, 1, 1, 0.55f, 0.98f);
584   EXPECT_EQ(320, adapter.output_format().width);
585   EXPECT_EQ(200, adapter.output_format().height);
586 
587   // Test reason for adapting is CPU.
588   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
589             adapter.adapt_reason());
590 
591   // Server format request 320x200. Same as CPU. Do nothing.
592   format.width = 320;
593   format.height = 200;
594   adapter.OnOutputFormatRequest(format);
595   EXPECT_EQ(320, adapter.output_format().width);
596   EXPECT_EQ(200, adapter.output_format().height);
597 
598   // Test reason for adapting is CPU and VIEW.
599   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
600             CoordinatedVideoAdapter::ADAPTREASON_VIEW,
601             adapter.adapt_reason());
602 
603   // Process load and system load are normal. Adapt nothing.
604   UpdateCpuLoad(&adapter, 1, 1, 0.5f, 0.8f);
605   EXPECT_EQ(320, adapter.output_format().width);
606   EXPECT_EQ(200, adapter.output_format().height);
607 
608   // Process load and system load are low, but view is still low. Adapt nothing.
609   UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
610   EXPECT_EQ(320, adapter.output_format().width);
611   EXPECT_EQ(200, adapter.output_format().height);
612 
613   // Test reason for adapting is VIEW.
614   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
615             adapter.adapt_reason());
616 
617   // Server format request 640x400. Cpu is still low.  Upgrade.
618   format.width = 640;
619   format.height = 400;
620   adapter.OnOutputFormatRequest(format);
621   EXPECT_EQ(480, adapter.output_format().width);
622   EXPECT_EQ(300, adapter.output_format().height);
623 
624   // Test reason for adapting is CPU.
625   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
626             adapter.adapt_reason());
627 
628   // Encoder resolution request: downgrade.
629   adapter.OnEncoderResolutionRequest(480, 300,
630                                      CoordinatedVideoAdapter::DOWNGRADE);
631   EXPECT_EQ(320, adapter.output_format().width);
632   EXPECT_EQ(200, adapter.output_format().height);
633 
634   // Test reason for adapting is BANDWIDTH.
635   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
636             adapter.adapt_reason());
637 
638   // Process load and system load are low. Constrained by GD. Adapt nothing
639   adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
640   EXPECT_EQ(320, adapter.output_format().width);
641   EXPECT_EQ(200, adapter.output_format().height);
642 
643   // Encoder resolution request: upgrade.
644   adapter.OnEncoderResolutionRequest(320, 200,
645                                      CoordinatedVideoAdapter::UPGRADE);
646   EXPECT_EQ(480, adapter.output_format().width);
647   EXPECT_EQ(300, adapter.output_format().height);
648 
649   // Encoder resolution request: upgrade. Constrained by CPU.
650   adapter.OnEncoderResolutionRequest(480, 300,
651                                      CoordinatedVideoAdapter::UPGRADE);
652   EXPECT_EQ(480, adapter.output_format().width);
653   EXPECT_EQ(300, adapter.output_format().height);
654 
655   // Server format request 640x400. Constrained by CPU.
656   format.width = 640;
657   format.height = 400;
658   adapter.OnOutputFormatRequest(format);
659   EXPECT_EQ(480, adapter.output_format().width);
660   EXPECT_EQ(300, adapter.output_format().height);
661 }
662 
TEST(CoordinatedVideoAdapterTest,TestCoordinatedWithCpuRequest)663 TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithCpuRequest) {
664   CoordinatedVideoAdapter adapter;
665   adapter.set_cpu_adaptation(true);
666   EXPECT_FALSE(adapter.cpu_smoothing());
667   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
668   adapter.SetInputFormat(format);
669 
670   // Server format request 640x400.
671   format.height = 400;
672   adapter.OnOutputFormatRequest(format);
673   EXPECT_EQ(640, adapter.output_format().width);
674   EXPECT_EQ(400, adapter.output_format().height);
675 
676   // CPU resolution request: downgrade.  Adapt down.
677   adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
678   EXPECT_EQ(480, adapter.output_format().width);
679   EXPECT_EQ(300, adapter.output_format().height);
680 
681   // CPU resolution request: keep. Do nothing.
682   adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::KEEP);
683   EXPECT_EQ(480, adapter.output_format().width);
684   EXPECT_EQ(300, adapter.output_format().height);
685 
686   // CPU resolution request: downgrade, but cpu adaptation disabled.
687   // Adapt nothing.
688   adapter.set_cpu_adaptation(false);
689   adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
690   EXPECT_EQ(480, adapter.output_format().width);
691   EXPECT_EQ(300, adapter.output_format().height);
692 
693   // CPU resolution request: downgrade.  Adapt down.
694   adapter.set_cpu_adaptation(true);
695   adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
696   EXPECT_EQ(320, adapter.output_format().width);
697   EXPECT_EQ(200, adapter.output_format().height);
698 
699   // Test reason for adapting is CPU.
700   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
701             adapter.adapt_reason());
702 
703   // CPU resolution request: downgrade, but already at minimum.  Do nothing.
704   adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
705   EXPECT_EQ(320, adapter.output_format().width);
706   EXPECT_EQ(200, adapter.output_format().height);
707 
708   // Server format request 320x200. Same as CPU. Do nothing.
709   format.width = 320;
710   format.height = 200;
711   adapter.OnOutputFormatRequest(format);
712   EXPECT_EQ(320, adapter.output_format().width);
713   EXPECT_EQ(200, adapter.output_format().height);
714 
715   // Test reason for adapting is CPU and VIEW.
716   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
717             CoordinatedVideoAdapter::ADAPTREASON_VIEW,
718             adapter.adapt_reason());
719 
720   // CPU resolution request: upgrade, but view request still low. Do nothing.
721   adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE);
722   EXPECT_EQ(320, adapter.output_format().width);
723   EXPECT_EQ(200, adapter.output_format().height);
724 
725   // Test reason for adapting is VIEW.
726   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
727             adapter.adapt_reason());
728 
729   // Server format request 640x400. Cpu is still low.  Upgrade.
730   format.width = 640;
731   format.height = 400;
732   adapter.OnOutputFormatRequest(format);
733   EXPECT_EQ(480, adapter.output_format().width);
734   EXPECT_EQ(300, adapter.output_format().height);
735 
736   // Test reason for adapting is CPU.
737   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
738             adapter.adapt_reason());
739 
740   // Encoder resolution request: downgrade.
741   adapter.OnEncoderResolutionRequest(480, 300,
742                                      CoordinatedVideoAdapter::DOWNGRADE);
743   EXPECT_EQ(320, adapter.output_format().width);
744   EXPECT_EQ(200, adapter.output_format().height);
745 
746   // Test reason for adapting is BANDWIDTH.
747   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
748             adapter.adapt_reason());
749 
750   // Process load and system load are low. Constrained by GD. Adapt nothing
751   adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
752   EXPECT_EQ(320, adapter.output_format().width);
753   EXPECT_EQ(200, adapter.output_format().height);
754 
755   // Encoder resolution request: upgrade.
756   adapter.OnEncoderResolutionRequest(320, 200,
757                                      CoordinatedVideoAdapter::UPGRADE);
758   EXPECT_EQ(480, adapter.output_format().width);
759   EXPECT_EQ(300, adapter.output_format().height);
760 
761   // Encoder resolution request: upgrade. Constrained by CPU.
762   adapter.OnEncoderResolutionRequest(480, 300,
763                                      CoordinatedVideoAdapter::UPGRADE);
764   EXPECT_EQ(480, adapter.output_format().width);
765   EXPECT_EQ(300, adapter.output_format().height);
766 
767   // Server format request 640x400. Constrained by CPU.
768   format.width = 640;
769   format.height = 400;
770   adapter.OnOutputFormatRequest(format);
771   EXPECT_EQ(480, adapter.output_format().width);
772   EXPECT_EQ(300, adapter.output_format().height);
773 }
774 
TEST(CoordinatedVideoAdapterTest,TestViewRequestPlusCameraSwitch)775 TEST(CoordinatedVideoAdapterTest, TestViewRequestPlusCameraSwitch) {
776   CoordinatedVideoAdapter adapter;
777   adapter.set_view_switch(true);
778 
779   // Start at HD.
780   VideoFormat format(1280, 720, VideoFormat::FpsToInterval(30), FOURCC_I420);
781   adapter.SetInputFormat(format);
782   EXPECT_EQ(format, adapter.input_format());
783   EXPECT_TRUE(adapter.output_format().IsSize0x0());
784 
785   // View request for VGA.
786   format.width = 640;
787   format.height = 360;
788   adapter.OnOutputFormatRequest(format);
789   EXPECT_EQ(640, adapter.output_format().width);
790   EXPECT_EQ(360, adapter.output_format().height);
791   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW, adapter.adapt_reason());
792 
793   // Now, the camera reopens at VGA.
794   // Both the frame and the output format should be 640x360.
795   const VideoFormat out_format = adapter.AdaptFrameResolution(640, 360);
796   EXPECT_EQ(640, out_format.width);
797   EXPECT_EQ(360, out_format.height);
798   // At this point, the view is no longer adapted, since the input has resized
799   // small enough to fit the last view request.
800   EXPECT_EQ(0, adapter.adapt_reason());
801 
802   // And another view request comes in for 640x360, which should have no
803   // real impact.
804   adapter.OnOutputFormatRequest(format);
805   EXPECT_EQ(640, adapter.output_format().width);
806   EXPECT_EQ(360, adapter.output_format().height);
807   EXPECT_EQ(0, adapter.adapt_reason());
808 }
809 
TEST(CoordinatedVideoAdapterTest,TestVGAWidth)810 TEST(CoordinatedVideoAdapterTest, TestVGAWidth) {
811   CoordinatedVideoAdapter adapter;
812   adapter.set_view_switch(true);
813 
814   // Start at 640x480, for cameras that don't support 640x360.
815   VideoFormat format(640, 480, VideoFormat::FpsToInterval(30), FOURCC_I420);
816   adapter.SetInputFormat(format);
817   EXPECT_EQ(format, adapter.input_format());
818   EXPECT_TRUE(adapter.output_format().IsSize0x0());
819 
820   // Output format is 640x360, though.
821   format.width = 640;
822   format.height = 360;
823   adapter.SetOutputFormat(format);
824 
825   // And also a view request comes for 640x360.
826   adapter.OnOutputFormatRequest(format);
827   // At this point, we have to adapt down to something lower.
828   EXPECT_EQ(480, adapter.output_format().width);
829   EXPECT_EQ(360, adapter.output_format().height);
830 
831   // But if frames come in at 640x360, we shouldn't adapt them down.
832   // Fake a 640x360 frame.
833   VideoFormat out_format = adapter.AdaptFrameResolution(640, 360);
834   EXPECT_EQ(640, out_format.width);
835   EXPECT_EQ(360, out_format.height);
836 
837   // Similarly, no-op adapt requests for other reasons shouldn't change
838   // adaptation state (before a previous bug, the previous EXPECTs would
839   // fail and the following would succeed, as the no-op CPU request would
840   // fix the adaptation state).
841   adapter.set_cpu_adaptation(true);
842   UpdateCpuLoad(&adapter, 1, 1, 0.7f, 0.7f);
843   out_format = adapter.AdaptFrameResolution(640, 360);
844 
845   EXPECT_EQ(640, out_format.width);
846   EXPECT_EQ(360, out_format.height);
847 }
848 
849 // When adapting resolution for CPU or GD, the quantity of pixels that the
850 // request is based on is reduced to half or double, and then an actual
851 // resolution is snapped to, rounding to the closest actual resolution.
852 // This works well for some tolerance to 3/4, odd widths and aspect ratios
853 // that dont exactly match, but is not best behavior for ViewRequests which
854 // need to be be strictly respected to avoid going over the resolution budget
855 // given to the codec - 854x480 total pixels.
856 // ViewRequest must find a lower resolution.
TEST(CoordinatedVideoAdapterTest,TestCoordinatedViewRequestDown)857 TEST(CoordinatedVideoAdapterTest, TestCoordinatedViewRequestDown) {
858   CoordinatedVideoAdapter adapter;
859   adapter.set_cpu_adaptation(false);
860 
861   VideoFormat format(960, 540, VideoFormat::FpsToInterval(30), FOURCC_I420);
862   adapter.SetInputFormat(format);
863   adapter.set_scale_third(true);
864   EXPECT_EQ(format, adapter.input_format());
865   EXPECT_TRUE(adapter.output_format().IsSize0x0());
866 
867   // Server format request 640x400. Expect HVGA.
868   format.width = 640;
869   format.height = 400;
870   adapter.OnOutputFormatRequest(format);
871   EXPECT_EQ(640, adapter.output_format().width);
872   EXPECT_EQ(360, adapter.output_format().height);
873 
874   // Test reason for adapting is VIEW.
875   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW, adapter.adapt_reason());
876 }
877 
878 // Test that we downgrade video for cpu up to two times.
TEST(CoordinatedVideoAdapterTest,TestCpuDowngradeTimes)879 TEST(CoordinatedVideoAdapterTest, TestCpuDowngradeTimes) {
880   CoordinatedVideoAdapter adapter;
881   adapter.set_cpu_adaptation(true);
882   EXPECT_FALSE(adapter.cpu_smoothing());
883   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
884   adapter.SetInputFormat(format);
885 
886   // Server format request 640x400.
887   format.height = 400;
888   adapter.OnOutputFormatRequest(format);
889   EXPECT_EQ(640, adapter.output_format().width);
890   EXPECT_EQ(400, adapter.output_format().height);
891 
892   // Process load and system load are low. Do not change the cpu desired format
893   // and do not adapt.
894   adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
895   EXPECT_EQ(640, adapter.output_format().width);
896   EXPECT_EQ(400, adapter.output_format().height);
897 
898   // System load is high. Downgrade.
899   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
900   EXPECT_EQ(480, adapter.output_format().width);
901   EXPECT_EQ(300, adapter.output_format().height);
902 
903   // System load is high. Downgrade again.
904   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
905   EXPECT_EQ(320, adapter.output_format().width);
906   EXPECT_EQ(200, adapter.output_format().height);
907 
908   // System load is still high. Do not downgrade any more.
909   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
910   EXPECT_EQ(320, adapter.output_format().width);
911   EXPECT_EQ(200, adapter.output_format().height);
912 
913   // Process load and system load are low. Upgrade.
914   UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
915   EXPECT_EQ(480, adapter.output_format().width);
916   EXPECT_EQ(300, adapter.output_format().height);
917 
918   // System load is high. Downgrade.
919   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
920   EXPECT_EQ(320, adapter.output_format().width);
921   EXPECT_EQ(200, adapter.output_format().height);
922 
923   // System load is still high. Do not downgrade any more.
924   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
925   EXPECT_EQ(320, adapter.output_format().width);
926   EXPECT_EQ(200, adapter.output_format().height);
927 }
928 
929 // Test that we respect CPU adapter threshold values.
TEST(CoordinatedVideoAdapterTest,TestAdapterCpuThreshold)930 TEST(CoordinatedVideoAdapterTest, TestAdapterCpuThreshold) {
931   CoordinatedVideoAdapter adapter;
932   adapter.set_cpu_adaptation(true);
933   EXPECT_FALSE(adapter.cpu_smoothing());
934   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
935   adapter.SetInputFormat(format);
936 
937   // Server format request 640x400.
938   format.height = 400;
939   adapter.OnOutputFormatRequest(format);
940   EXPECT_EQ(640, adapter.output_format().width);
941   EXPECT_EQ(400, adapter.output_format().height);
942 
943   // Process load and system load are low. Do not change the cpu desired format
944   // and do not adapt.
945   adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
946   EXPECT_EQ(640, adapter.output_format().width);
947   EXPECT_EQ(400, adapter.output_format().height);
948 
949   // System load is high. Downgrade.
950   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
951   EXPECT_EQ(480, adapter.output_format().width);
952   EXPECT_EQ(300, adapter.output_format().height);
953 
954   // Test reason for adapting is CPU.
955   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, adapter.adapt_reason());
956 
957   // System load is high. Normally downgrade but threshold is high. Do nothing.
958   adapter.set_high_system_threshold(0.98f);  // Set threshold high.
959   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
960   EXPECT_EQ(480, adapter.output_format().width);
961   EXPECT_EQ(300, adapter.output_format().height);
962 
963   // System load is medium. Normally do nothing, threshold is low. Adapt down.
964   adapter.set_high_system_threshold(0.75f);  // Set threshold low.
965   UpdateCpuLoad(&adapter, 1, 1, 0.8f, 0.8f);
966   EXPECT_EQ(320, adapter.output_format().width);
967   EXPECT_EQ(200, adapter.output_format().height);
968 }
969 
970 
971 // Test that for an upgrade cpu request, we actually upgrade the desired format;
972 // for a downgrade request, we downgrade from the output format.
TEST(CoordinatedVideoAdapterTest,TestRealCpuUpgrade)973 TEST(CoordinatedVideoAdapterTest, TestRealCpuUpgrade) {
974   CoordinatedVideoAdapter adapter;
975   adapter.set_cpu_adaptation(true);
976   adapter.set_cpu_smoothing(true);
977   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
978   adapter.SetInputFormat(format);
979 
980   // Server format request 640x400.
981   format.width = 640;
982   format.height = 400;
983   adapter.OnOutputFormatRequest(format);
984   EXPECT_EQ(640, adapter.output_format().width);
985   EXPECT_EQ(400, adapter.output_format().height);
986 
987   // Process load and system load are low. Do not change the cpu desired format
988   // and do not adapt.
989   UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
990   EXPECT_EQ(640, adapter.output_format().width);
991   EXPECT_EQ(400, adapter.output_format().height);
992 
993   // Server format request 320x200.
994   format.width = 320;
995   format.height = 200;
996   adapter.OnOutputFormatRequest(format);
997   EXPECT_EQ(320, adapter.output_format().width);
998   EXPECT_EQ(200, adapter.output_format().height);
999 
1000   // Process load and system load are low. Do not change the cpu desired format
1001   // and do not adapt.
1002   UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
1003   EXPECT_EQ(320, adapter.output_format().width);
1004   EXPECT_EQ(200, adapter.output_format().height);
1005 
1006   // Server format request 640x400. Set to 640x400 immediately.
1007   format.width = 640;
1008   format.height = 400;
1009   adapter.OnOutputFormatRequest(format);
1010   EXPECT_EQ(640, adapter.output_format().width);
1011   EXPECT_EQ(400, adapter.output_format().height);
1012 
1013   // Server format request 320x200.
1014   format.width = 320;
1015   format.height = 200;
1016   adapter.OnOutputFormatRequest(format);
1017   EXPECT_EQ(320, adapter.output_format().width);
1018   EXPECT_EQ(200, adapter.output_format().height);
1019 
1020   // Process load is high, but system is not. Do not change the cpu desired
1021   // format and do not adapt.
1022   for (size_t i = 0; i < 10; ++i) {
1023     UpdateCpuLoad(&adapter, 1, 1, 0.75f, 0.8f);
1024   }
1025   EXPECT_EQ(320, adapter.output_format().width);
1026   EXPECT_EQ(200, adapter.output_format().height);
1027 }
1028 
1029 // Test that for an upgrade encoder request, we actually upgrade the desired
1030 //  format; for a downgrade request, we downgrade from the output format.
TEST(CoordinatedVideoAdapterTest,TestRealEncoderUpgrade)1031 TEST(CoordinatedVideoAdapterTest, TestRealEncoderUpgrade) {
1032   CoordinatedVideoAdapter adapter;
1033   adapter.set_cpu_adaptation(true);
1034   adapter.set_cpu_smoothing(true);
1035   VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
1036   adapter.SetInputFormat(format);
1037 
1038   // Server format request 640x400.
1039   format.width = 640;
1040   format.height = 400;
1041   adapter.OnOutputFormatRequest(format);
1042   EXPECT_EQ(640, adapter.output_format().width);
1043   EXPECT_EQ(400, adapter.output_format().height);
1044 
1045   // Encoder resolution request. Do not change the encoder desired format and
1046   // do not adapt.
1047   adapter.OnEncoderResolutionRequest(640, 400,
1048                                      CoordinatedVideoAdapter::UPGRADE);
1049   EXPECT_EQ(640, adapter.output_format().width);
1050   EXPECT_EQ(400, adapter.output_format().height);
1051 
1052   // Server format request 320x200.
1053   format.width = 320;
1054   format.height = 200;
1055   adapter.OnOutputFormatRequest(format);
1056   EXPECT_EQ(320, adapter.output_format().width);
1057   EXPECT_EQ(200, adapter.output_format().height);
1058 
1059   // Encoder resolution request. Do not change the encoder desired format and
1060   // do not adapt.
1061   adapter.OnEncoderResolutionRequest(320, 200,
1062                                      CoordinatedVideoAdapter::UPGRADE);
1063   EXPECT_EQ(320, adapter.output_format().width);
1064   EXPECT_EQ(200, adapter.output_format().height);
1065 
1066   // Server format request 640x400. Set to 640x400 immediately.
1067   format.width = 640;
1068   format.height = 400;
1069   adapter.OnOutputFormatRequest(format);
1070   EXPECT_EQ(480, adapter.output_format().width);
1071   EXPECT_EQ(300, adapter.output_format().height);
1072 
1073   // Test reason for adapting is BANDWIDTH.
1074   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
1075             adapter.adapt_reason());
1076 
1077   // Server format request 320x200.
1078   format.width = 320;
1079   format.height = 200;
1080   adapter.OnOutputFormatRequest(format);
1081   EXPECT_EQ(320, adapter.output_format().width);
1082   EXPECT_EQ(200, adapter.output_format().height);
1083 
1084   // Encoder resolution request. Downgrade from 320x200.
1085   adapter.OnEncoderResolutionRequest(320, 200,
1086                                      CoordinatedVideoAdapter::DOWNGRADE);
1087   EXPECT_EQ(240, adapter.output_format().width);
1088   EXPECT_EQ(150, adapter.output_format().height);
1089 }
1090 
TEST(CoordinatedVideoAdapterTest,TestNormalizeOutputFormat)1091 TEST(CoordinatedVideoAdapterTest, TestNormalizeOutputFormat) {
1092   CoordinatedVideoAdapter adapter;
1093   // The input format is 640x360 and the output is limited to 16:9.
1094   VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1095   adapter.SetInputFormat(format);
1096 
1097   format.width = 320;
1098   format.height = 180;
1099   format.interval = VideoFormat::FpsToInterval(15);
1100   adapter.OnOutputFormatRequest(format);
1101   EXPECT_EQ(320, adapter.output_format().width);
1102   EXPECT_EQ(180, adapter.output_format().height);
1103   EXPECT_EQ(VideoFormat::FpsToInterval(15), adapter.output_format().interval);
1104 
1105   format.width = 320;
1106   format.height = 200;
1107   format.interval = VideoFormat::FpsToInterval(40);
1108   adapter.OnOutputFormatRequest(format);
1109   EXPECT_EQ(320, adapter.output_format().width);
1110   EXPECT_EQ(180, adapter.output_format().height);
1111   EXPECT_EQ(VideoFormat::FpsToInterval(30), adapter.output_format().interval);
1112 
1113   // Test reason for adapting is VIEW. Should work even with normalization.
1114   EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
1115             adapter.adapt_reason());
1116 
1117   format.width = 320;
1118   format.height = 240;
1119   adapter.OnOutputFormatRequest(format);
1120   EXPECT_EQ(320, adapter.output_format().width);
1121   EXPECT_EQ(180, adapter.output_format().height);
1122 
1123   // The input format is 640x480 and the output will be 4:3.
1124   format.width = 640;
1125   format.height = 480;
1126   adapter.SetInputFormat(format);
1127   EXPECT_EQ(320, adapter.output_format().width);
1128   EXPECT_EQ(240, adapter.output_format().height);
1129 
1130   format.width = 320;
1131   format.height = 240;
1132   adapter.OnOutputFormatRequest(format);
1133   EXPECT_EQ(320, adapter.output_format().width);
1134   EXPECT_EQ(240, adapter.output_format().height);
1135 
1136   // The input format is initialized after the output. At that time, the output
1137   // height is adjusted.
1138   format.width = 0;
1139   format.height = 0;
1140   adapter.SetInputFormat(format);
1141 
1142   format.width = 320;
1143   format.height = 240;
1144   format.interval = VideoFormat::FpsToInterval(30);
1145   adapter.OnOutputFormatRequest(format);
1146   EXPECT_EQ(320, adapter.output_format().width);
1147   EXPECT_EQ(240, adapter.output_format().height);
1148   EXPECT_EQ(VideoFormat::FpsToInterval(30), adapter.output_format().interval);
1149 
1150   format.width = 640;
1151   format.height = 480;
1152   format.interval = VideoFormat::FpsToInterval(15);
1153   adapter.SetInputFormat(format);
1154   EXPECT_EQ(320, adapter.output_format().width);
1155   EXPECT_EQ(240, adapter.output_format().height);
1156   EXPECT_EQ(VideoFormat::FpsToInterval(15), adapter.output_format().interval);
1157 }
1158 
1159 // Test that we downgrade video for cpu up to two times.
TEST_F(VideoAdapterTest,CpuDowngradeAndSignal)1160 TEST_F(VideoAdapterTest, CpuDowngradeAndSignal) {
1161   CoordinatedVideoAdapter adapter;
1162   CpuAdapterListener cpu_listener;
1163   adapter.SignalCpuAdaptationUnable.connect(
1164       &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1165 
1166   adapter.set_cpu_adaptation(true);
1167   EXPECT_FALSE(adapter.cpu_smoothing());
1168   VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1169   adapter.SetInputFormat(format);
1170   adapter.OnOutputFormatRequest(format);
1171 
1172   // System load is high. Downgrade.
1173   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1174 
1175   // System load is high. Downgrade again.
1176   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1177 
1178   // System load is still high. Do not downgrade any more. Ensure we have not
1179   // signalled until after the cpu warning though.
1180   EXPECT_TRUE(!cpu_listener.received_cpu_signal());
1181   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1182   EXPECT_TRUE_WAIT(cpu_listener.received_cpu_signal(), kWaitTimeout);
1183 }
1184 
1185 // Test that we downgrade video for cpu up to two times.
TEST_F(VideoAdapterTest,CpuDowngradeAndDontSignal)1186 TEST_F(VideoAdapterTest, CpuDowngradeAndDontSignal) {
1187   CoordinatedVideoAdapter adapter;
1188   CpuAdapterListener cpu_listener;
1189   adapter.SignalCpuAdaptationUnable.connect(
1190       &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1191 
1192   adapter.set_cpu_adaptation(true);
1193   adapter.set_cpu_smoothing(true);
1194   VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1195   adapter.SetInputFormat(format);
1196   adapter.OnOutputFormatRequest(format);
1197 
1198   // System load is high. Downgrade.
1199   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1200 
1201   // System load is high, process is not, Do not downgrade again.
1202   UpdateCpuLoad(&adapter, 1, 1, 0.25f, 0.95f);
1203 
1204   // System load is high, process is not, Do not downgrade again and do not
1205   // signal.
1206   adapter.set_cpu_adaptation(false);
1207   UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1208   rtc::Thread::Current()->ProcessMessages(kShortWaitTimeout);
1209   EXPECT_TRUE(!cpu_listener.received_cpu_signal());
1210   adapter.set_cpu_adaptation(true);
1211 }
1212 
1213 // Test that we require enough time before we downgrade.
TEST_F(VideoAdapterTest,CpuMinTimeRequirement)1214 TEST_F(VideoAdapterTest, CpuMinTimeRequirement) {
1215   CoordinatedVideoAdapter adapter;
1216   CpuAdapterListener cpu_listener;
1217   adapter.SignalCpuAdaptationUnable.connect(
1218       &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1219 
1220   adapter.set_cpu_adaptation(true);
1221   adapter.set_cpu_smoothing(true);
1222   VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1223   adapter.SetInputFormat(format);
1224   adapter.OnOutputFormatRequest(format);
1225 
1226   EXPECT_EQ(3, adapter.cpu_load_min_samples());
1227   adapter.set_cpu_load_min_samples(5);
1228 
1229   for (size_t i = 0; i < 4; ++i) {
1230     adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1231     EXPECT_EQ(640, adapter.output_format().width);
1232     EXPECT_EQ(360, adapter.output_format().height);
1233   }
1234   // The computed cpu load should now be around 93.5%, with the coefficient of
1235   // 0.4 and a seed value of 0.5. That should be high enough to adapt, but it
1236   // isn't enough samples, so we shouldn't have adapted on any of the previous
1237   // samples.
1238 
1239   // One more sample is enough, though, once enough time has passed.
1240   adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1241   EXPECT_EQ(480, adapter.output_format().width);
1242   EXPECT_EQ(270, adapter.output_format().height);
1243 
1244   // Now the cpu is lower, but we still need enough samples to upgrade.
1245   for (size_t i = 0; i < 4; ++i) {
1246     adapter.OnCpuLoadUpdated(1, 1, 0.1f, 0.1f);
1247     EXPECT_EQ(480, adapter.output_format().width);
1248     EXPECT_EQ(270, adapter.output_format().height);
1249   }
1250 
1251   // One more sample is enough, once time has elapsed.
1252   adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1253   EXPECT_EQ(640, adapter.output_format().width);
1254   EXPECT_EQ(360, adapter.output_format().height);
1255 }
1256 
TEST_F(VideoAdapterTest,CpuIgnoresSpikes)1257 TEST_F(VideoAdapterTest, CpuIgnoresSpikes) {
1258   CoordinatedVideoAdapter adapter;
1259   CpuAdapterListener cpu_listener;
1260   adapter.SignalCpuAdaptationUnable.connect(
1261       &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1262 
1263   adapter.set_cpu_adaptation(true);
1264   adapter.set_cpu_smoothing(true);
1265   VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1266   adapter.SetInputFormat(format);
1267   adapter.OnOutputFormatRequest(format);
1268 
1269   // System load is high. Downgrade.
1270   for (size_t i = 0; i < 5; ++i) {
1271     UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1272   }
1273   EXPECT_EQ(480, adapter.output_format().width);
1274   EXPECT_EQ(270, adapter.output_format().height);
1275 
1276   // Now we're in a state where we could upgrade or downgrade, so get to a
1277   // steady state of about 75% cpu usage.
1278   for (size_t i = 0; i < 5; ++i) {
1279     UpdateCpuLoad(&adapter, 1, 1, 0.75f, 0.75f);
1280     EXPECT_EQ(480, adapter.output_format().width);
1281     EXPECT_EQ(270, adapter.output_format().height);
1282   }
1283 
1284   // Now, the cpu spikes for two samples, but then goes back to
1285   // normal. This shouldn't cause adaptation.
1286   UpdateCpuLoad(&adapter, 1, 1, 0.90f, 0.90f);
1287   UpdateCpuLoad(&adapter, 1, 1, 0.90f, 0.90f);
1288   EXPECT_EQ(480, adapter.output_format().width);
1289   EXPECT_EQ(270, adapter.output_format().height);
1290   // Back to the steady state for awhile.
1291   for (size_t i = 0; i < 5; ++i) {
1292     UpdateCpuLoad(&adapter, 1, 1, 0.75, 0.75);
1293     EXPECT_EQ(480, adapter.output_format().width);
1294     EXPECT_EQ(270, adapter.output_format().height);
1295   }
1296 
1297   // Now, system cpu usage is starting to drop down. But it takes a bit before
1298   // it gets all the way there.
1299   for (size_t i = 0; i < 10; ++i) {
1300     UpdateCpuLoad(&adapter, 1, 1, 0.5f, 0.5f);
1301   }
1302   EXPECT_EQ(640, adapter.output_format().width);
1303   EXPECT_EQ(360, adapter.output_format().height);
1304 }
1305 
1306 }  // namespace cricket
1307 #endif  // HAVE_WEBRTC_VIDEO
1308