Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(530)

Side by Side Diff: webrtc/modules/video_coding/qm_select.cc

Issue 1528503003: Lint enabled for webrtc/modules/video_coding folder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/video_coding/qm_select.h ('k') | webrtc/modules/video_coding/qm_select_data.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 18 matching lines...) Expand all
29 user_frame_rate_(0.0f), 29 user_frame_rate_(0.0f),
30 native_width_(0), 30 native_width_(0),
31 native_height_(0), 31 native_height_(0),
32 native_frame_rate_(0.0f), 32 native_frame_rate_(0.0f),
33 image_type_(kVGA), 33 image_type_(kVGA),
34 framerate_level_(kFrameRateHigh), 34 framerate_level_(kFrameRateHigh),
35 init_(false) { 35 init_(false) {
36 ResetQM(); 36 ResetQM();
37 } 37 }
38 38
39 VCMQmMethod::~VCMQmMethod() { 39 VCMQmMethod::~VCMQmMethod() {}
40 }
41 40
42 void VCMQmMethod::ResetQM() { 41 void VCMQmMethod::ResetQM() {
43 aspect_ratio_ = 1.0f; 42 aspect_ratio_ = 1.0f;
44 motion_.Reset(); 43 motion_.Reset();
45 spatial_.Reset(); 44 spatial_.Reset();
46 content_class_ = 0; 45 content_class_ = 0;
47 } 46 }
48 47
49 uint8_t VCMQmMethod::ComputeContentClass() { 48 uint8_t VCMQmMethod::ComputeContentClass() {
50 ComputeMotionNFD(); 49 ComputeMotionNFD();
51 ComputeSpatial(); 50 ComputeSpatial();
52 return content_class_ = 3 * motion_.level + spatial_.level; 51 return content_class_ = 3 * motion_.level + spatial_.level;
53 } 52 }
54 53
55 void VCMQmMethod::UpdateContent(const VideoContentMetrics* contentMetrics) { 54 void VCMQmMethod::UpdateContent(const VideoContentMetrics* contentMetrics) {
56 content_metrics_ = contentMetrics; 55 content_metrics_ = contentMetrics;
57 } 56 }
58 57
59 void VCMQmMethod::ComputeMotionNFD() { 58 void VCMQmMethod::ComputeMotionNFD() {
60 if (content_metrics_) { 59 if (content_metrics_) {
61 motion_.value = content_metrics_->motion_magnitude; 60 motion_.value = content_metrics_->motion_magnitude;
62 } 61 }
63 // Determine motion level. 62 // Determine motion level.
64 if (motion_.value < kLowMotionNfd) { 63 if (motion_.value < kLowMotionNfd) {
65 motion_.level = kLow; 64 motion_.level = kLow;
66 } else if (motion_.value > kHighMotionNfd) { 65 } else if (motion_.value > kHighMotionNfd) {
67 motion_.level = kHigh; 66 motion_.level = kHigh;
68 } else { 67 } else {
69 motion_.level = kDefault; 68 motion_.level = kDefault;
70 } 69 }
71 } 70 }
72 71
73 void VCMQmMethod::ComputeSpatial() { 72 void VCMQmMethod::ComputeSpatial() {
74 float spatial_err = 0.0; 73 float spatial_err = 0.0;
75 float spatial_err_h = 0.0; 74 float spatial_err_h = 0.0;
76 float spatial_err_v = 0.0; 75 float spatial_err_v = 0.0;
77 if (content_metrics_) { 76 if (content_metrics_) {
78 spatial_err = content_metrics_->spatial_pred_err; 77 spatial_err = content_metrics_->spatial_pred_err;
79 spatial_err_h = content_metrics_->spatial_pred_err_h; 78 spatial_err_h = content_metrics_->spatial_pred_err_h;
80 spatial_err_v = content_metrics_->spatial_pred_err_v; 79 spatial_err_v = content_metrics_->spatial_pred_err_v;
81 } 80 }
82 // Spatial measure: take average of 3 prediction errors. 81 // Spatial measure: take average of 3 prediction errors.
83 spatial_.value = (spatial_err + spatial_err_h + spatial_err_v) / 3.0f; 82 spatial_.value = (spatial_err + spatial_err_h + spatial_err_v) / 3.0f;
84 83
85 // Reduce thresholds for large scenes/higher pixel correlation. 84 // Reduce thresholds for large scenes/higher pixel correlation.
86 float scale2 = image_type_ > kVGA ? kScaleTexture : 1.0; 85 float scale2 = image_type_ > kVGA ? kScaleTexture : 1.0;
87 86
88 if (spatial_.value > scale2 * kHighTexture) { 87 if (spatial_.value > scale2 * kHighTexture) {
89 spatial_.level = kHigh; 88 spatial_.level = kHigh;
90 } else if (spatial_.value < scale2 * kLowTexture) { 89 } else if (spatial_.value < scale2 * kLowTexture) {
91 spatial_.level = kLow; 90 spatial_.level = kLow;
92 } else { 91 } else {
93 spatial_.level = kDefault; 92 spatial_.level = kDefault;
94 } 93 }
95 } 94 }
96 95
97 ImageType VCMQmMethod::GetImageType(uint16_t width, 96 ImageType VCMQmMethod::GetImageType(uint16_t width, uint16_t height) {
98 uint16_t height) {
99 // Get the image type for the encoder frame size. 97 // Get the image type for the encoder frame size.
100 uint32_t image_size = width * height; 98 uint32_t image_size = width * height;
101 if (image_size == kSizeOfImageType[kQCIF]) { 99 if (image_size == kSizeOfImageType[kQCIF]) {
102 return kQCIF; 100 return kQCIF;
103 } else if (image_size == kSizeOfImageType[kHCIF]) { 101 } else if (image_size == kSizeOfImageType[kHCIF]) {
104 return kHCIF; 102 return kHCIF;
105 } else if (image_size == kSizeOfImageType[kQVGA]) { 103 } else if (image_size == kSizeOfImageType[kQVGA]) {
106 return kQVGA; 104 return kQVGA;
107 } else if (image_size == kSizeOfImageType[kCIF]) { 105 } else if (image_size == kSizeOfImageType[kCIF]) {
108 return kCIF; 106 return kCIF;
(...skipping 26 matching lines...) Expand all
135 } 133 }
136 return static_cast<ImageType>(isel); 134 return static_cast<ImageType>(isel);
137 } 135 }
138 136
139 FrameRateLevelClass VCMQmMethod::FrameRateLevel(float avg_framerate) { 137 FrameRateLevelClass VCMQmMethod::FrameRateLevel(float avg_framerate) {
140 if (avg_framerate <= kLowFrameRate) { 138 if (avg_framerate <= kLowFrameRate) {
141 return kFrameRateLow; 139 return kFrameRateLow;
142 } else if (avg_framerate <= kMiddleFrameRate) { 140 } else if (avg_framerate <= kMiddleFrameRate) {
143 return kFrameRateMiddle1; 141 return kFrameRateMiddle1;
144 } else if (avg_framerate <= kHighFrameRate) { 142 } else if (avg_framerate <= kHighFrameRate) {
145 return kFrameRateMiddle2; 143 return kFrameRateMiddle2;
146 } else { 144 } else {
147 return kFrameRateHigh; 145 return kFrameRateHigh;
148 } 146 }
149 } 147 }
150 148
151 // RESOLUTION CLASS 149 // RESOLUTION CLASS
152 150
153 VCMQmResolution::VCMQmResolution() 151 VCMQmResolution::VCMQmResolution() : qm_(new VCMResolutionScale()) {
154 : qm_(new VCMResolutionScale()) {
155 Reset(); 152 Reset();
156 } 153 }
157 154
158 VCMQmResolution::~VCMQmResolution() { 155 VCMQmResolution::~VCMQmResolution() {
159 delete qm_; 156 delete qm_;
160 } 157 }
161 158
162 void VCMQmResolution::ResetRates() { 159 void VCMQmResolution::ResetRates() {
163 sum_target_rate_ = 0.0f; 160 sum_target_rate_ = 0.0f;
164 sum_incoming_framerate_ = 0.0f; 161 sum_incoming_framerate_ = 0.0f;
165 sum_rate_MM_ = 0.0f; 162 sum_rate_MM_ = 0.0f;
166 sum_rate_MM_sgn_ = 0.0f; 163 sum_rate_MM_sgn_ = 0.0f;
167 sum_packet_loss_ = 0.0f; 164 sum_packet_loss_ = 0.0f;
168 buffer_level_ = kInitBufferLevel * target_bitrate_; 165 buffer_level_ = kInitBufferLevel * target_bitrate_;
169 frame_cnt_ = 0; 166 frame_cnt_ = 0;
170 frame_cnt_delta_ = 0; 167 frame_cnt_delta_ = 0;
171 low_buffer_cnt_ = 0; 168 low_buffer_cnt_ = 0;
172 update_rate_cnt_ = 0; 169 update_rate_cnt_ = 0;
173 } 170 }
174 171
175 void VCMQmResolution::ResetDownSamplingState() { 172 void VCMQmResolution::ResetDownSamplingState() {
176 state_dec_factor_spatial_ = 1.0; 173 state_dec_factor_spatial_ = 1.0;
177 state_dec_factor_temporal_ = 1.0; 174 state_dec_factor_temporal_ = 1.0;
178 for (int i = 0; i < kDownActionHistorySize; i++) { 175 for (int i = 0; i < kDownActionHistorySize; i++) {
179 down_action_history_[i].spatial = kNoChangeSpatial; 176 down_action_history_[i].spatial = kNoChangeSpatial;
180 down_action_history_[i].temporal = kNoChangeTemporal; 177 down_action_history_[i].temporal = kNoChangeTemporal;
181 } 178 }
182 } 179 }
183 180
184 void VCMQmResolution::Reset() { 181 void VCMQmResolution::Reset() {
185 target_bitrate_ = 0.0f; 182 target_bitrate_ = 0.0f;
186 incoming_framerate_ = 0.0f; 183 incoming_framerate_ = 0.0f;
187 buffer_level_ = 0.0f; 184 buffer_level_ = 0.0f;
(...skipping 30 matching lines...) Expand all
218 incoming_framerate_ = user_framerate; 215 incoming_framerate_ = user_framerate;
219 UpdateCodecParameters(user_framerate, width, height); 216 UpdateCodecParameters(user_framerate, width, height);
220 native_width_ = width; 217 native_width_ = width;
221 native_height_ = height; 218 native_height_ = height;
222 native_frame_rate_ = user_framerate; 219 native_frame_rate_ = user_framerate;
223 num_layers_ = num_layers; 220 num_layers_ = num_layers;
224 // Initial buffer level. 221 // Initial buffer level.
225 buffer_level_ = kInitBufferLevel * target_bitrate_; 222 buffer_level_ = kInitBufferLevel * target_bitrate_;
226 // Per-frame bandwidth. 223 // Per-frame bandwidth.
227 per_frame_bandwidth_ = target_bitrate_ / user_framerate; 224 per_frame_bandwidth_ = target_bitrate_ / user_framerate;
228 init_ = true; 225 init_ = true;
229 return VCM_OK; 226 return VCM_OK;
230 } 227 }
231 228
232 void VCMQmResolution::UpdateCodecParameters(float frame_rate, uint16_t width, 229 void VCMQmResolution::UpdateCodecParameters(float frame_rate,
230 uint16_t width,
233 uint16_t height) { 231 uint16_t height) {
234 width_ = width; 232 width_ = width;
235 height_ = height; 233 height_ = height;
236 // |user_frame_rate| is the target frame rate for VPM frame dropper. 234 // |user_frame_rate| is the target frame rate for VPM frame dropper.
237 user_frame_rate_ = frame_rate; 235 user_frame_rate_ = frame_rate;
238 image_type_ = GetImageType(width, height); 236 image_type_ = GetImageType(width, height);
239 } 237 }
240 238
241 // Update rate data after every encoded frame. 239 // Update rate data after every encoded frame.
242 void VCMQmResolution::UpdateEncodedSize(size_t encoded_size) { 240 void VCMQmResolution::UpdateEncodedSize(size_t encoded_size) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 // at previous ~1sec. 274 // at previous ~1sec.
277 float diff = target_bitrate_ - encoder_sent_rate; 275 float diff = target_bitrate_ - encoder_sent_rate;
278 if (target_bitrate_ > 0.0) 276 if (target_bitrate_ > 0.0)
279 sum_rate_MM_ += fabs(diff) / target_bitrate_; 277 sum_rate_MM_ += fabs(diff) / target_bitrate_;
280 int sgnDiff = diff > 0 ? 1 : (diff < 0 ? -1 : 0); 278 int sgnDiff = diff > 0 ? 1 : (diff < 0 ? -1 : 0);
281 // To check for consistent under(+)/over_shooting(-) of target rate. 279 // To check for consistent under(+)/over_shooting(-) of target rate.
282 sum_rate_MM_sgn_ += sgnDiff; 280 sum_rate_MM_sgn_ += sgnDiff;
283 281
284 // Update with the current new target and frame rate: 282 // Update with the current new target and frame rate:
285 // these values are ones the encoder will use for the current/next ~1sec. 283 // these values are ones the encoder will use for the current/next ~1sec.
286 target_bitrate_ = target_bitrate; 284 target_bitrate_ = target_bitrate;
287 incoming_framerate_ = incoming_framerate; 285 incoming_framerate_ = incoming_framerate;
288 sum_incoming_framerate_ += incoming_framerate_; 286 sum_incoming_framerate_ += incoming_framerate_;
289 // Update the per_frame_bandwidth: 287 // Update the per_frame_bandwidth:
290 // this is the per_frame_bw for the current/next ~1sec. 288 // this is the per_frame_bw for the current/next ~1sec.
291 per_frame_bandwidth_ = 0.0f; 289 per_frame_bandwidth_ = 0.0f;
292 if (incoming_framerate_ > 0.0f) { 290 if (incoming_framerate_ > 0.0f) {
293 per_frame_bandwidth_ = target_bitrate_ / incoming_framerate_; 291 per_frame_bandwidth_ = target_bitrate_ / incoming_framerate_;
294 } 292 }
295 } 293 }
296 294
297 // Select the resolution factors: frame size and frame rate change (qm scales). 295 // Select the resolution factors: frame size and frame rate change (qm scales).
298 // Selection is for going down in resolution, or for going back up 296 // Selection is for going down in resolution, or for going back up
299 // (if a previous down-sampling action was taken). 297 // (if a previous down-sampling action was taken).
300 298
301 // In the current version the following constraints are imposed: 299 // In the current version the following constraints are imposed:
302 // 1) We only allow for one action, either down or up, at a given time. 300 // 1) We only allow for one action, either down or up, at a given time.
303 // 2) The possible down-sampling actions are: spatial by 1/2x1/2, 3/4x3/4; 301 // 2) The possible down-sampling actions are: spatial by 1/2x1/2, 3/4x3/4;
304 // temporal/frame rate reduction by 1/2 and 2/3. 302 // temporal/frame rate reduction by 1/2 and 2/3.
305 // 3) The action for going back up is the reverse of last (spatial or temporal) 303 // 3) The action for going back up is the reverse of last (spatial or temporal)
306 // down-sampling action. The list of down-sampling actions from the 304 // down-sampling action. The list of down-sampling actions from the
307 // Initialize() state are kept in |down_action_history_|. 305 // Initialize() state are kept in |down_action_history_|.
308 // 4) The total amount of down-sampling (spatial and/or temporal) from the 306 // 4) The total amount of down-sampling (spatial and/or temporal) from the
309 // Initialize() state (native resolution) is limited by various factors. 307 // Initialize() state (native resolution) is limited by various factors.
310 int VCMQmResolution::SelectResolution(VCMResolutionScale** qm) { 308 int VCMQmResolution::SelectResolution(VCMResolutionScale** qm) {
311 if (!init_) { 309 if (!init_) {
312 return VCM_UNINITIALIZED; 310 return VCM_UNINITIALIZED;
313 } 311 }
314 if (content_metrics_ == NULL) { 312 if (content_metrics_ == NULL) {
315 Reset(); 313 Reset();
316 *qm = qm_; 314 *qm = qm_;
317 return VCM_OK; 315 return VCM_OK;
318 } 316 }
319 317
320 // Check conditions on down-sampling state. 318 // Check conditions on down-sampling state.
321 assert(state_dec_factor_spatial_ >= 1.0f); 319 assert(state_dec_factor_spatial_ >= 1.0f);
322 assert(state_dec_factor_temporal_ >= 1.0f); 320 assert(state_dec_factor_temporal_ >= 1.0f);
323 assert(state_dec_factor_spatial_ <= kMaxSpatialDown); 321 assert(state_dec_factor_spatial_ <= kMaxSpatialDown);
324 assert(state_dec_factor_temporal_ <= kMaxTempDown); 322 assert(state_dec_factor_temporal_ <= kMaxTempDown);
325 assert(state_dec_factor_temporal_ * state_dec_factor_spatial_ <= 323 assert(state_dec_factor_temporal_ * state_dec_factor_spatial_ <=
326 kMaxTotalDown); 324 kMaxTotalDown);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 } 367 }
370 368
371 void VCMQmResolution::ComputeRatesForSelection() { 369 void VCMQmResolution::ComputeRatesForSelection() {
372 avg_target_rate_ = 0.0f; 370 avg_target_rate_ = 0.0f;
373 avg_incoming_framerate_ = 0.0f; 371 avg_incoming_framerate_ = 0.0f;
374 avg_ratio_buffer_low_ = 0.0f; 372 avg_ratio_buffer_low_ = 0.0f;
375 avg_rate_mismatch_ = 0.0f; 373 avg_rate_mismatch_ = 0.0f;
376 avg_rate_mismatch_sgn_ = 0.0f; 374 avg_rate_mismatch_sgn_ = 0.0f;
377 avg_packet_loss_ = 0.0f; 375 avg_packet_loss_ = 0.0f;
378 if (frame_cnt_ > 0) { 376 if (frame_cnt_ > 0) {
379 avg_ratio_buffer_low_ = static_cast<float>(low_buffer_cnt_) / 377 avg_ratio_buffer_low_ =
380 static_cast<float>(frame_cnt_); 378 static_cast<float>(low_buffer_cnt_) / static_cast<float>(frame_cnt_);
381 } 379 }
382 if (update_rate_cnt_ > 0) { 380 if (update_rate_cnt_ > 0) {
383 avg_rate_mismatch_ = static_cast<float>(sum_rate_MM_) / 381 avg_rate_mismatch_ =
384 static_cast<float>(update_rate_cnt_); 382 static_cast<float>(sum_rate_MM_) / static_cast<float>(update_rate_cnt_);
385 avg_rate_mismatch_sgn_ = static_cast<float>(sum_rate_MM_sgn_) / 383 avg_rate_mismatch_sgn_ = static_cast<float>(sum_rate_MM_sgn_) /
386 static_cast<float>(update_rate_cnt_); 384 static_cast<float>(update_rate_cnt_);
387 avg_target_rate_ = static_cast<float>(sum_target_rate_) / 385 avg_target_rate_ = static_cast<float>(sum_target_rate_) /
388 static_cast<float>(update_rate_cnt_); 386 static_cast<float>(update_rate_cnt_);
389 avg_incoming_framerate_ = static_cast<float>(sum_incoming_framerate_) / 387 avg_incoming_framerate_ = static_cast<float>(sum_incoming_framerate_) /
390 static_cast<float>(update_rate_cnt_); 388 static_cast<float>(update_rate_cnt_);
391 avg_packet_loss_ = static_cast<float>(sum_packet_loss_) / 389 avg_packet_loss_ = static_cast<float>(sum_packet_loss_) /
392 static_cast<float>(update_rate_cnt_); 390 static_cast<float>(update_rate_cnt_);
393 } 391 }
394 // For selection we may want to weight some quantities more heavily 392 // For selection we may want to weight some quantities more heavily
395 // with the current (i.e., next ~1sec) rate values. 393 // with the current (i.e., next ~1sec) rate values.
396 avg_target_rate_ = kWeightRate * avg_target_rate_ + 394 avg_target_rate_ =
397 (1.0 - kWeightRate) * target_bitrate_; 395 kWeightRate * avg_target_rate_ + (1.0 - kWeightRate) * target_bitrate_;
398 avg_incoming_framerate_ = kWeightRate * avg_incoming_framerate_ + 396 avg_incoming_framerate_ = kWeightRate * avg_incoming_framerate_ +
399 (1.0 - kWeightRate) * incoming_framerate_; 397 (1.0 - kWeightRate) * incoming_framerate_;
400 // Use base layer frame rate for temporal layers: this will favor spatial. 398 // Use base layer frame rate for temporal layers: this will favor spatial.
401 assert(num_layers_ > 0); 399 assert(num_layers_ > 0);
402 framerate_level_ = FrameRateLevel( 400 framerate_level_ = FrameRateLevel(avg_incoming_framerate_ /
403 avg_incoming_framerate_ / static_cast<float>(1 << (num_layers_ - 1))); 401 static_cast<float>(1 << (num_layers_ - 1)));
404 } 402 }
405 403
406 void VCMQmResolution::ComputeEncoderState() { 404 void VCMQmResolution::ComputeEncoderState() {
407 // Default. 405 // Default.
408 encoder_state_ = kStableEncoding; 406 encoder_state_ = kStableEncoding;
409 407
410 // Assign stressed state if: 408 // Assign stressed state if:
411 // 1) occurrences of low buffer levels is high, or 409 // 1) occurrences of low buffer levels is high, or
412 // 2) rate mis-match is high, and consistent over-shooting by encoder. 410 // 2) rate mis-match is high, and consistent over-shooting by encoder.
413 if ((avg_ratio_buffer_low_ > kMaxBufferLow) || 411 if ((avg_ratio_buffer_low_ > kMaxBufferLow) ||
414 ((avg_rate_mismatch_ > kMaxRateMisMatch) && 412 ((avg_rate_mismatch_ > kMaxRateMisMatch) &&
415 (avg_rate_mismatch_sgn_ < -kRateOverShoot))) { 413 (avg_rate_mismatch_sgn_ < -kRateOverShoot))) {
416 encoder_state_ = kStressedEncoding; 414 encoder_state_ = kStressedEncoding;
417 } 415 }
418 // Assign easy state if: 416 // Assign easy state if:
419 // 1) rate mis-match is high, and 417 // 1) rate mis-match is high, and
420 // 2) consistent under-shooting by encoder. 418 // 2) consistent under-shooting by encoder.
421 if ((avg_rate_mismatch_ > kMaxRateMisMatch) && 419 if ((avg_rate_mismatch_ > kMaxRateMisMatch) &&
422 (avg_rate_mismatch_sgn_ > kRateUnderShoot)) { 420 (avg_rate_mismatch_sgn_ > kRateUnderShoot)) {
423 encoder_state_ = kEasyEncoding; 421 encoder_state_ = kEasyEncoding;
424 } 422 }
425 } 423 }
426 424
427 bool VCMQmResolution::GoingUpResolution() { 425 bool VCMQmResolution::GoingUpResolution() {
428 // For going up, we check for undoing the previous down-sampling action. 426 // For going up, we check for undoing the previous down-sampling action.
429 427
430 float fac_width = kFactorWidthSpatial[down_action_history_[0].spatial]; 428 float fac_width = kFactorWidthSpatial[down_action_history_[0].spatial];
431 float fac_height = kFactorHeightSpatial[down_action_history_[0].spatial]; 429 float fac_height = kFactorHeightSpatial[down_action_history_[0].spatial];
432 float fac_temp = kFactorTemporal[down_action_history_[0].temporal]; 430 float fac_temp = kFactorTemporal[down_action_history_[0].temporal];
433 // For going up spatially, we allow for going up by 3/4x3/4 at each stage. 431 // For going up spatially, we allow for going up by 3/4x3/4 at each stage.
434 // So if the last spatial action was 1/2x1/2 it would be undone in 2 stages. 432 // So if the last spatial action was 1/2x1/2 it would be undone in 2 stages.
435 // Modify the fac_width/height for this case. 433 // Modify the fac_width/height for this case.
436 if (down_action_history_[0].spatial == kOneQuarterSpatialUniform) { 434 if (down_action_history_[0].spatial == kOneQuarterSpatialUniform) {
437 fac_width = kFactorWidthSpatial[kOneQuarterSpatialUniform] / 435 fac_width = kFactorWidthSpatial[kOneQuarterSpatialUniform] /
438 kFactorWidthSpatial[kOneHalfSpatialUniform]; 436 kFactorWidthSpatial[kOneHalfSpatialUniform];
439 fac_height = kFactorHeightSpatial[kOneQuarterSpatialUniform] / 437 fac_height = kFactorHeightSpatial[kOneQuarterSpatialUniform] /
440 kFactorHeightSpatial[kOneHalfSpatialUniform]; 438 kFactorHeightSpatial[kOneHalfSpatialUniform];
441 } 439 }
442 440
443 // Check if we should go up both spatially and temporally. 441 // Check if we should go up both spatially and temporally.
444 if (down_action_history_[0].spatial != kNoChangeSpatial && 442 if (down_action_history_[0].spatial != kNoChangeSpatial &&
445 down_action_history_[0].temporal != kNoChangeTemporal) { 443 down_action_history_[0].temporal != kNoChangeTemporal) {
446 if (ConditionForGoingUp(fac_width, fac_height, fac_temp, 444 if (ConditionForGoingUp(fac_width, fac_height, fac_temp,
447 kTransRateScaleUpSpatialTemp)) { 445 kTransRateScaleUpSpatialTemp)) {
448 action_.spatial = down_action_history_[0].spatial; 446 action_.spatial = down_action_history_[0].spatial;
449 action_.temporal = down_action_history_[0].temporal; 447 action_.temporal = down_action_history_[0].temporal;
450 UpdateDownsamplingState(kUpResolution); 448 UpdateDownsamplingState(kUpResolution);
451 return true; 449 return true;
452 } 450 }
453 } 451 }
454 // Check if we should go up either spatially or temporally. 452 // Check if we should go up either spatially or temporally.
455 bool selected_up_spatial = false; 453 bool selected_up_spatial = false;
456 bool selected_up_temporal = false; 454 bool selected_up_temporal = false;
457 if (down_action_history_[0].spatial != kNoChangeSpatial) { 455 if (down_action_history_[0].spatial != kNoChangeSpatial) {
458 selected_up_spatial = ConditionForGoingUp(fac_width, fac_height, 1.0f, 456 selected_up_spatial = ConditionForGoingUp(fac_width, fac_height, 1.0f,
459 kTransRateScaleUpSpatial); 457 kTransRateScaleUpSpatial);
460 } 458 }
461 if (down_action_history_[0].temporal != kNoChangeTemporal) { 459 if (down_action_history_[0].temporal != kNoChangeTemporal) {
462 selected_up_temporal = ConditionForGoingUp(1.0f, 1.0f, fac_temp, 460 selected_up_temporal =
463 kTransRateScaleUpTemp); 461 ConditionForGoingUp(1.0f, 1.0f, fac_temp, kTransRateScaleUpTemp);
464 } 462 }
465 if (selected_up_spatial && !selected_up_temporal) { 463 if (selected_up_spatial && !selected_up_temporal) {
466 action_.spatial = down_action_history_[0].spatial; 464 action_.spatial = down_action_history_[0].spatial;
467 action_.temporal = kNoChangeTemporal; 465 action_.temporal = kNoChangeTemporal;
468 UpdateDownsamplingState(kUpResolution); 466 UpdateDownsamplingState(kUpResolution);
469 return true; 467 return true;
470 } else if (!selected_up_spatial && selected_up_temporal) { 468 } else if (!selected_up_spatial && selected_up_temporal) {
471 action_.spatial = kNoChangeSpatial; 469 action_.spatial = kNoChangeSpatial;
472 action_.temporal = down_action_history_[0].temporal; 470 action_.temporal = down_action_history_[0].temporal;
473 UpdateDownsamplingState(kUpResolution); 471 UpdateDownsamplingState(kUpResolution);
474 return true; 472 return true;
475 } else if (selected_up_spatial && selected_up_temporal) { 473 } else if (selected_up_spatial && selected_up_temporal) {
476 PickSpatialOrTemporal(); 474 PickSpatialOrTemporal();
477 UpdateDownsamplingState(kUpResolution); 475 UpdateDownsamplingState(kUpResolution);
478 return true; 476 return true;
479 } 477 }
480 return false; 478 return false;
481 } 479 }
482 480
483 bool VCMQmResolution::ConditionForGoingUp(float fac_width, 481 bool VCMQmResolution::ConditionForGoingUp(float fac_width,
484 float fac_height, 482 float fac_height,
485 float fac_temp, 483 float fac_temp,
486 float scale_fac) { 484 float scale_fac) {
487 float estimated_transition_rate_up = GetTransitionRate(fac_width, fac_height, 485 float estimated_transition_rate_up =
488 fac_temp, scale_fac); 486 GetTransitionRate(fac_width, fac_height, fac_temp, scale_fac);
489 // Go back up if: 487 // Go back up if:
490 // 1) target rate is above threshold and current encoder state is stable, or 488 // 1) target rate is above threshold and current encoder state is stable, or
491 // 2) encoder state is easy (encoder is significantly under-shooting target). 489 // 2) encoder state is easy (encoder is significantly under-shooting target).
492 if (((avg_target_rate_ > estimated_transition_rate_up) && 490 if (((avg_target_rate_ > estimated_transition_rate_up) &&
493 (encoder_state_ == kStableEncoding)) || 491 (encoder_state_ == kStableEncoding)) ||
494 (encoder_state_ == kEasyEncoding)) { 492 (encoder_state_ == kEasyEncoding)) {
495 return true; 493 return true;
496 } else { 494 } else {
497 return false; 495 return false;
498 } 496 }
499 } 497 }
500 498
501 bool VCMQmResolution::GoingDownResolution() { 499 bool VCMQmResolution::GoingDownResolution() {
502 float estimated_transition_rate_down = 500 float estimated_transition_rate_down =
503 GetTransitionRate(1.0f, 1.0f, 1.0f, 1.0f); 501 GetTransitionRate(1.0f, 1.0f, 1.0f, 1.0f);
504 float max_rate = kFrameRateFac[framerate_level_] * kMaxRateQm[image_type_]; 502 float max_rate = kFrameRateFac[framerate_level_] * kMaxRateQm[image_type_];
505 // Resolution reduction if: 503 // Resolution reduction if:
506 // (1) target rate is below transition rate, or 504 // (1) target rate is below transition rate, or
507 // (2) encoder is in stressed state and target rate below a max threshold. 505 // (2) encoder is in stressed state and target rate below a max threshold.
508 if ((avg_target_rate_ < estimated_transition_rate_down ) || 506 if ((avg_target_rate_ < estimated_transition_rate_down) ||
509 (encoder_state_ == kStressedEncoding && avg_target_rate_ < max_rate)) { 507 (encoder_state_ == kStressedEncoding && avg_target_rate_ < max_rate)) {
510 // Get the down-sampling action: based on content class, and how low 508 // Get the down-sampling action: based on content class, and how low
511 // average target rate is relative to transition rate. 509 // average target rate is relative to transition rate.
512 uint8_t spatial_fact = 510 uint8_t spatial_fact =
513 kSpatialAction[content_class_ + 511 kSpatialAction[content_class_ +
514 9 * RateClass(estimated_transition_rate_down)]; 512 9 * RateClass(estimated_transition_rate_down)];
515 uint8_t temp_fact = 513 uint8_t temp_fact =
516 kTemporalAction[content_class_ + 514 kTemporalAction[content_class_ +
517 9 * RateClass(estimated_transition_rate_down)]; 515 9 * RateClass(estimated_transition_rate_down)];
518 516
519 switch (spatial_fact) { 517 switch (spatial_fact) {
520 case 4: { 518 case 4: {
521 action_.spatial = kOneQuarterSpatialUniform; 519 action_.spatial = kOneQuarterSpatialUniform;
522 break; 520 break;
523 } 521 }
524 case 2: { 522 case 2: {
525 action_.spatial = kOneHalfSpatialUniform; 523 action_.spatial = kOneHalfSpatialUniform;
526 break; 524 break;
527 } 525 }
528 case 1: { 526 case 1: {
529 action_.spatial = kNoChangeSpatial; 527 action_.spatial = kNoChangeSpatial;
530 break; 528 break;
531 } 529 }
532 default: { 530 default: { assert(false); }
533 assert(false);
534 }
535 } 531 }
536 switch (temp_fact) { 532 switch (temp_fact) {
537 case 3: { 533 case 3: {
538 action_.temporal = kTwoThirdsTemporal; 534 action_.temporal = kTwoThirdsTemporal;
539 break; 535 break;
540 } 536 }
541 case 2: { 537 case 2: {
542 action_.temporal = kOneHalfTemporal; 538 action_.temporal = kOneHalfTemporal;
543 break; 539 break;
544 } 540 }
545 case 1: { 541 case 1: {
546 action_.temporal = kNoChangeTemporal; 542 action_.temporal = kNoChangeTemporal;
547 break; 543 break;
548 } 544 }
549 default: { 545 default: { assert(false); }
550 assert(false);
551 }
552 } 546 }
553 // Only allow for one action (spatial or temporal) at a given time. 547 // Only allow for one action (spatial or temporal) at a given time.
554 assert(action_.temporal == kNoChangeTemporal || 548 assert(action_.temporal == kNoChangeTemporal ||
555 action_.spatial == kNoChangeSpatial); 549 action_.spatial == kNoChangeSpatial);
556 550
557 // Adjust cases not captured in tables, mainly based on frame rate, and 551 // Adjust cases not captured in tables, mainly based on frame rate, and
558 // also check for odd frame sizes. 552 // also check for odd frame sizes.
559 AdjustAction(); 553 AdjustAction();
560 554
561 // Update down-sampling state. 555 // Update down-sampling state.
562 if (action_.spatial != kNoChangeSpatial || 556 if (action_.spatial != kNoChangeSpatial ||
563 action_.temporal != kNoChangeTemporal) { 557 action_.temporal != kNoChangeTemporal) {
564 UpdateDownsamplingState(kDownResolution); 558 UpdateDownsamplingState(kDownResolution);
565 return true; 559 return true;
566 } 560 }
567 } 561 }
568 return false; 562 return false;
569 } 563 }
570 564
571 float VCMQmResolution::GetTransitionRate(float fac_width, 565 float VCMQmResolution::GetTransitionRate(float fac_width,
572 float fac_height, 566 float fac_height,
573 float fac_temp, 567 float fac_temp,
574 float scale_fac) { 568 float scale_fac) {
575 ImageType image_type = GetImageType( 569 ImageType image_type =
576 static_cast<uint16_t>(fac_width * width_), 570 GetImageType(static_cast<uint16_t>(fac_width * width_),
577 static_cast<uint16_t>(fac_height * height_)); 571 static_cast<uint16_t>(fac_height * height_));
578 572
579 FrameRateLevelClass framerate_level = 573 FrameRateLevelClass framerate_level =
580 FrameRateLevel(fac_temp * avg_incoming_framerate_); 574 FrameRateLevel(fac_temp * avg_incoming_framerate_);
581 // If we are checking for going up temporally, and this is the last 575 // If we are checking for going up temporally, and this is the last
582 // temporal action, then use native frame rate. 576 // temporal action, then use native frame rate.
583 if (down_action_history_[1].temporal == kNoChangeTemporal && 577 if (down_action_history_[1].temporal == kNoChangeTemporal &&
584 fac_temp > 1.0f) { 578 fac_temp > 1.0f) {
585 framerate_level = FrameRateLevel(native_frame_rate_); 579 framerate_level = FrameRateLevel(native_frame_rate_);
586 } 580 }
587 581
588 // The maximum allowed rate below which down-sampling is allowed: 582 // The maximum allowed rate below which down-sampling is allowed:
589 // Nominal values based on image format (frame size and frame rate). 583 // Nominal values based on image format (frame size and frame rate).
590 float max_rate = kFrameRateFac[framerate_level] * kMaxRateQm[image_type]; 584 float max_rate = kFrameRateFac[framerate_level] * kMaxRateQm[image_type];
591 585
592 uint8_t image_class = image_type > kVGA ? 1: 0; 586 uint8_t image_class = image_type > kVGA ? 1 : 0;
593 uint8_t table_index = image_class * 9 + content_class_; 587 uint8_t table_index = image_class * 9 + content_class_;
594 // Scale factor for down-sampling transition threshold: 588 // Scale factor for down-sampling transition threshold:
595 // factor based on the content class and the image size. 589 // factor based on the content class and the image size.
596 float scaleTransRate = kScaleTransRateQm[table_index]; 590 float scaleTransRate = kScaleTransRateQm[table_index];
597 // Threshold bitrate for resolution action. 591 // Threshold bitrate for resolution action.
598 return static_cast<float> (scale_fac * scaleTransRate * max_rate); 592 return static_cast<float>(scale_fac * scaleTransRate * max_rate);
599 } 593 }
600 594
601 void VCMQmResolution::UpdateDownsamplingState(UpDownAction up_down) { 595 void VCMQmResolution::UpdateDownsamplingState(UpDownAction up_down) {
602 if (up_down == kUpResolution) { 596 if (up_down == kUpResolution) {
603 qm_->spatial_width_fact = 1.0f / kFactorWidthSpatial[action_.spatial]; 597 qm_->spatial_width_fact = 1.0f / kFactorWidthSpatial[action_.spatial];
604 qm_->spatial_height_fact = 1.0f / kFactorHeightSpatial[action_.spatial]; 598 qm_->spatial_height_fact = 1.0f / kFactorHeightSpatial[action_.spatial];
605 // If last spatial action was 1/2x1/2, we undo it in two steps, so the 599 // If last spatial action was 1/2x1/2, we undo it in two steps, so the
606 // spatial scale factor in this first step is modified as (4.0/3.0 / 2.0). 600 // spatial scale factor in this first step is modified as (4.0/3.0 / 2.0).
607 if (action_.spatial == kOneQuarterSpatialUniform) { 601 if (action_.spatial == kOneQuarterSpatialUniform) {
608 qm_->spatial_width_fact = 602 qm_->spatial_width_fact = 1.0f *
609 1.0f * kFactorWidthSpatial[kOneHalfSpatialUniform] / 603 kFactorWidthSpatial[kOneHalfSpatialUniform] /
610 kFactorWidthSpatial[kOneQuarterSpatialUniform]; 604 kFactorWidthSpatial[kOneQuarterSpatialUniform];
611 qm_->spatial_height_fact = 605 qm_->spatial_height_fact =
612 1.0f * kFactorHeightSpatial[kOneHalfSpatialUniform] / 606 1.0f * kFactorHeightSpatial[kOneHalfSpatialUniform] /
613 kFactorHeightSpatial[kOneQuarterSpatialUniform]; 607 kFactorHeightSpatial[kOneQuarterSpatialUniform];
614 } 608 }
615 qm_->temporal_fact = 1.0f / kFactorTemporal[action_.temporal]; 609 qm_->temporal_fact = 1.0f / kFactorTemporal[action_.temporal];
616 RemoveLastDownAction(); 610 RemoveLastDownAction();
617 } else if (up_down == kDownResolution) { 611 } else if (up_down == kDownResolution) {
618 ConstrainAmountOfDownSampling(); 612 ConstrainAmountOfDownSampling();
619 ConvertSpatialFractionalToWhole(); 613 ConvertSpatialFractionalToWhole();
620 qm_->spatial_width_fact = kFactorWidthSpatial[action_.spatial]; 614 qm_->spatial_width_fact = kFactorWidthSpatial[action_.spatial];
621 qm_->spatial_height_fact = kFactorHeightSpatial[action_.spatial]; 615 qm_->spatial_height_fact = kFactorHeightSpatial[action_.spatial];
622 qm_->temporal_fact = kFactorTemporal[action_.temporal]; 616 qm_->temporal_fact = kFactorTemporal[action_.temporal];
623 InsertLatestDownAction(); 617 InsertLatestDownAction();
624 } else { 618 } else {
625 // This function should only be called if either the Up or Down action 619 // This function should only be called if either the Up or Down action
626 // has been selected. 620 // has been selected.
627 assert(false); 621 assert(false);
628 } 622 }
629 UpdateCodecResolution(); 623 UpdateCodecResolution();
630 state_dec_factor_spatial_ = state_dec_factor_spatial_ * 624 state_dec_factor_spatial_ = state_dec_factor_spatial_ *
631 qm_->spatial_width_fact * qm_->spatial_height_fact; 625 qm_->spatial_width_fact *
626 qm_->spatial_height_fact;
632 state_dec_factor_temporal_ = state_dec_factor_temporal_ * qm_->temporal_fact; 627 state_dec_factor_temporal_ = state_dec_factor_temporal_ * qm_->temporal_fact;
633 } 628 }
634 629
635 void VCMQmResolution::UpdateCodecResolution() { 630 void VCMQmResolution::UpdateCodecResolution() {
636 if (action_.spatial != kNoChangeSpatial) { 631 if (action_.spatial != kNoChangeSpatial) {
637 qm_->change_resolution_spatial = true; 632 qm_->change_resolution_spatial = true;
638 qm_->codec_width = static_cast<uint16_t>(width_ / 633 qm_->codec_width =
639 qm_->spatial_width_fact + 0.5f); 634 static_cast<uint16_t>(width_ / qm_->spatial_width_fact + 0.5f);
640 qm_->codec_height = static_cast<uint16_t>(height_ / 635 qm_->codec_height =
641 qm_->spatial_height_fact + 0.5f); 636 static_cast<uint16_t>(height_ / qm_->spatial_height_fact + 0.5f);
642 // Size should not exceed native sizes. 637 // Size should not exceed native sizes.
643 assert(qm_->codec_width <= native_width_); 638 assert(qm_->codec_width <= native_width_);
644 assert(qm_->codec_height <= native_height_); 639 assert(qm_->codec_height <= native_height_);
645 // New sizes should be multiple of 2, otherwise spatial should not have 640 // New sizes should be multiple of 2, otherwise spatial should not have
646 // been selected. 641 // been selected.
647 assert(qm_->codec_width % 2 == 0); 642 assert(qm_->codec_width % 2 == 0);
648 assert(qm_->codec_height % 2 == 0); 643 assert(qm_->codec_height % 2 == 0);
649 } 644 }
650 if (action_.temporal != kNoChangeTemporal) { 645 if (action_.temporal != kNoChangeTemporal) {
651 qm_->change_resolution_temporal = true; 646 qm_->change_resolution_temporal = true;
652 // Update the frame rate based on the average incoming frame rate. 647 // Update the frame rate based on the average incoming frame rate.
653 qm_->frame_rate = avg_incoming_framerate_ / qm_->temporal_fact + 0.5f; 648 qm_->frame_rate = avg_incoming_framerate_ / qm_->temporal_fact + 0.5f;
654 if (down_action_history_[0].temporal == 0) { 649 if (down_action_history_[0].temporal == 0) {
655 // When we undo the last temporal-down action, make sure we go back up 650 // When we undo the last temporal-down action, make sure we go back up
656 // to the native frame rate. Since the incoming frame rate may 651 // to the native frame rate. Since the incoming frame rate may
657 // fluctuate over time, |avg_incoming_framerate_| scaled back up may 652 // fluctuate over time, |avg_incoming_framerate_| scaled back up may
658 // be smaller than |native_frame rate_|. 653 // be smaller than |native_frame rate_|.
659 qm_->frame_rate = native_frame_rate_; 654 qm_->frame_rate = native_frame_rate_;
660 } 655 }
661 } 656 }
662 } 657 }
663 658
664 uint8_t VCMQmResolution::RateClass(float transition_rate) { 659 uint8_t VCMQmResolution::RateClass(float transition_rate) {
665 return avg_target_rate_ < (kFacLowRate * transition_rate) ? 0: 660 return avg_target_rate_ < (kFacLowRate * transition_rate)
666 (avg_target_rate_ >= transition_rate ? 2 : 1); 661 ? 0
662 : (avg_target_rate_ >= transition_rate ? 2 : 1);
667 } 663 }
668 664
669 // TODO(marpan): Would be better to capture these frame rate adjustments by 665 // TODO(marpan): Would be better to capture these frame rate adjustments by
670 // extending the table data (qm_select_data.h). 666 // extending the table data (qm_select_data.h).
671 void VCMQmResolution::AdjustAction() { 667 void VCMQmResolution::AdjustAction() {
672 // If the spatial level is default state (neither low or high), motion level 668 // If the spatial level is default state (neither low or high), motion level
673 // is not high, and spatial action was selected, switch to 2/3 frame rate 669 // is not high, and spatial action was selected, switch to 2/3 frame rate
674 // reduction if the average incoming frame rate is high. 670 // reduction if the average incoming frame rate is high.
675 if (spatial_.level == kDefault && motion_.level != kHigh && 671 if (spatial_.level == kDefault && motion_.level != kHigh &&
676 action_.spatial != kNoChangeSpatial && 672 action_.spatial != kNoChangeSpatial &&
(...skipping 14 matching lines...) Expand all
691 // reduction already (i.e., 1/4), then switch to temporal action if the 687 // reduction already (i.e., 1/4), then switch to temporal action if the
692 // average frame rate is not low. 688 // average frame rate is not low.
693 if (action_.spatial != kNoChangeSpatial && 689 if (action_.spatial != kNoChangeSpatial &&
694 down_action_history_[0].spatial == kOneQuarterSpatialUniform && 690 down_action_history_[0].spatial == kOneQuarterSpatialUniform &&
695 framerate_level_ != kFrameRateLow) { 691 framerate_level_ != kFrameRateLow) {
696 action_.spatial = kNoChangeSpatial; 692 action_.spatial = kNoChangeSpatial;
697 action_.temporal = kTwoThirdsTemporal; 693 action_.temporal = kTwoThirdsTemporal;
698 } 694 }
699 // Never use temporal action if number of temporal layers is above 2. 695 // Never use temporal action if number of temporal layers is above 2.
700 if (num_layers_ > 2) { 696 if (num_layers_ > 2) {
701 if (action_.temporal != kNoChangeTemporal) { 697 if (action_.temporal != kNoChangeTemporal) {
702 action_.spatial = kOneHalfSpatialUniform; 698 action_.spatial = kOneHalfSpatialUniform;
703 } 699 }
704 action_.temporal = kNoChangeTemporal; 700 action_.temporal = kNoChangeTemporal;
705 } 701 }
706 // If spatial action was selected, we need to make sure the frame sizes 702 // If spatial action was selected, we need to make sure the frame sizes
707 // are multiples of two. Otherwise switch to 2/3 temporal. 703 // are multiples of two. Otherwise switch to 2/3 temporal.
708 if (action_.spatial != kNoChangeSpatial && 704 if (action_.spatial != kNoChangeSpatial && !EvenFrameSize()) {
709 !EvenFrameSize()) {
710 action_.spatial = kNoChangeSpatial; 705 action_.spatial = kNoChangeSpatial;
711 // Only one action (spatial or temporal) is allowed at a given time, so need 706 // Only one action (spatial or temporal) is allowed at a given time, so need
712 // to check whether temporal action is currently selected. 707 // to check whether temporal action is currently selected.
713 action_.temporal = kTwoThirdsTemporal; 708 action_.temporal = kTwoThirdsTemporal;
714 } 709 }
715 } 710 }
716 711
717 void VCMQmResolution::ConvertSpatialFractionalToWhole() { 712 void VCMQmResolution::ConvertSpatialFractionalToWhole() {
718 // If 3/4 spatial is selected, check if there has been another 3/4, 713 // If 3/4 spatial is selected, check if there has been another 3/4,
719 // and if so, combine them into 1/2. 1/2 scaling is more efficient than 9/16. 714 // and if so, combine them into 1/2. 1/2 scaling is more efficient than 9/16.
720 // Note we define 3/4x3/4 spatial as kOneHalfSpatialUniform. 715 // Note we define 3/4x3/4 spatial as kOneHalfSpatialUniform.
721 if (action_.spatial == kOneHalfSpatialUniform) { 716 if (action_.spatial == kOneHalfSpatialUniform) {
722 bool found = false; 717 bool found = false;
723 int isel = kDownActionHistorySize; 718 int isel = kDownActionHistorySize;
724 for (int i = 0; i < kDownActionHistorySize; ++i) { 719 for (int i = 0; i < kDownActionHistorySize; ++i) {
725 if (down_action_history_[i].spatial == kOneHalfSpatialUniform) { 720 if (down_action_history_[i].spatial == kOneHalfSpatialUniform) {
726 isel = i; 721 isel = i;
727 found = true; 722 found = true;
728 break; 723 break;
729 } 724 }
730 } 725 }
731 if (found) { 726 if (found) {
732 action_.spatial = kOneQuarterSpatialUniform; 727 action_.spatial = kOneQuarterSpatialUniform;
733 state_dec_factor_spatial_ = state_dec_factor_spatial_ / 728 state_dec_factor_spatial_ =
734 (kFactorWidthSpatial[kOneHalfSpatialUniform] * 729 state_dec_factor_spatial_ /
735 kFactorHeightSpatial[kOneHalfSpatialUniform]); 730 (kFactorWidthSpatial[kOneHalfSpatialUniform] *
736 // Check if switching to 1/2x1/2 (=1/4) spatial is allowed. 731 kFactorHeightSpatial[kOneHalfSpatialUniform]);
737 ConstrainAmountOfDownSampling(); 732 // Check if switching to 1/2x1/2 (=1/4) spatial is allowed.
738 if (action_.spatial == kNoChangeSpatial) { 733 ConstrainAmountOfDownSampling();
739 // Not allowed. Go back to 3/4x3/4 spatial. 734 if (action_.spatial == kNoChangeSpatial) {
740 action_.spatial = kOneHalfSpatialUniform; 735 // Not allowed. Go back to 3/4x3/4 spatial.
741 state_dec_factor_spatial_ = state_dec_factor_spatial_ * 736 action_.spatial = kOneHalfSpatialUniform;
742 kFactorWidthSpatial[kOneHalfSpatialUniform] * 737 state_dec_factor_spatial_ =
743 kFactorHeightSpatial[kOneHalfSpatialUniform]; 738 state_dec_factor_spatial_ *
744 } else { 739 kFactorWidthSpatial[kOneHalfSpatialUniform] *
745 // Switching is allowed. Remove 3/4x3/4 from the history, and update 740 kFactorHeightSpatial[kOneHalfSpatialUniform];
746 // the frame size. 741 } else {
747 for (int i = isel; i < kDownActionHistorySize - 1; ++i) { 742 // Switching is allowed. Remove 3/4x3/4 from the history, and update
748 down_action_history_[i].spatial = 743 // the frame size.
749 down_action_history_[i + 1].spatial; 744 for (int i = isel; i < kDownActionHistorySize - 1; ++i) {
750 } 745 down_action_history_[i].spatial = down_action_history_[i + 1].spatial;
751 width_ = width_ * kFactorWidthSpatial[kOneHalfSpatialUniform]; 746 }
752 height_ = height_ * kFactorHeightSpatial[kOneHalfSpatialUniform]; 747 width_ = width_ * kFactorWidthSpatial[kOneHalfSpatialUniform];
753 } 748 height_ = height_ * kFactorHeightSpatial[kOneHalfSpatialUniform];
749 }
754 } 750 }
755 } 751 }
756 } 752 }
757 753
758 // Returns false if the new frame sizes, under the current spatial action, 754 // Returns false if the new frame sizes, under the current spatial action,
759 // are not multiples of two. 755 // are not multiples of two.
760 bool VCMQmResolution::EvenFrameSize() { 756 bool VCMQmResolution::EvenFrameSize() {
761 if (action_.spatial == kOneHalfSpatialUniform) { 757 if (action_.spatial == kOneHalfSpatialUniform) {
762 if ((width_ * 3 / 4) % 2 != 0 || (height_ * 3 / 4) % 2 != 0) { 758 if ((width_ * 3 / 4) % 2 != 0 || (height_ * 3 / 4) % 2 != 0) {
763 return false; 759 return false;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 } 804 }
809 805
810 void VCMQmResolution::ConstrainAmountOfDownSampling() { 806 void VCMQmResolution::ConstrainAmountOfDownSampling() {
811 // Sanity checks on down-sampling selection: 807 // Sanity checks on down-sampling selection:
812 // override the settings for too small image size and/or frame rate. 808 // override the settings for too small image size and/or frame rate.
813 // Also check the limit on current down-sampling states. 809 // Also check the limit on current down-sampling states.
814 810
815 float spatial_width_fact = kFactorWidthSpatial[action_.spatial]; 811 float spatial_width_fact = kFactorWidthSpatial[action_.spatial];
816 float spatial_height_fact = kFactorHeightSpatial[action_.spatial]; 812 float spatial_height_fact = kFactorHeightSpatial[action_.spatial];
817 float temporal_fact = kFactorTemporal[action_.temporal]; 813 float temporal_fact = kFactorTemporal[action_.temporal];
818 float new_dec_factor_spatial = state_dec_factor_spatial_ * 814 float new_dec_factor_spatial =
819 spatial_width_fact * spatial_height_fact; 815 state_dec_factor_spatial_ * spatial_width_fact * spatial_height_fact;
820 float new_dec_factor_temp = state_dec_factor_temporal_ * temporal_fact; 816 float new_dec_factor_temp = state_dec_factor_temporal_ * temporal_fact;
821 817
822 // No spatial sampling if current frame size is too small, or if the 818 // No spatial sampling if current frame size is too small, or if the
823 // amount of spatial down-sampling is above maximum spatial down-action. 819 // amount of spatial down-sampling is above maximum spatial down-action.
824 if ((width_ * height_) <= kMinImageSize || 820 if ((width_ * height_) <= kMinImageSize ||
825 new_dec_factor_spatial > kMaxSpatialDown) { 821 new_dec_factor_spatial > kMaxSpatialDown) {
826 action_.spatial = kNoChangeSpatial; 822 action_.spatial = kNoChangeSpatial;
827 new_dec_factor_spatial = state_dec_factor_spatial_; 823 new_dec_factor_spatial = state_dec_factor_spatial_;
828 } 824 }
829 // No frame rate reduction if average frame rate is below some point, or if 825 // No frame rate reduction if average frame rate is below some point, or if
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 qm_->spatial_height_fact = 2.0f; 897 qm_->spatial_height_fact = 2.0f;
902 } 898 }
903 } 899 }
904 900
905 // ROBUSTNESS CLASS 901 // ROBUSTNESS CLASS
906 902
907 VCMQmRobustness::VCMQmRobustness() { 903 VCMQmRobustness::VCMQmRobustness() {
908 Reset(); 904 Reset();
909 } 905 }
910 906
911 VCMQmRobustness::~VCMQmRobustness() { 907 VCMQmRobustness::~VCMQmRobustness() {}
912 }
913 908
914 void VCMQmRobustness::Reset() { 909 void VCMQmRobustness::Reset() {
915 prev_total_rate_ = 0.0f; 910 prev_total_rate_ = 0.0f;
916 prev_rtt_time_ = 0; 911 prev_rtt_time_ = 0;
917 prev_packet_loss_ = 0; 912 prev_packet_loss_ = 0;
918 prev_code_rate_delta_ = 0; 913 prev_code_rate_delta_ = 0;
919 ResetQM(); 914 ResetQM();
920 } 915 }
921 916
922 // Adjust the FEC rate based on the content and the network state 917 // Adjust the FEC rate based on the content and the network state
923 // (packet loss rate, total rate/bandwidth, round trip time). 918 // (packet loss rate, total rate/bandwidth, round trip time).
924 // Note that packetLoss here is the filtered loss value. 919 // Note that packetLoss here is the filtered loss value.
925 float VCMQmRobustness::AdjustFecFactor(uint8_t code_rate_delta, 920 float VCMQmRobustness::AdjustFecFactor(uint8_t code_rate_delta,
926 float total_rate, 921 float total_rate,
927 float framerate, 922 float framerate,
928 int64_t rtt_time, 923 int64_t rtt_time,
929 uint8_t packet_loss) { 924 uint8_t packet_loss) {
930 // Default: no adjustment 925 // Default: no adjustment
931 float adjust_fec = 1.0f; 926 float adjust_fec = 1.0f;
932 if (content_metrics_ == NULL) { 927 if (content_metrics_ == NULL) {
933 return adjust_fec; 928 return adjust_fec;
934 } 929 }
935 // Compute class state of the content. 930 // Compute class state of the content.
936 ComputeMotionNFD(); 931 ComputeMotionNFD();
937 ComputeSpatial(); 932 ComputeSpatial();
938 933
939 // TODO(marpan): Set FEC adjustment factor. 934 // TODO(marpan): Set FEC adjustment factor.
940 935
941 // Keep track of previous values of network state: 936 // Keep track of previous values of network state:
942 // adjustment may be also based on pattern of changes in network state. 937 // adjustment may be also based on pattern of changes in network state.
943 prev_total_rate_ = total_rate; 938 prev_total_rate_ = total_rate;
944 prev_rtt_time_ = rtt_time; 939 prev_rtt_time_ = rtt_time;
945 prev_packet_loss_ = packet_loss; 940 prev_packet_loss_ = packet_loss;
946 prev_code_rate_delta_ = code_rate_delta; 941 prev_code_rate_delta_ = code_rate_delta;
947 return adjust_fec; 942 return adjust_fec;
948 } 943 }
949 944
950 // Set the UEP (unequal-protection across packets) on/off for the FEC. 945 // Set the UEP (unequal-protection across packets) on/off for the FEC.
951 bool VCMQmRobustness::SetUepProtection(uint8_t code_rate_delta, 946 bool VCMQmRobustness::SetUepProtection(uint8_t code_rate_delta,
952 float total_rate, 947 float total_rate,
953 uint8_t packet_loss, 948 uint8_t packet_loss,
954 bool frame_type) { 949 bool frame_type) {
955 // Default. 950 // Default.
956 return false; 951 return false;
957 } 952 }
958 } // namespace 953 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/qm_select.h ('k') | webrtc/modules/video_coding/qm_select_data.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698