Line data Source code
1 : /*
2 : * Copyright (c) 2010 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 <math.h>
12 : #include "vpx_mem/vpx_mem.h"
13 :
14 : #include "onyx_int.h"
15 : #include "vp8/encoder/quantize.h"
16 : #include "vp8/common/quant_common.h"
17 :
18 0 : void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d) {
19 : int i, rc, eob;
20 : int x, y, z, sz;
21 0 : short *coeff_ptr = b->coeff;
22 0 : short *round_ptr = b->round;
23 0 : short *quant_ptr = b->quant_fast;
24 0 : short *qcoeff_ptr = d->qcoeff;
25 0 : short *dqcoeff_ptr = d->dqcoeff;
26 0 : short *dequant_ptr = d->dequant;
27 :
28 0 : eob = -1;
29 0 : for (i = 0; i < 16; ++i) {
30 0 : rc = vp8_default_zig_zag1d[i];
31 0 : z = coeff_ptr[rc];
32 :
33 0 : sz = (z >> 31); /* sign of z */
34 0 : x = (z ^ sz) - sz; /* x = abs(z) */
35 :
36 0 : y = ((x + round_ptr[rc]) * quant_ptr[rc]) >> 16; /* quantize (x) */
37 0 : x = (y ^ sz) - sz; /* get the sign back */
38 0 : qcoeff_ptr[rc] = x; /* write to destination */
39 0 : dqcoeff_ptr[rc] = x * dequant_ptr[rc]; /* dequantized value */
40 :
41 0 : if (y) {
42 0 : eob = i; /* last nonzero coeffs */
43 : }
44 : }
45 0 : *d->eob = (char)(eob + 1);
46 0 : }
47 :
48 0 : void vp8_regular_quantize_b_c(BLOCK *b, BLOCKD *d) {
49 : int i, rc, eob;
50 : int zbin;
51 : int x, y, z, sz;
52 0 : short *zbin_boost_ptr = b->zrun_zbin_boost;
53 0 : short *coeff_ptr = b->coeff;
54 0 : short *zbin_ptr = b->zbin;
55 0 : short *round_ptr = b->round;
56 0 : short *quant_ptr = b->quant;
57 0 : short *quant_shift_ptr = b->quant_shift;
58 0 : short *qcoeff_ptr = d->qcoeff;
59 0 : short *dqcoeff_ptr = d->dqcoeff;
60 0 : short *dequant_ptr = d->dequant;
61 0 : short zbin_oq_value = b->zbin_extra;
62 :
63 0 : memset(qcoeff_ptr, 0, 32);
64 0 : memset(dqcoeff_ptr, 0, 32);
65 :
66 0 : eob = -1;
67 :
68 0 : for (i = 0; i < 16; ++i) {
69 0 : rc = vp8_default_zig_zag1d[i];
70 0 : z = coeff_ptr[rc];
71 :
72 0 : zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value;
73 :
74 0 : zbin_boost_ptr++;
75 0 : sz = (z >> 31); /* sign of z */
76 0 : x = (z ^ sz) - sz; /* x = abs(z) */
77 :
78 0 : if (x >= zbin) {
79 0 : x += round_ptr[rc];
80 0 : y = ((((x * quant_ptr[rc]) >> 16) + x) * quant_shift_ptr[rc]) >>
81 : 16; /* quantize (x) */
82 0 : x = (y ^ sz) - sz; /* get the sign back */
83 0 : qcoeff_ptr[rc] = x; /* write to destination */
84 0 : dqcoeff_ptr[rc] = x * dequant_ptr[rc]; /* dequantized value */
85 :
86 0 : if (y) {
87 0 : eob = i; /* last nonzero coeffs */
88 0 : zbin_boost_ptr = b->zrun_zbin_boost; /* reset zero runlength */
89 : }
90 : }
91 : }
92 :
93 0 : *d->eob = (char)(eob + 1);
94 0 : }
95 :
96 0 : void vp8_quantize_mby(MACROBLOCK *x) {
97 : int i;
98 0 : int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&
99 0 : x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
100 :
101 0 : for (i = 0; i < 16; ++i) x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
102 :
103 0 : if (has_2nd_order) x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
104 0 : }
105 :
106 0 : void vp8_quantize_mb(MACROBLOCK *x) {
107 : int i;
108 0 : int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&
109 0 : x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
110 :
111 0 : for (i = 0; i < 24 + has_2nd_order; ++i) {
112 0 : x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
113 : }
114 0 : }
115 :
116 0 : void vp8_quantize_mbuv(MACROBLOCK *x) {
117 : int i;
118 :
119 0 : for (i = 16; i < 24; ++i) x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
120 0 : }
121 :
122 : static const int qrounding_factors[129] = {
123 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
124 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
125 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
126 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
127 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
128 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
129 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
130 : };
131 :
132 : static const int qzbin_factors[129] = {
133 : 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
134 : 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
135 : 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 80, 80, 80, 80, 80, 80, 80, 80, 80,
136 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
137 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
138 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
139 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
140 : };
141 :
142 : static const int qrounding_factors_y2[129] = {
143 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
144 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
145 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
146 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
147 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
148 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
149 : 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
150 : };
151 :
152 : static const int qzbin_factors_y2[129] = {
153 : 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
154 : 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
155 : 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 80, 80, 80, 80, 80, 80, 80, 80, 80,
156 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
157 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
158 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
159 : 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
160 : };
161 :
162 0 : static void invert_quant(int improved_quant, short *quant, short *shift,
163 : short d) {
164 0 : if (improved_quant) {
165 : unsigned t;
166 : int l, m;
167 0 : t = d;
168 0 : for (l = 0; t > 1; ++l) t >>= 1;
169 0 : m = 1 + (1 << (16 + l)) / d;
170 0 : *quant = (short)(m - (1 << 16));
171 0 : *shift = l;
172 : /* use multiplication and constant shift by 16 */
173 0 : *shift = 1 << (16 - *shift);
174 : } else {
175 0 : *quant = (1 << 16) / d;
176 0 : *shift = 0;
177 : /* use multiplication and constant shift by 16 */
178 0 : *shift = 1 << (16 - *shift);
179 : }
180 0 : }
181 :
182 0 : void vp8cx_init_quantizer(VP8_COMP *cpi) {
183 : int i;
184 : int quant_val;
185 : int Q;
186 :
187 0 : int zbin_boost[16] = { 0, 0, 8, 10, 12, 14, 16, 20,
188 : 24, 28, 32, 36, 40, 44, 44, 44 };
189 :
190 0 : for (Q = 0; Q < QINDEX_RANGE; ++Q) {
191 : /* dc values */
192 0 : quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
193 0 : cpi->Y1quant_fast[Q][0] = (1 << 16) / quant_val;
194 0 : invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 0,
195 0 : cpi->Y1quant_shift[Q] + 0, quant_val);
196 0 : cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
197 0 : cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
198 0 : cpi->common.Y1dequant[Q][0] = quant_val;
199 0 : cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
200 :
201 0 : quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
202 0 : cpi->Y2quant_fast[Q][0] = (1 << 16) / quant_val;
203 0 : invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 0,
204 0 : cpi->Y2quant_shift[Q] + 0, quant_val);
205 0 : cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
206 0 : cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
207 0 : cpi->common.Y2dequant[Q][0] = quant_val;
208 0 : cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
209 :
210 0 : quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
211 0 : cpi->UVquant_fast[Q][0] = (1 << 16) / quant_val;
212 0 : invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 0,
213 0 : cpi->UVquant_shift[Q] + 0, quant_val);
214 0 : cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
215 0 : cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
216 0 : cpi->common.UVdequant[Q][0] = quant_val;
217 0 : cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
218 :
219 : /* all the ac values = ; */
220 0 : quant_val = vp8_ac_yquant(Q);
221 0 : cpi->Y1quant_fast[Q][1] = (1 << 16) / quant_val;
222 0 : invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 1,
223 0 : cpi->Y1quant_shift[Q] + 1, quant_val);
224 0 : cpi->Y1zbin[Q][1] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
225 0 : cpi->Y1round[Q][1] = (qrounding_factors[Q] * quant_val) >> 7;
226 0 : cpi->common.Y1dequant[Q][1] = quant_val;
227 0 : cpi->zrun_zbin_boost_y1[Q][1] = (quant_val * zbin_boost[1]) >> 7;
228 :
229 0 : quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
230 0 : cpi->Y2quant_fast[Q][1] = (1 << 16) / quant_val;
231 0 : invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 1,
232 0 : cpi->Y2quant_shift[Q] + 1, quant_val);
233 0 : cpi->Y2zbin[Q][1] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
234 0 : cpi->Y2round[Q][1] = (qrounding_factors_y2[Q] * quant_val) >> 7;
235 0 : cpi->common.Y2dequant[Q][1] = quant_val;
236 0 : cpi->zrun_zbin_boost_y2[Q][1] = (quant_val * zbin_boost[1]) >> 7;
237 :
238 0 : quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
239 0 : cpi->UVquant_fast[Q][1] = (1 << 16) / quant_val;
240 0 : invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 1,
241 0 : cpi->UVquant_shift[Q] + 1, quant_val);
242 0 : cpi->UVzbin[Q][1] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
243 0 : cpi->UVround[Q][1] = (qrounding_factors[Q] * quant_val) >> 7;
244 0 : cpi->common.UVdequant[Q][1] = quant_val;
245 0 : cpi->zrun_zbin_boost_uv[Q][1] = (quant_val * zbin_boost[1]) >> 7;
246 :
247 0 : for (i = 2; i < 16; ++i) {
248 0 : cpi->Y1quant_fast[Q][i] = cpi->Y1quant_fast[Q][1];
249 0 : cpi->Y1quant[Q][i] = cpi->Y1quant[Q][1];
250 0 : cpi->Y1quant_shift[Q][i] = cpi->Y1quant_shift[Q][1];
251 0 : cpi->Y1zbin[Q][i] = cpi->Y1zbin[Q][1];
252 0 : cpi->Y1round[Q][i] = cpi->Y1round[Q][1];
253 0 : cpi->zrun_zbin_boost_y1[Q][i] =
254 0 : (cpi->common.Y1dequant[Q][1] * zbin_boost[i]) >> 7;
255 :
256 0 : cpi->Y2quant_fast[Q][i] = cpi->Y2quant_fast[Q][1];
257 0 : cpi->Y2quant[Q][i] = cpi->Y2quant[Q][1];
258 0 : cpi->Y2quant_shift[Q][i] = cpi->Y2quant_shift[Q][1];
259 0 : cpi->Y2zbin[Q][i] = cpi->Y2zbin[Q][1];
260 0 : cpi->Y2round[Q][i] = cpi->Y2round[Q][1];
261 0 : cpi->zrun_zbin_boost_y2[Q][i] =
262 0 : (cpi->common.Y2dequant[Q][1] * zbin_boost[i]) >> 7;
263 :
264 0 : cpi->UVquant_fast[Q][i] = cpi->UVquant_fast[Q][1];
265 0 : cpi->UVquant[Q][i] = cpi->UVquant[Q][1];
266 0 : cpi->UVquant_shift[Q][i] = cpi->UVquant_shift[Q][1];
267 0 : cpi->UVzbin[Q][i] = cpi->UVzbin[Q][1];
268 0 : cpi->UVround[Q][i] = cpi->UVround[Q][1];
269 0 : cpi->zrun_zbin_boost_uv[Q][i] =
270 0 : (cpi->common.UVdequant[Q][1] * zbin_boost[i]) >> 7;
271 : }
272 : }
273 0 : }
274 :
275 : #define ZBIN_EXTRA_Y \
276 : ((cpi->common.Y1dequant[QIndex][1] * \
277 : (x->zbin_over_quant + x->zbin_mode_boost + x->act_zbin_adj)) >> \
278 : 7)
279 :
280 : #define ZBIN_EXTRA_UV \
281 : ((cpi->common.UVdequant[QIndex][1] * \
282 : (x->zbin_over_quant + x->zbin_mode_boost + x->act_zbin_adj)) >> \
283 : 7)
284 :
285 : #define ZBIN_EXTRA_Y2 \
286 : ((cpi->common.Y2dequant[QIndex][1] * \
287 : ((x->zbin_over_quant / 2) + x->zbin_mode_boost + x->act_zbin_adj)) >> \
288 : 7)
289 :
290 0 : void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x, int ok_to_skip) {
291 : int i;
292 : int QIndex;
293 0 : MACROBLOCKD *xd = &x->e_mbd;
294 : int zbin_extra;
295 :
296 : /* Select the baseline MB Q index. */
297 0 : if (xd->segmentation_enabled) {
298 : /* Abs Value */
299 0 : if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA) {
300 0 : QIndex = xd->segment_feature_data[MB_LVL_ALT_Q]
301 0 : [xd->mode_info_context->mbmi.segment_id];
302 : /* Delta Value */
303 : } else {
304 0 : QIndex = cpi->common.base_qindex +
305 : xd->segment_feature_data[MB_LVL_ALT_Q]
306 0 : [xd->mode_info_context->mbmi.segment_id];
307 : /* Clamp to valid range */
308 0 : QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;
309 : }
310 : } else {
311 0 : QIndex = cpi->common.base_qindex;
312 : }
313 :
314 : /* This initialization should be called at least once. Use ok_to_skip to
315 : * decide if it is ok to skip.
316 : * Before encoding a frame, this function is always called with ok_to_skip
317 : * =0, which means no skiping of calculations. The "last" values are
318 : * initialized at that time.
319 : */
320 0 : if (!ok_to_skip || QIndex != x->q_index) {
321 0 : xd->dequant_y1_dc[0] = 1;
322 0 : xd->dequant_y1[0] = cpi->common.Y1dequant[QIndex][0];
323 0 : xd->dequant_y2[0] = cpi->common.Y2dequant[QIndex][0];
324 0 : xd->dequant_uv[0] = cpi->common.UVdequant[QIndex][0];
325 :
326 0 : for (i = 1; i < 16; ++i) {
327 0 : xd->dequant_y1_dc[i] = xd->dequant_y1[i] =
328 0 : cpi->common.Y1dequant[QIndex][1];
329 0 : xd->dequant_y2[i] = cpi->common.Y2dequant[QIndex][1];
330 0 : xd->dequant_uv[i] = cpi->common.UVdequant[QIndex][1];
331 : }
332 : #if 1
333 : /*TODO: Remove dequant from BLOCKD. This is a temporary solution until
334 : * the quantizer code uses a passed in pointer to the dequant constants.
335 : * This will also require modifications to the x86 and neon assembly.
336 : * */
337 0 : for (i = 0; i < 16; ++i) x->e_mbd.block[i].dequant = xd->dequant_y1;
338 0 : for (i = 16; i < 24; ++i) x->e_mbd.block[i].dequant = xd->dequant_uv;
339 0 : x->e_mbd.block[24].dequant = xd->dequant_y2;
340 : #endif
341 :
342 : /* Y */
343 0 : zbin_extra = ZBIN_EXTRA_Y;
344 :
345 0 : for (i = 0; i < 16; ++i) {
346 0 : x->block[i].quant = cpi->Y1quant[QIndex];
347 0 : x->block[i].quant_fast = cpi->Y1quant_fast[QIndex];
348 0 : x->block[i].quant_shift = cpi->Y1quant_shift[QIndex];
349 0 : x->block[i].zbin = cpi->Y1zbin[QIndex];
350 0 : x->block[i].round = cpi->Y1round[QIndex];
351 0 : x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[QIndex];
352 0 : x->block[i].zbin_extra = (short)zbin_extra;
353 : }
354 :
355 : /* UV */
356 0 : zbin_extra = ZBIN_EXTRA_UV;
357 :
358 0 : for (i = 16; i < 24; ++i) {
359 0 : x->block[i].quant = cpi->UVquant[QIndex];
360 0 : x->block[i].quant_fast = cpi->UVquant_fast[QIndex];
361 0 : x->block[i].quant_shift = cpi->UVquant_shift[QIndex];
362 0 : x->block[i].zbin = cpi->UVzbin[QIndex];
363 0 : x->block[i].round = cpi->UVround[QIndex];
364 0 : x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[QIndex];
365 0 : x->block[i].zbin_extra = (short)zbin_extra;
366 : }
367 :
368 : /* Y2 */
369 0 : zbin_extra = ZBIN_EXTRA_Y2;
370 :
371 0 : x->block[24].quant_fast = cpi->Y2quant_fast[QIndex];
372 0 : x->block[24].quant = cpi->Y2quant[QIndex];
373 0 : x->block[24].quant_shift = cpi->Y2quant_shift[QIndex];
374 0 : x->block[24].zbin = cpi->Y2zbin[QIndex];
375 0 : x->block[24].round = cpi->Y2round[QIndex];
376 0 : x->block[24].zrun_zbin_boost = cpi->zrun_zbin_boost_y2[QIndex];
377 0 : x->block[24].zbin_extra = (short)zbin_extra;
378 :
379 : /* save this macroblock QIndex for vp8_update_zbin_extra() */
380 0 : x->q_index = QIndex;
381 :
382 0 : x->last_zbin_over_quant = x->zbin_over_quant;
383 0 : x->last_zbin_mode_boost = x->zbin_mode_boost;
384 0 : x->last_act_zbin_adj = x->act_zbin_adj;
385 :
386 0 : } else if (x->last_zbin_over_quant != x->zbin_over_quant ||
387 0 : x->last_zbin_mode_boost != x->zbin_mode_boost ||
388 0 : x->last_act_zbin_adj != x->act_zbin_adj) {
389 : /* Y */
390 0 : zbin_extra = ZBIN_EXTRA_Y;
391 :
392 0 : for (i = 0; i < 16; ++i) x->block[i].zbin_extra = (short)zbin_extra;
393 :
394 : /* UV */
395 0 : zbin_extra = ZBIN_EXTRA_UV;
396 :
397 0 : for (i = 16; i < 24; ++i) x->block[i].zbin_extra = (short)zbin_extra;
398 :
399 : /* Y2 */
400 0 : zbin_extra = ZBIN_EXTRA_Y2;
401 0 : x->block[24].zbin_extra = (short)zbin_extra;
402 :
403 0 : x->last_zbin_over_quant = x->zbin_over_quant;
404 0 : x->last_zbin_mode_boost = x->zbin_mode_boost;
405 0 : x->last_act_zbin_adj = x->act_zbin_adj;
406 : }
407 0 : }
408 :
409 0 : void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x) {
410 : int i;
411 0 : int QIndex = x->q_index;
412 : int zbin_extra;
413 :
414 : /* Y */
415 0 : zbin_extra = ZBIN_EXTRA_Y;
416 :
417 0 : for (i = 0; i < 16; ++i) x->block[i].zbin_extra = (short)zbin_extra;
418 :
419 : /* UV */
420 0 : zbin_extra = ZBIN_EXTRA_UV;
421 :
422 0 : for (i = 16; i < 24; ++i) x->block[i].zbin_extra = (short)zbin_extra;
423 :
424 : /* Y2 */
425 0 : zbin_extra = ZBIN_EXTRA_Y2;
426 0 : x->block[24].zbin_extra = (short)zbin_extra;
427 0 : }
428 : #undef ZBIN_EXTRA_Y
429 : #undef ZBIN_EXTRA_UV
430 : #undef ZBIN_EXTRA_Y2
431 :
432 0 : void vp8cx_frame_init_quantizer(VP8_COMP *cpi) {
433 : /* Clear Zbin mode boost for default case */
434 0 : cpi->mb.zbin_mode_boost = 0;
435 :
436 : /* MB level quantizer setup */
437 0 : vp8cx_mb_init_quantizer(cpi, &cpi->mb, 0);
438 0 : }
439 :
440 0 : void vp8_set_quantizer(struct VP8_COMP *cpi, int Q) {
441 0 : VP8_COMMON *cm = &cpi->common;
442 0 : MACROBLOCKD *mbd = &cpi->mb.e_mbd;
443 0 : int update = 0;
444 : int new_delta_q;
445 : int new_uv_delta_q;
446 0 : cm->base_qindex = Q;
447 :
448 : /* if any of the delta_q values are changing update flag has to be set */
449 : /* currently only y2dc_delta_q may change */
450 :
451 0 : cm->y1dc_delta_q = 0;
452 0 : cm->y2ac_delta_q = 0;
453 :
454 0 : if (Q < 4) {
455 0 : new_delta_q = 4 - Q;
456 : } else {
457 0 : new_delta_q = 0;
458 : }
459 :
460 0 : update |= cm->y2dc_delta_q != new_delta_q;
461 0 : cm->y2dc_delta_q = new_delta_q;
462 :
463 0 : new_uv_delta_q = 0;
464 : // For screen content, lower the q value for UV channel. For now, select
465 : // conservative delta; same delta for dc and ac, and decrease it with lower
466 : // Q, and set to 0 below some threshold. May want to condition this in
467 : // future on the variance/energy in UV channel.
468 0 : if (cpi->oxcf.screen_content_mode && Q > 40) {
469 0 : new_uv_delta_q = -(int)(0.15 * Q);
470 : // Check range: magnitude of delta is 4 bits.
471 0 : if (new_uv_delta_q < -15) {
472 0 : new_uv_delta_q = -15;
473 : }
474 : }
475 0 : update |= cm->uvdc_delta_q != new_uv_delta_q;
476 0 : cm->uvdc_delta_q = new_uv_delta_q;
477 0 : cm->uvac_delta_q = new_uv_delta_q;
478 :
479 : /* Set Segment specific quatizers */
480 0 : mbd->segment_feature_data[MB_LVL_ALT_Q][0] =
481 0 : cpi->segment_feature_data[MB_LVL_ALT_Q][0];
482 0 : mbd->segment_feature_data[MB_LVL_ALT_Q][1] =
483 0 : cpi->segment_feature_data[MB_LVL_ALT_Q][1];
484 0 : mbd->segment_feature_data[MB_LVL_ALT_Q][2] =
485 0 : cpi->segment_feature_data[MB_LVL_ALT_Q][2];
486 0 : mbd->segment_feature_data[MB_LVL_ALT_Q][3] =
487 0 : cpi->segment_feature_data[MB_LVL_ALT_Q][3];
488 :
489 : /* quantizer has to be reinitialized for any delta_q changes */
490 0 : if (update) vp8cx_init_quantizer(cpi);
491 0 : }
|