Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2014 The WebM project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #include <limits.h> |
| 12 | #include <math.h> |
Alex Converse | a8a08ce | 2015-08-10 11:28:04 -0700 | [diff] [blame] | 13 | #include "vpx_ports/system_state.h" |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 14 | |
James Zern | 97db651 | 2015-05-14 20:21:01 -0700 | [diff] [blame] | 15 | #include "vp9/encoder/vp9_aq_complexity.h" |
Paul Wilkins | d031237 | 2014-11-07 16:32:50 +0000 | [diff] [blame] | 16 | #include "vp9/encoder/vp9_aq_variance.h" |
| 17 | #include "vp9/encoder/vp9_encodeframe.h" |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 18 | #include "vp9/common/vp9_seg_common.h" |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 19 | #include "vp9/encoder/vp9_segmentation.h" |
| 20 | |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 21 | #define AQ_C_SEGMENTS 5 |
| 22 | #define DEFAULT_AQ2_SEG 3 // Neutral Q segment |
| 23 | #define AQ_C_STRENGTHS 3 |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 24 | static const double aq_c_q_adj_factor[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 25 | { {1.75, 1.25, 1.05, 1.00, 0.90}, |
| 26 | {2.00, 1.50, 1.15, 1.00, 0.85}, |
| 27 | {2.50, 1.75, 1.25, 1.00, 0.80} }; |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 28 | static const double aq_c_transitions[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 29 | { {0.15, 0.30, 0.55, 2.00, 100.0}, |
| 30 | {0.20, 0.40, 0.65, 2.00, 100.0}, |
| 31 | {0.25, 0.50, 0.75, 2.00, 100.0} }; |
| 32 | static const double aq_c_var_thresholds[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = |
| 33 | { {-4.0, -3.0, -2.0, 100.00, 100.0}, |
| 34 | {-3.5, -2.5, -1.5, 100.00, 100.0}, |
| 35 | {-3.0, -2.0, -1.0, 100.00, 100.0} }; |
| 36 | |
| 37 | #define DEFAULT_COMPLEXITY 64 |
| 38 | |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 39 | |
Deb Mukherjee | 5cd0aab | 2014-09-02 16:34:09 -0700 | [diff] [blame] | 40 | static int get_aq_c_strength(int q_index, vpx_bit_depth_t bit_depth) { |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 41 | // Approximate base quatizer (truncated to int) |
Deb Mukherjee | 5cd0aab | 2014-09-02 16:34:09 -0700 | [diff] [blame] | 42 | const int base_quant = vp9_ac_quant(q_index, 0, bit_depth) / 4; |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 43 | return (base_quant > 10) + (base_quant > 25); |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 44 | } |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 45 | |
| 46 | void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) { |
| 47 | VP9_COMMON *const cm = &cpi->common; |
| 48 | struct segmentation *const seg = &cm->seg; |
| 49 | |
| 50 | // Make SURE use of floating point in this function is safe. |
Alex Converse | a8a08ce | 2015-08-10 11:28:04 -0700 | [diff] [blame] | 51 | vpx_clear_system_state(); |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 52 | |
| 53 | if (cm->frame_type == KEY_FRAME || |
| 54 | cpi->refresh_alt_ref_frame || |
| 55 | (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) { |
| 56 | int segment; |
Deb Mukherjee | 5cd0aab | 2014-09-02 16:34:09 -0700 | [diff] [blame] | 57 | const int aq_strength = get_aq_c_strength(cm->base_qindex, cm->bit_depth); |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 58 | |
| 59 | // Clear down the segment map. |
James Zern | f58011a | 2015-04-23 20:47:40 -0700 | [diff] [blame] | 60 | memset(cpi->segmentation_map, DEFAULT_AQ2_SEG, cm->mi_rows * cm->mi_cols); |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 61 | |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 62 | vp9_clearall_segfeatures(seg); |
| 63 | |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 64 | // Segmentation only makes sense if the target bits per SB is above a |
| 65 | // threshold. Below this the overheads will usually outweigh any benefit. |
| 66 | if (cpi->rc.sb64_target_rate < 256) { |
| 67 | vp9_disable_segmentation(seg); |
| 68 | return; |
| 69 | } |
| 70 | |
| 71 | vp9_enable_segmentation(seg); |
| 72 | |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 73 | // Select delta coding method. |
| 74 | seg->abs_delta = SEGMENT_DELTADATA; |
| 75 | |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 76 | // Default segment "Q" feature is disabled so it defaults to the baseline Q. |
| 77 | vp9_disable_segfeature(seg, DEFAULT_AQ2_SEG, SEG_LVL_ALT_Q); |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 78 | |
| 79 | // Use some of the segments for in frame Q adjustment. |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 80 | for (segment = 0; segment < AQ_C_SEGMENTS; ++segment) { |
| 81 | int qindex_delta; |
| 82 | |
| 83 | if (segment == DEFAULT_AQ2_SEG) |
| 84 | continue; |
| 85 | |
| 86 | qindex_delta = |
| 87 | vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type, cm->base_qindex, |
| 88 | aq_c_q_adj_factor[aq_strength][segment], |
| 89 | cm->bit_depth); |
| 90 | |
Paul Wilkins | 090d079 | 2014-06-03 13:03:49 +0100 | [diff] [blame] | 91 | |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 92 | // For AQ complexity mode, we dont allow Q0 in a segment if the base |
| 93 | // Q is not 0. Q0 (lossless) implies 4x4 only and in AQ mode 2 a segment |
| 94 | // Q delta is sometimes applied without going back around the rd loop. |
Paul Wilkins | 090d079 | 2014-06-03 13:03:49 +0100 | [diff] [blame] | 95 | // This could lead to an illegal combination of partition size and q. |
| 96 | if ((cm->base_qindex != 0) && ((cm->base_qindex + qindex_delta) == 0)) { |
| 97 | qindex_delta = -cm->base_qindex + 1; |
| 98 | } |
| 99 | if ((cm->base_qindex + qindex_delta) > 0) { |
| 100 | vp9_enable_segfeature(seg, segment, SEG_LVL_ALT_Q); |
| 101 | vp9_set_segdata(seg, segment, SEG_LVL_ALT_Q, qindex_delta); |
| 102 | } |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 103 | } |
| 104 | } |
| 105 | } |
| 106 | |
Paul Wilkins | 00e3626 | 2014-11-25 14:54:55 +0000 | [diff] [blame] | 107 | #define DEFAULT_LV_THRESH 10.0 |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 108 | #define MIN_DEFAULT_LV_THRESH 8.0 |
| 109 | #define VAR_STRENGTH_STEP 0.25 |
| 110 | // Select a segment for the current block. |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 111 | // The choice of segment for a block depends on the ratio of the projected |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 112 | // bits for the block vs a target average and its spatial complexity. |
| 113 | void vp9_caq_select_segment(VP9_COMP *cpi, MACROBLOCK *mb, BLOCK_SIZE bs, |
| 114 | int mi_row, int mi_col, int projected_rate) { |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 115 | VP9_COMMON *const cm = &cpi->common; |
| 116 | |
| 117 | const int mi_offset = mi_row * cm->mi_cols + mi_col; |
| 118 | const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64]; |
| 119 | const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64]; |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 120 | const int xmis = MIN(cm->mi_cols - mi_col, num_8x8_blocks_wide_lookup[bs]); |
| 121 | const int ymis = MIN(cm->mi_rows - mi_row, num_8x8_blocks_high_lookup[bs]); |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 122 | int x, y; |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 123 | int i; |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 124 | unsigned char segment; |
| 125 | |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 126 | if (0) { |
| 127 | segment = DEFAULT_AQ2_SEG; |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 128 | } else { |
| 129 | // Rate depends on fraction of a SB64 in frame (xmis * ymis / bw * bh). |
| 130 | // It is converted to bits * 256 units. |
| 131 | const int target_rate = (cpi->rc.sb64_target_rate * xmis * ymis * 256) / |
| 132 | (bw * bh); |
Paul Wilkins | d031237 | 2014-11-07 16:32:50 +0000 | [diff] [blame] | 133 | double logvar; |
Paul Wilkins | 00e3626 | 2014-11-25 14:54:55 +0000 | [diff] [blame] | 134 | double low_var_thresh; |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 135 | const int aq_strength = get_aq_c_strength(cm->base_qindex, cm->bit_depth); |
Paul Wilkins | 00e3626 | 2014-11-25 14:54:55 +0000 | [diff] [blame] | 136 | |
Alex Converse | a8a08ce | 2015-08-10 11:28:04 -0700 | [diff] [blame] | 137 | vpx_clear_system_state(); |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 138 | low_var_thresh = (cpi->oxcf.pass == 2) |
| 139 | ? MAX(cpi->twopass.mb_av_energy, MIN_DEFAULT_LV_THRESH) |
| 140 | : DEFAULT_LV_THRESH; |
Paul Wilkins | d031237 | 2014-11-07 16:32:50 +0000 | [diff] [blame] | 141 | |
Yunqing Wang | edbd61e | 2014-11-21 11:11:06 -0800 | [diff] [blame] | 142 | vp9_setup_src_planes(mb, cpi->Source, mi_row, mi_col); |
| 143 | logvar = vp9_log_block_var(cpi, mb, bs); |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 144 | |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 145 | segment = AQ_C_SEGMENTS - 1; // Just in case no break out below. |
| 146 | for (i = 0; i < AQ_C_SEGMENTS; ++i) { |
| 147 | // Test rate against a threshold value and variance against a threshold. |
| 148 | // Increasing segment number (higher variance and complexity) = higher Q. |
Paul Wilkins | d031237 | 2014-11-07 16:32:50 +0000 | [diff] [blame] | 149 | if ((projected_rate < |
Paul Wilkins | e68c8dc | 2014-11-27 10:50:56 +0000 | [diff] [blame] | 150 | target_rate * aq_c_transitions[aq_strength][i]) && |
| 151 | (logvar < (low_var_thresh + aq_c_var_thresholds[aq_strength][i]))) { |
| 152 | segment = i; |
Paul Wilkins | adf4293 | 2014-06-04 14:14:14 +0100 | [diff] [blame] | 153 | break; |
| 154 | } |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 155 | } |
| 156 | } |
| 157 | |
| 158 | // Fill in the entires in the segment map corresponding to this SB64. |
| 159 | for (y = 0; y < ymis; y++) { |
| 160 | for (x = 0; x < xmis; x++) { |
| 161 | cpi->segmentation_map[mi_offset + y * cm->mi_cols + x] = segment; |
Marco Paniconi | 2b06bf2 | 2014-03-26 16:05:45 -0700 | [diff] [blame] | 162 | } |
| 163 | } |
| 164 | } |