1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This file includes unit tests the QmResolution class
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * In particular, for the selection of spatial and/or temporal down-sampling.
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
18a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/interface/module_common_types.h"
19a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/qm_select.h"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Representative values of content metrics for: low/high/medium(default) state,
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// based on parameters settings in qm_select_data.h.
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst float kSpatialLow = 0.01f;
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst float kSpatialMedium = 0.03f;
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst float kSpatialHigh = 0.1f;
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst float kTemporalLow = 0.01f;
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst float kTemporalMedium = 0.06f;
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst float kTemporalHigh = 0.1f;
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass QmSelectTest : public ::testing::Test {
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org protected:
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  QmSelectTest()
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      :  qm_resolution_(new VCMQmResolution()),
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         content_metrics_(new VideoContentMetrics()),
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         qm_scale_(NULL) {
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VCMQmResolution* qm_resolution_;
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VideoContentMetrics* content_metrics_;
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VCMResolutionScale* qm_scale_;
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void InitQmNativeData(float initial_bit_rate,
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int user_frame_rate,
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int native_width,
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int native_height,
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int num_layers);
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void UpdateQmEncodedFrame(int* encoded_size, int num_updates);
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void UpdateQmRateData(int* target_rate,
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int* encoder_sent_rate,
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int* incoming_frame_rate,
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        uint8_t* fraction_lost,
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int num_updates);
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void UpdateQmContentData(float motion_metric,
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           float spatial_metric,
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           float spatial_metric_horiz,
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           float spatial_metric_vert);
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bool IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               float fac_width,
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               float fac_height,
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               float fac_temp,
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               uint16_t new_width,
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               uint16_t new_height,
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               float new_frame_rate);
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void TearDown() {
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete qm_resolution_;
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete content_metrics_;
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, HandleInputs) {
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Expect parameter error. Initialize with invalid inputs.
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 0, 640, 480, 1));
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 640, 0, 1));
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 0, 480, 1));
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Expect uninitialized error.: No valid initialization before selection.
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(-7, qm_resolution_->SelectResolution(&qm_scale_));
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VideoContentMetrics* content_metrics = NULL;
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->Initialize(1000, 30, 640, 480, 1));
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateContent(content_metrics);
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Content metrics are NULL: Expect success and no down-sampling action.
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0, 1.0, 1.0, 640, 480,
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(marpan): Add a test for number of temporal layers > 1.
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// No down-sampling action at high rates.
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, NoActionHighRate) {
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(800, 30, 640, 480, 1);
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {800, 800, 800};
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {800, 800, 800};
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Rate is well below transition, down-sampling action is taken,
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// depending on the content state.
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, DownActionLowRate) {
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial: 2x2 spatial expected.
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, low spatial: 2/3 temporal is expected.
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, low spatial: 2x2 spatial expected.
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, high spatial: 2/3 temporal expected.
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialHigh, kSpatialHigh, kSpatialHigh);
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->ComputeContentClass());
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial: 1/2 temporal expected.
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      15.5f));
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, high spatial: 1/2 temporal expected.
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialHigh);
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      15.5f));
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, medium spatial: 2x2 spatial expected.
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialMedium);
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Target frame rate for frame dropper should be the same as previous == 15.
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, medium spatial: high frame rate, so 1/2 temporal expected.
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialMedium);
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      15.5f));
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, medium spatial: high frame rate, so 2/3 temporal expected.
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialMedium, kSpatialMedium,
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialMedium);
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(8, qm_resolution_->ComputeContentClass());
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Rate mis-match is high, and we have over-shooting.
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// since target rate is below max for down-sampling, down-sampling is selected.
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, DownActionHighRateMMOvershoot) {
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(300, 30, 640, 480, 1);
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {300, 300, 300};
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {900, 900, 900};
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 480, 360, 30.0f));
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Rate mis-match is high, target rate is below max for down-sampling,
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// but since we have consistent under-shooting, no down-sampling action.
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, NoActionHighRateMMUndershoot) {
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(300, 30, 640, 480, 1);
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {300, 300, 300};
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {100, 100, 100};
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Buffer is underflowing, and target rate is below max for down-sampling,
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// so action is taken.
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, DownActionBufferUnderflow) {
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(300, 30, 640, 480, 1);
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoded size over a number of frames.
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // per-frame bandwidth = 15 = 450/30: simulate (decoder) buffer underflow:
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoded_size[] = {200, 100, 50, 30, 60, 40, 20, 30, 20, 40};
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmEncodedFrame(encoded_size, 10);
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {300, 300, 300};
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {450, 450, 450};
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 480, 360, 30.0f));
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Target rate is below max for down-sampling, but buffer level is stable,
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// so no action is taken.
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, NoActionBufferStable) {
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(350, 30, 640, 480, 1);
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoded size over a number of frames.
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // per-frame bandwidth = 15 = 450/30: simulate stable (decoder) buffer levels.
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int32_t encoded_size[] = {40, 10, 10, 16, 18, 20, 17, 20, 16, 15};
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmEncodedFrame(encoded_size, 10);
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {350, 350, 350};
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {350, 450, 450};
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetDownSamplingState();
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Very low rate, but no spatial down-sampling below some size (QCIF).
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, LimitDownSpatialAction) {
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(10, 30, 176, 144, 1);
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 176;
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 144;
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->GetImageType(codec_width, codec_height));
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {10, 10, 10};
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {10, 10, 10};
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 176, 144,
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Very low rate, but no frame reduction below some frame_rate (8fps).
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, LimitDownTemporalAction) {
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(10, 8, 640, 480, 1);
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(8.0f, codec_width, codec_height);
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {10, 10, 10};
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {10, 10, 10};
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {8, 8, 8};
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, medium spatial.
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialMedium);
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      8.0f));
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages: spatial down-sample and then back up spatially,
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// as rate as increased.
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 2StageDownSpatialUpSpatial) {
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    fraction_lost, 3);
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset and go up in rate: expected to go back up, in 2 stages of 3/4.
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {400, 400, 400, 400, 400};
488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {400, 400, 400, 400, 400};
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float scale = (4.0f / 3.0f) / 2.0f;
496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360,
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      640, 480, 30.0f));
504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages: spatial down-sample and then back up spatially, since encoder
507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// is under-shooting target even though rate has not increased much.
508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 2StageDownSpatialUpSpatialUndershoot) {
509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    fraction_lost, 3);
526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset rates and simulate under-shooting scenario.: expect to go back up.
537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Goes up spatially in two stages for 1/2x1/2 down-sampling.
538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {200, 200, 200, 200, 200};
543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {50, 50, 50, 50, 50};
544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float scale = (4.0f / 3.0f) / 2.0f;
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360,
552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      640, 480, 30.0f));
559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages: spatial down-sample and then no action to go up,
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// as encoding rate mis-match is too high.
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 2StageDownSpatialNoActionUp) {
564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    fraction_lost, 3);
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset and simulate large rate mis-match: expect no action to go back up.
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {400, 400, 400, 400, 400};
597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000};
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 320, 240,
605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages: temporally down-sample and then back up temporally,
609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// as rate as increased.
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporal) {
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      15.5f));
637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset rates and go up in rate: expect to go back up.
639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {400, 400, 400, 400, 400};
642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {400, 400, 400, 400, 400};
643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480,
650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages: temporal down-sample and then back up temporally, since encoder
654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// is under-shooting target even though rate has not increased much.
655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporalUndershoot) {
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    fraction_lost, 3);
673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      15.5f));
682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset rates and simulate under-shooting scenario.: expect to go back up.
684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {150, 150, 150, 150, 150};
687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {50, 50, 50, 50, 50};
688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480,
695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages: temporal down-sample and then no action to go up,
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// as encoding rate mis-match is too high.
700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 2StageDownTemporalNoActionUp) {
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(50, 30, 640, 480, 1);
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {50, 50, 50};
713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {50, 50, 50};
714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1, 1, 2, 640, 480, 15.5f));
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset and simulate large rate mis-match: expect no action to go back up.
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(15.0f, codec_width, codec_height);
729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {600, 600, 600, 600, 600};
732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000};
733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      15.0f));
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 3 stages: spatial down-sample, followed by temporal down-sample,
743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// and then go up to full state, as encoding rate has increased.
744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, 3StageDownSpatialTemporlaUpSpatialTemporal) {
745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(80, 30, 640, 480, 1);
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {80, 80, 80};
757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {80, 80, 80};
758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Change content data: expect temporal down-sample.
773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset rates and go lower in rate.
777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {40, 40, 40, 40, 40};
779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    fraction_lost2, 5);
784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240,
792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset rates and go high up in rate: expect to go back up both spatial
795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // and temporally. The 1/2x1/2 spatial is undone in two stages.
796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate3[] = {1000, 1000, 1000, 1000, 1000};
799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate3[] = {1000, 1000, 1000, 1000, 1000};
800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost3, 5);
804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float scale = (4.0f / 3.0f) / 2.0f;
809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f,
810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      480, 360, 30.0f));
811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      640, 480, 30.0f));
817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// No down-sampling below some total amount.
820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, NoActionTooMuchDownSampling) {
821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(150, 30, 1280, 720, 1);
824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 1280;
827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 720;
828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(7, qm_resolution_->GetImageType(codec_width, codec_height));
830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {150, 150, 150};
833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {150, 150, 150};
834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 640, 360,
846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org              30.0f));
847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset and lower rates to get another spatial action (3/4x3/4).
849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Lower the frame rate for spatial to be selected again.
850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(10.0f, 640, 360);
852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(640, 360));
853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {70, 70, 70, 70, 70};
855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {70, 70, 70, 70, 70};
856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {10, 10, 10, 10, 10};
857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, medium spatial.
863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialMedium);
865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 480, 270, 10.0f));
870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset and go to very low rate: no action should be taken,
872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // we went down too much already.
873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(10.0f, 480, 270);
875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->GetImageType(480, 270));
876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate3[] = {10, 10, 10, 10, 10};
878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate3[] = {10, 10, 10, 10, 10};
879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate3[] = {10, 10, 10, 10, 10};
880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost3, 5);
883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 480, 270,
887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      10.0f));
888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Multiple down-sampling stages and then undo all of them.
891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// followed by spatial 3/4x3/4. Then go up to full state,
893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// as encoding rate has increased.
894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, MultipleStagesCheckActionHistory1) {
895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(150, 30, 640, 480, 1);
898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down spatial 3/4x3/4.
906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {150, 150, 150};
908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {150, 150, 150};
909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, low spatial.
916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 480, 360, 30.0f));
922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 2/3 temporal.
923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {100, 100, 100, 100, 100};
927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360,
940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 3/4x3/4 spatial:
943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(20.0f, 480, 360);
944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate3[] = {80, 80, 80, 80, 80};
946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate3[] = {80, 80, 80, 80, 80};
947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    fraction_lost3, 5);
951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // High motion, low spatial.
954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // The two spatial actions of 3/4x3/4 are converted to 1/2x1/2,
959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // so scale factor is 2.0.
960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.0f));
962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Reset rates and go high up in rate: expect to go up:
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // 1/2x1x2 spatial and 1/2 temporally.
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go up 1/2x1/2 spatially and 1/2 temporally. Spatial is done in 2 stages.
967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(15.0f, 320, 240);
968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate4[] = {1000, 1000, 1000, 1000, 1000};
972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate4[] = {1000, 1000, 1000, 1000, 1000};
973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate4[] = {15, 15, 15, 15, 15};
974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost4[] = {10, 10, 10, 10, 10};
975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost4, 5);
977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float scale = (4.0f / 3.0f) / 2.0f;
982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      360, 30.0f));
984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      640, 480, 30.0f));
990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Multiple down-sampling and up-sample stages, with partial undoing.
993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Spatial down-sample 1/2x1/2, followed by temporal down-sample 2/3, undo the
994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// temporal, then another temporal, and then undo both spatial and temporal.
995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, MultipleStagesCheckActionHistory2) {
996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(80, 30, 640, 480, 1);
999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 1/2x1/2 spatial.
1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {80, 80, 80};
1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {80, 80, 80};
1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
1011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, low spatial.
1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 2/3 temporal.
1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {40, 40, 40, 40, 40};
1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, high spatial.
1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      kSpatialHigh);
1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240,
1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go up 2/3 temporally.
1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(20.0f, 320, 240);
1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate3[] = {150, 150, 150, 150, 150};
1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate3[] = {150, 150, 150, 150, 150};
1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost3, 5);
1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 320,
1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      240, 30.0f));
1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 2/3 temporal.
1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate4[] = {40, 40, 40, 40, 40};
1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate4[] = {40, 40, 40, 40, 40};
1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost4[] = {10, 10, 10, 10, 10};
1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost4, 5);
1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240,
1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go up spatial and temporal. Spatial undoing is done in 2 stages.
1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(20.5f, 320, 240);
1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate5[] = {1000, 1000, 1000, 1000, 1000};
1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate5[] = {1000, 1000, 1000, 1000, 1000};
1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate5[] = {20, 20, 20, 20, 20};
1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost5[] = {10, 10, 10, 10, 10};
1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate5, encoder_sent_rate5, incoming_frame_rate5,
1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost5, 5);
1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float scale = (4.0f / 3.0f) / 2.0f;
1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f,
1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      480, 360, 30.0f));
1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      640, 480, 30.0f));
1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Multiple down-sampling and up-sample stages, with partial undoing.
1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// undo the temporal 2/3, and then undo the spatial.
1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, MultipleStagesCheckActionHistory3) {
1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(100, 30, 640, 480, 1);
1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 3/4x3/4 spatial.
1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {100, 100, 100};
1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {100, 100, 100};
1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, low spatial.
1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 480, 360, 30.0f));
1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 2/3 temporal.
1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {100, 100, 100, 100, 100};
1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Low motion, high spatial.
1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360,
1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      20.5f));
1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go up 2/3 temporal.
1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(20.5f, 480, 360);
1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate3[] = {250, 250, 250, 250, 250};
1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate3[] = {250, 250, 250, 250, 250};
1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate3[] = {20, 20, 20, 20, 120};
1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost3, 5);
1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 480,
1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      360, 30.0f));
1173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go up spatial.
1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate4[] = {500, 500, 500, 500, 500};
1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate4[] = {500, 500, 500, 500, 500};
1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost4[] = {30, 30, 30, 30, 30};
1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost4, 5);
1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f,
1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 640, 480, 30.0f));
1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Two stages of 3/4x3/4 converted to one stage of 1/2x1/2.
1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTEST_F(QmSelectTest, ConvertThreeQuartersToOneHalf) {
1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Initialize with bitrate, frame rate, native system width/height, and
1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // number of temporal layers.
1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  InitQmNativeData(150, 30, 640, 480, 1);
1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update with encoder frame size.
1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_width = 640;
1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint16_t codec_height = 480;
1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Go down 3/4x3/4 spatial.
1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update rates for a sequence of intervals.
1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate[] = {150, 150, 150};
1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate[] = {150, 150, 150};
1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate[] = {30, 30, 30};
1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost[] = {10, 10, 10};
1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost, 3);
1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, low spatial.
1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      1.0f, 480, 360, 30.0f));
1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Set rates to go down another 3/4 spatial. Should be converted ton 1/2.
1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->ResetRates();
1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int target_rate2[] = {100, 100, 100, 100, 100};
1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   fraction_lost2, 5);
1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update content: motion level, and 3 spatial prediction errors.
1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Medium motion, low spatial.
1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      30.0f));
1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid QmSelectTest::InitQmNativeData(float initial_bit_rate,
1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int user_frame_rate,
1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int native_width,
1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int native_height,
1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int num_layers) {
1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, qm_resolution_->Initialize(initial_bit_rate,
1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          user_frame_rate,
1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          native_width,
1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          native_height,
1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          num_layers));
1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid QmSelectTest::UpdateQmContentData(float motion_metric,
1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       float spatial_metric,
1256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       float spatial_metric_horiz,
1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       float spatial_metric_vert) {
1258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  content_metrics_->motion_magnitude = motion_metric;
1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  content_metrics_->spatial_pred_err = spatial_metric;
1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  content_metrics_->spatial_pred_err_h = spatial_metric_horiz;
1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  content_metrics_->spatial_pred_err_v = spatial_metric_vert;
1262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_resolution_->UpdateContent(content_metrics_);
1263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid QmSelectTest::UpdateQmEncodedFrame(int* encoded_size, int num_updates) {
1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameType frame_type = kVideoFrameDelta;
1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (int i = 0; i < num_updates; ++i) {
1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Convert to bytes.
1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int32_t encoded_size_update = 1000 * encoded_size[i] / 8;
1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    qm_resolution_->UpdateEncodedSize(encoded_size_update, frame_type);
1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid QmSelectTest::UpdateQmRateData(int* target_rate,
1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int* encoder_sent_rate,
1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int* incoming_frame_rate,
1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    uint8_t* fraction_lost,
1278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int num_updates) {
1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (int i = 0; i < num_updates; ++i) {
1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    float target_rate_update = target_rate[i];
1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    float encoder_sent_rate_update = encoder_sent_rate[i];
1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    float incoming_frame_rate_update = incoming_frame_rate[i];
1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    uint8_t fraction_lost_update = fraction_lost[i];
1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    qm_resolution_->UpdateRates(target_rate_update,
1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                encoder_sent_rate_update,
1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                incoming_frame_rate_update,
1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                fraction_lost_update);
1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Check is the selected action from the QmResolution class is the same
1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// as the expected scales from |fac_width|, |fac_height|, |fac_temp|.
1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool QmSelectTest::IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
1294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           float fac_width,
1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           float fac_height,
1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           float fac_temp,
1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           uint16_t new_width,
1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           uint16_t new_height,
1299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                           float new_frame_rate) {
1300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (qm_scale->spatial_width_fact == fac_width &&
1301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      qm_scale->spatial_height_fact == fac_height &&
1302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      qm_scale->temporal_fact == fac_temp &&
1303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      qm_scale->codec_width == new_width &&
1304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      qm_scale->codec_height == new_height &&
1305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      qm_scale->frame_rate == new_frame_rate) {
1306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
1307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
1309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
1312