/src/libvpx/vp9/encoder/vp9_aq_complexity.c
Line | Count | Source (jump to first uncovered line) |
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> |
13 | | #include "vpx_dsp/vpx_dsp_common.h" |
14 | | #include "vpx_ports/system_state.h" |
15 | | |
16 | | #include "vp9/encoder/vp9_aq_complexity.h" |
17 | | #include "vp9/encoder/vp9_aq_variance.h" |
18 | | #include "vp9/encoder/vp9_encodeframe.h" |
19 | | #include "vp9/common/vp9_seg_common.h" |
20 | | #include "vp9/encoder/vp9_segmentation.h" |
21 | | |
22 | 0 | #define AQ_C_SEGMENTS 5 |
23 | 0 | #define DEFAULT_AQ2_SEG 3 // Neutral Q segment |
24 | | #define AQ_C_STRENGTHS 3 |
25 | | static const double aq_c_q_adj_factor[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = { |
26 | | { 1.75, 1.25, 1.05, 1.00, 0.90 }, |
27 | | { 2.00, 1.50, 1.15, 1.00, 0.85 }, |
28 | | { 2.50, 1.75, 1.25, 1.00, 0.80 } |
29 | | }; |
30 | | static const double aq_c_transitions[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = { |
31 | | { 0.15, 0.30, 0.55, 2.00, 100.0 }, |
32 | | { 0.20, 0.40, 0.65, 2.00, 100.0 }, |
33 | | { 0.25, 0.50, 0.75, 2.00, 100.0 } |
34 | | }; |
35 | | static const double aq_c_var_thresholds[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = { |
36 | | { -4.0, -3.0, -2.0, 100.00, 100.0 }, |
37 | | { -3.5, -2.5, -1.5, 100.00, 100.0 }, |
38 | | { -3.0, -2.0, -1.0, 100.00, 100.0 } |
39 | | }; |
40 | | |
41 | 0 | static int get_aq_c_strength(int q_index, vpx_bit_depth_t bit_depth) { |
42 | | // Approximate base quatizer (truncated to int) |
43 | 0 | const int base_quant = vp9_ac_quant(q_index, 0, bit_depth) / 4; |
44 | 0 | return (base_quant > 10) + (base_quant > 25); |
45 | 0 | } |
46 | | |
47 | 0 | void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) { |
48 | 0 | VP9_COMMON *const cm = &cpi->common; |
49 | 0 | struct segmentation *const seg = &cm->seg; |
50 | | |
51 | | // Make SURE use of floating point in this function is safe. |
52 | 0 | vpx_clear_system_state(); |
53 | |
|
54 | 0 | if (frame_is_intra_only(cm) || cm->error_resilient_mode || |
55 | 0 | cpi->refresh_alt_ref_frame || cpi->force_update_segmentation || |
56 | 0 | (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) { |
57 | 0 | int segment; |
58 | 0 | const int aq_strength = get_aq_c_strength(cm->base_qindex, cm->bit_depth); |
59 | | |
60 | | // Clear down the segment map. |
61 | 0 | memset(cpi->segmentation_map, DEFAULT_AQ2_SEG, cm->mi_rows * cm->mi_cols); |
62 | |
|
63 | 0 | vp9_clearall_segfeatures(seg); |
64 | | |
65 | | // Segmentation only makes sense if the target bits per SB is above a |
66 | | // threshold. Below this the overheads will usually outweigh any benefit. |
67 | 0 | if (cpi->rc.sb64_target_rate < 256) { |
68 | 0 | vp9_disable_segmentation(seg); |
69 | 0 | return; |
70 | 0 | } |
71 | | |
72 | 0 | vp9_enable_segmentation(seg); |
73 | | |
74 | | // Select delta coding method. |
75 | 0 | seg->abs_delta = SEGMENT_DELTADATA; |
76 | | |
77 | | // Default segment "Q" feature is disabled so it defaults to the baseline Q. |
78 | 0 | vp9_disable_segfeature(seg, DEFAULT_AQ2_SEG, SEG_LVL_ALT_Q); |
79 | | |
80 | | // Use some of the segments for in frame Q adjustment. |
81 | 0 | for (segment = 0; segment < AQ_C_SEGMENTS; ++segment) { |
82 | 0 | int qindex_delta; |
83 | |
|
84 | 0 | if (segment == DEFAULT_AQ2_SEG) continue; |
85 | | |
86 | 0 | qindex_delta = vp9_compute_qdelta_by_rate( |
87 | 0 | &cpi->rc, cm->frame_type, cm->base_qindex, |
88 | 0 | aq_c_q_adj_factor[aq_strength][segment], cm->bit_depth); |
89 | | |
90 | | // For AQ complexity mode, we don't allow Q0 in a segment if the base |
91 | | // Q is not 0. Q0 (lossless) implies 4x4 only and in AQ mode 2 a segment |
92 | | // Q delta is sometimes applied without going back around the rd loop. |
93 | | // This could lead to an illegal combination of partition size and q. |
94 | 0 | if ((cm->base_qindex != 0) && ((cm->base_qindex + qindex_delta) == 0)) { |
95 | 0 | qindex_delta = -cm->base_qindex + 1; |
96 | 0 | } |
97 | 0 | if ((cm->base_qindex + qindex_delta) > 0) { |
98 | 0 | vp9_enable_segfeature(seg, segment, SEG_LVL_ALT_Q); |
99 | 0 | vp9_set_segdata(seg, segment, SEG_LVL_ALT_Q, qindex_delta); |
100 | 0 | } |
101 | 0 | } |
102 | 0 | } |
103 | 0 | } |
104 | | |
105 | 0 | #define DEFAULT_LV_THRESH 10.0 |
106 | | #define MIN_DEFAULT_LV_THRESH 8.0 |
107 | | // Select a segment for the current block. |
108 | | // The choice of segment for a block depends on the ratio of the projected |
109 | | // bits for the block vs a target average and its spatial complexity. |
110 | | void vp9_caq_select_segment(VP9_COMP *cpi, MACROBLOCK *mb, BLOCK_SIZE bs, |
111 | 0 | int mi_row, int mi_col, int projected_rate) { |
112 | 0 | VP9_COMMON *const cm = &cpi->common; |
113 | |
|
114 | 0 | const int mi_offset = mi_row * cm->mi_cols + mi_col; |
115 | 0 | const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64]; |
116 | 0 | const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64]; |
117 | 0 | const int xmis = VPXMIN(cm->mi_cols - mi_col, num_8x8_blocks_wide_lookup[bs]); |
118 | 0 | const int ymis = VPXMIN(cm->mi_rows - mi_row, num_8x8_blocks_high_lookup[bs]); |
119 | 0 | int x, y; |
120 | 0 | int i; |
121 | 0 | unsigned char segment; |
122 | |
|
123 | 0 | if (0) { |
124 | 0 | segment = DEFAULT_AQ2_SEG; |
125 | 0 | } else { |
126 | | // Rate depends on fraction of a SB64 in frame (xmis * ymis / bw * bh). |
127 | | // It is converted to bits * 256 units. |
128 | 0 | const int target_rate = |
129 | 0 | (cpi->rc.sb64_target_rate * xmis * ymis * 256) / (bw * bh); |
130 | 0 | double logvar; |
131 | 0 | double low_var_thresh; |
132 | 0 | const int aq_strength = get_aq_c_strength(cm->base_qindex, cm->bit_depth); |
133 | |
|
134 | 0 | vpx_clear_system_state(); |
135 | 0 | low_var_thresh = (cpi->oxcf.pass == 2) ? VPXMAX(cpi->twopass.mb_av_energy, |
136 | 0 | MIN_DEFAULT_LV_THRESH) |
137 | 0 | : DEFAULT_LV_THRESH; |
138 | |
|
139 | 0 | vp9_setup_src_planes(mb, cpi->Source, mi_row, mi_col); |
140 | 0 | logvar = vp9_log_block_var(cpi, mb, bs); |
141 | |
|
142 | 0 | segment = AQ_C_SEGMENTS - 1; // Just in case no break out below. |
143 | 0 | for (i = 0; i < AQ_C_SEGMENTS; ++i) { |
144 | | // Test rate against a threshold value and variance against a threshold. |
145 | | // Increasing segment number (higher variance and complexity) = higher Q. |
146 | 0 | if ((projected_rate < target_rate * aq_c_transitions[aq_strength][i]) && |
147 | 0 | (logvar < (low_var_thresh + aq_c_var_thresholds[aq_strength][i]))) { |
148 | 0 | segment = i; |
149 | 0 | break; |
150 | 0 | } |
151 | 0 | } |
152 | 0 | } |
153 | | |
154 | | // Fill in the entires in the segment map corresponding to this SB64. |
155 | 0 | for (y = 0; y < ymis; y++) { |
156 | 0 | for (x = 0; x < xmis; x++) { |
157 | 0 | cpi->segmentation_map[mi_offset + y * cm->mi_cols + x] = segment; |
158 | 0 | } |
159 | 0 | } |
160 | 0 | } |