Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
michael@0 | 3 | * |
michael@0 | 4 | * Use of this source code is governed by a BSD-style license |
michael@0 | 5 | * that can be found in the LICENSE file in the root of the source |
michael@0 | 6 | * tree. An additional intellectual property rights grant can be found |
michael@0 | 7 | * in the file PATENTS. All contributing project authors may |
michael@0 | 8 | * be found in the AUTHORS file in the root of the source tree. |
michael@0 | 9 | */ |
michael@0 | 10 | |
michael@0 | 11 | #include <math.h> |
michael@0 | 12 | #include "vpx_mem/vpx_mem.h" |
michael@0 | 13 | |
michael@0 | 14 | #include "vp9/encoder/vp9_onyx_int.h" |
michael@0 | 15 | #include "vp9/encoder/vp9_rdopt.h" |
michael@0 | 16 | #include "vp9/encoder/vp9_quantize.h" |
michael@0 | 17 | #include "vp9/common/vp9_quant_common.h" |
michael@0 | 18 | |
michael@0 | 19 | #include "vp9/common/vp9_seg_common.h" |
michael@0 | 20 | |
michael@0 | 21 | #ifdef ENC_DEBUG |
michael@0 | 22 | extern int enc_debug; |
michael@0 | 23 | #endif |
michael@0 | 24 | |
michael@0 | 25 | void vp9_quantize_b_c(const int16_t *coeff_ptr, intptr_t count, |
michael@0 | 26 | int skip_block, |
michael@0 | 27 | const int16_t *zbin_ptr, const int16_t *round_ptr, |
michael@0 | 28 | const int16_t *quant_ptr, const int16_t *quant_shift_ptr, |
michael@0 | 29 | int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr, |
michael@0 | 30 | const int16_t *dequant_ptr, |
michael@0 | 31 | int zbin_oq_value, uint16_t *eob_ptr, |
michael@0 | 32 | const int16_t *scan, const int16_t *iscan) { |
michael@0 | 33 | int i, non_zero_count = count, eob = -1; |
michael@0 | 34 | const int zbins[2] = { zbin_ptr[0] + zbin_oq_value, |
michael@0 | 35 | zbin_ptr[1] + zbin_oq_value }; |
michael@0 | 36 | const int nzbins[2] = { zbins[0] * -1, |
michael@0 | 37 | zbins[1] * -1 }; |
michael@0 | 38 | |
michael@0 | 39 | vpx_memset(qcoeff_ptr, 0, count * sizeof(int16_t)); |
michael@0 | 40 | vpx_memset(dqcoeff_ptr, 0, count * sizeof(int16_t)); |
michael@0 | 41 | |
michael@0 | 42 | if (!skip_block) { |
michael@0 | 43 | // Pre-scan pass |
michael@0 | 44 | for (i = count - 1; i >= 0; i--) { |
michael@0 | 45 | const int rc = scan[i]; |
michael@0 | 46 | const int coeff = coeff_ptr[rc]; |
michael@0 | 47 | |
michael@0 | 48 | if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0]) |
michael@0 | 49 | non_zero_count--; |
michael@0 | 50 | else |
michael@0 | 51 | break; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | // Quantization pass: All coefficients with index >= zero_flag are |
michael@0 | 55 | // skippable. Note: zero_flag can be zero. |
michael@0 | 56 | for (i = 0; i < non_zero_count; i++) { |
michael@0 | 57 | const int rc = scan[i]; |
michael@0 | 58 | const int coeff = coeff_ptr[rc]; |
michael@0 | 59 | const int coeff_sign = (coeff >> 31); |
michael@0 | 60 | const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign; |
michael@0 | 61 | |
michael@0 | 62 | if (abs_coeff >= zbins[rc != 0]) { |
michael@0 | 63 | int tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX); |
michael@0 | 64 | tmp = ((((tmp * quant_ptr[rc != 0]) >> 16) + tmp) * |
michael@0 | 65 | quant_shift_ptr[rc != 0]) >> 16; // quantization |
michael@0 | 66 | qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign; |
michael@0 | 67 | dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0]; |
michael@0 | 68 | |
michael@0 | 69 | if (tmp) |
michael@0 | 70 | eob = i; |
michael@0 | 71 | } |
michael@0 | 72 | } |
michael@0 | 73 | } |
michael@0 | 74 | *eob_ptr = eob + 1; |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | void vp9_quantize_b_32x32_c(const int16_t *coeff_ptr, intptr_t n_coeffs, |
michael@0 | 78 | int skip_block, |
michael@0 | 79 | const int16_t *zbin_ptr, const int16_t *round_ptr, |
michael@0 | 80 | const int16_t *quant_ptr, |
michael@0 | 81 | const int16_t *quant_shift_ptr, |
michael@0 | 82 | int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr, |
michael@0 | 83 | const int16_t *dequant_ptr, |
michael@0 | 84 | int zbin_oq_value, uint16_t *eob_ptr, |
michael@0 | 85 | const int16_t *scan, const int16_t *iscan) { |
michael@0 | 86 | int i, rc, eob; |
michael@0 | 87 | int zbins[2], nzbins[2]; |
michael@0 | 88 | int x, y, z, sz; |
michael@0 | 89 | int idx = 0; |
michael@0 | 90 | int idx_arr[1024]; |
michael@0 | 91 | |
michael@0 | 92 | vpx_memset(qcoeff_ptr, 0, n_coeffs*sizeof(int16_t)); |
michael@0 | 93 | vpx_memset(dqcoeff_ptr, 0, n_coeffs*sizeof(int16_t)); |
michael@0 | 94 | |
michael@0 | 95 | eob = -1; |
michael@0 | 96 | |
michael@0 | 97 | // Base ZBIN |
michael@0 | 98 | zbins[0] = ROUND_POWER_OF_TWO(zbin_ptr[0] + zbin_oq_value, 1); |
michael@0 | 99 | zbins[1] = ROUND_POWER_OF_TWO(zbin_ptr[1] + zbin_oq_value, 1); |
michael@0 | 100 | nzbins[0] = zbins[0] * -1; |
michael@0 | 101 | nzbins[1] = zbins[1] * -1; |
michael@0 | 102 | |
michael@0 | 103 | if (!skip_block) { |
michael@0 | 104 | // Pre-scan pass |
michael@0 | 105 | for (i = 0; i < n_coeffs; i++) { |
michael@0 | 106 | rc = scan[i]; |
michael@0 | 107 | z = coeff_ptr[rc]; |
michael@0 | 108 | |
michael@0 | 109 | // If the coefficient is out of the base ZBIN range, keep it for |
michael@0 | 110 | // quantization. |
michael@0 | 111 | if (z >= zbins[rc != 0] || z <= nzbins[rc != 0]) |
michael@0 | 112 | idx_arr[idx++] = i; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | // Quantization pass: only process the coefficients selected in |
michael@0 | 116 | // pre-scan pass. Note: idx can be zero. |
michael@0 | 117 | for (i = 0; i < idx; i++) { |
michael@0 | 118 | rc = scan[idx_arr[i]]; |
michael@0 | 119 | |
michael@0 | 120 | z = coeff_ptr[rc]; |
michael@0 | 121 | sz = (z >> 31); // sign of z |
michael@0 | 122 | x = (z ^ sz) - sz; // x = abs(z) |
michael@0 | 123 | |
michael@0 | 124 | x += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1); |
michael@0 | 125 | x = clamp(x, INT16_MIN, INT16_MAX); |
michael@0 | 126 | y = ((((x * quant_ptr[rc != 0]) >> 16) + x) * |
michael@0 | 127 | quant_shift_ptr[rc != 0]) >> 15; // quantize (x) |
michael@0 | 128 | |
michael@0 | 129 | x = (y ^ sz) - sz; // get the sign back |
michael@0 | 130 | qcoeff_ptr[rc] = x; // write to destination |
michael@0 | 131 | dqcoeff_ptr[rc] = x * dequant_ptr[rc != 0] / 2; // dequantized value |
michael@0 | 132 | |
michael@0 | 133 | if (y) |
michael@0 | 134 | eob = idx_arr[i]; // last nonzero coeffs |
michael@0 | 135 | } |
michael@0 | 136 | } |
michael@0 | 137 | *eob_ptr = eob + 1; |
michael@0 | 138 | } |
michael@0 | 139 | |
michael@0 | 140 | struct plane_block_idx { |
michael@0 | 141 | int plane; |
michael@0 | 142 | int block; |
michael@0 | 143 | }; |
michael@0 | 144 | |
michael@0 | 145 | // TODO(jkoleszar): returning a struct so it can be used in a const context, |
michael@0 | 146 | // expect to refactor this further later. |
michael@0 | 147 | static INLINE struct plane_block_idx plane_block_idx(int y_blocks, |
michael@0 | 148 | int b_idx) { |
michael@0 | 149 | const int v_offset = y_blocks * 5 / 4; |
michael@0 | 150 | struct plane_block_idx res; |
michael@0 | 151 | |
michael@0 | 152 | if (b_idx < y_blocks) { |
michael@0 | 153 | res.plane = 0; |
michael@0 | 154 | res.block = b_idx; |
michael@0 | 155 | } else if (b_idx < v_offset) { |
michael@0 | 156 | res.plane = 1; |
michael@0 | 157 | res.block = b_idx - y_blocks; |
michael@0 | 158 | } else { |
michael@0 | 159 | assert(b_idx < y_blocks * 3 / 2); |
michael@0 | 160 | res.plane = 2; |
michael@0 | 161 | res.block = b_idx - v_offset; |
michael@0 | 162 | } |
michael@0 | 163 | return res; |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | void vp9_regular_quantize_b_4x4(MACROBLOCK *x, int y_blocks, int b_idx, |
michael@0 | 167 | const int16_t *scan, const int16_t *iscan) { |
michael@0 | 168 | MACROBLOCKD *const xd = &x->e_mbd; |
michael@0 | 169 | const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, b_idx); |
michael@0 | 170 | struct macroblock_plane* p = &x->plane[pb_idx.plane]; |
michael@0 | 171 | struct macroblockd_plane* pd = &xd->plane[pb_idx.plane]; |
michael@0 | 172 | |
michael@0 | 173 | vp9_quantize_b(BLOCK_OFFSET(p->coeff, pb_idx.block), |
michael@0 | 174 | 16, x->skip_block, |
michael@0 | 175 | p->zbin, p->round, p->quant, p->quant_shift, |
michael@0 | 176 | BLOCK_OFFSET(pd->qcoeff, pb_idx.block), |
michael@0 | 177 | BLOCK_OFFSET(pd->dqcoeff, pb_idx.block), |
michael@0 | 178 | pd->dequant, p->zbin_extra, &pd->eobs[pb_idx.block], scan, iscan); |
michael@0 | 179 | } |
michael@0 | 180 | |
michael@0 | 181 | static void invert_quant(int16_t *quant, int16_t *shift, int d) { |
michael@0 | 182 | unsigned t; |
michael@0 | 183 | int l; |
michael@0 | 184 | t = d; |
michael@0 | 185 | for (l = 0; t > 1; l++) |
michael@0 | 186 | t >>= 1; |
michael@0 | 187 | t = 1 + (1 << (16 + l)) / d; |
michael@0 | 188 | *quant = (int16_t)(t - (1 << 16)); |
michael@0 | 189 | *shift = 1 << (16 - l); |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | void vp9_init_quantizer(VP9_COMP *cpi) { |
michael@0 | 193 | int i, q; |
michael@0 | 194 | VP9_COMMON *const cm = &cpi->common; |
michael@0 | 195 | |
michael@0 | 196 | for (q = 0; q < QINDEX_RANGE; q++) { |
michael@0 | 197 | const int qzbin_factor = q == 0 ? 64 : (vp9_dc_quant(q, 0) < 148 ? 84 : 80); |
michael@0 | 198 | const int qrounding_factor = q == 0 ? 64 : 48; |
michael@0 | 199 | |
michael@0 | 200 | // y |
michael@0 | 201 | for (i = 0; i < 2; ++i) { |
michael@0 | 202 | const int quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q) |
michael@0 | 203 | : vp9_ac_quant(q, 0); |
michael@0 | 204 | invert_quant(&cpi->y_quant[q][i], &cpi->y_quant_shift[q][i], quant); |
michael@0 | 205 | cpi->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7); |
michael@0 | 206 | cpi->y_round[q][i] = (qrounding_factor * quant) >> 7; |
michael@0 | 207 | cm->y_dequant[q][i] = quant; |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | // uv |
michael@0 | 211 | for (i = 0; i < 2; ++i) { |
michael@0 | 212 | const int quant = i == 0 ? vp9_dc_quant(q, cm->uv_dc_delta_q) |
michael@0 | 213 | : vp9_ac_quant(q, cm->uv_ac_delta_q); |
michael@0 | 214 | invert_quant(&cpi->uv_quant[q][i], &cpi->uv_quant_shift[q][i], quant); |
michael@0 | 215 | cpi->uv_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7); |
michael@0 | 216 | cpi->uv_round[q][i] = (qrounding_factor * quant) >> 7; |
michael@0 | 217 | cm->uv_dequant[q][i] = quant; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | #if CONFIG_ALPHA |
michael@0 | 221 | // alpha |
michael@0 | 222 | for (i = 0; i < 2; ++i) { |
michael@0 | 223 | const int quant = i == 0 ? vp9_dc_quant(q, cm->a_dc_delta_q) |
michael@0 | 224 | : vp9_ac_quant(q, cm->a_ac_delta_q); |
michael@0 | 225 | invert_quant(&cpi->a_quant[q][i], &cpi->a_quant_shift[q][i], quant); |
michael@0 | 226 | cpi->a_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7); |
michael@0 | 227 | cpi->a_round[q][i] = (qrounding_factor * quant) >> 7; |
michael@0 | 228 | cm->a_dequant[q][i] = quant; |
michael@0 | 229 | } |
michael@0 | 230 | #endif |
michael@0 | 231 | |
michael@0 | 232 | for (i = 2; i < 8; i++) { |
michael@0 | 233 | cpi->y_quant[q][i] = cpi->y_quant[q][1]; |
michael@0 | 234 | cpi->y_quant_shift[q][i] = cpi->y_quant_shift[q][1]; |
michael@0 | 235 | cpi->y_zbin[q][i] = cpi->y_zbin[q][1]; |
michael@0 | 236 | cpi->y_round[q][i] = cpi->y_round[q][1]; |
michael@0 | 237 | cm->y_dequant[q][i] = cm->y_dequant[q][1]; |
michael@0 | 238 | |
michael@0 | 239 | cpi->uv_quant[q][i] = cpi->uv_quant[q][1]; |
michael@0 | 240 | cpi->uv_quant_shift[q][i] = cpi->uv_quant_shift[q][1]; |
michael@0 | 241 | cpi->uv_zbin[q][i] = cpi->uv_zbin[q][1]; |
michael@0 | 242 | cpi->uv_round[q][i] = cpi->uv_round[q][1]; |
michael@0 | 243 | cm->uv_dequant[q][i] = cm->uv_dequant[q][1]; |
michael@0 | 244 | |
michael@0 | 245 | #if CONFIG_ALPHA |
michael@0 | 246 | cpi->a_quant[q][i] = cpi->a_quant[q][1]; |
michael@0 | 247 | cpi->a_quant_shift[q][i] = cpi->a_quant_shift[q][1]; |
michael@0 | 248 | cpi->a_zbin[q][i] = cpi->a_zbin[q][1]; |
michael@0 | 249 | cpi->a_round[q][i] = cpi->a_round[q][1]; |
michael@0 | 250 | cm->a_dequant[q][i] = cm->a_dequant[q][1]; |
michael@0 | 251 | #endif |
michael@0 | 252 | } |
michael@0 | 253 | } |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | void vp9_mb_init_quantizer(VP9_COMP *cpi, MACROBLOCK *x) { |
michael@0 | 257 | int i; |
michael@0 | 258 | VP9_COMMON *const cm = &cpi->common; |
michael@0 | 259 | MACROBLOCKD *xd = &x->e_mbd; |
michael@0 | 260 | int zbin_extra; |
michael@0 | 261 | int segment_id = xd->mi_8x8[0]->mbmi.segment_id; |
michael@0 | 262 | const int qindex = vp9_get_qindex(&cpi->common.seg, segment_id, |
michael@0 | 263 | cpi->common.base_qindex); |
michael@0 | 264 | |
michael@0 | 265 | int rdmult = vp9_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q); |
michael@0 | 266 | |
michael@0 | 267 | // Y |
michael@0 | 268 | zbin_extra = (cpi->common.y_dequant[qindex][1] * |
michael@0 | 269 | (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7; |
michael@0 | 270 | |
michael@0 | 271 | x->plane[0].quant = cpi->y_quant[qindex]; |
michael@0 | 272 | x->plane[0].quant_shift = cpi->y_quant_shift[qindex]; |
michael@0 | 273 | x->plane[0].zbin = cpi->y_zbin[qindex]; |
michael@0 | 274 | x->plane[0].round = cpi->y_round[qindex]; |
michael@0 | 275 | x->plane[0].zbin_extra = (int16_t)zbin_extra; |
michael@0 | 276 | x->e_mbd.plane[0].dequant = cpi->common.y_dequant[qindex]; |
michael@0 | 277 | |
michael@0 | 278 | // UV |
michael@0 | 279 | zbin_extra = (cpi->common.uv_dequant[qindex][1] * |
michael@0 | 280 | (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7; |
michael@0 | 281 | |
michael@0 | 282 | for (i = 1; i < 3; i++) { |
michael@0 | 283 | x->plane[i].quant = cpi->uv_quant[qindex]; |
michael@0 | 284 | x->plane[i].quant_shift = cpi->uv_quant_shift[qindex]; |
michael@0 | 285 | x->plane[i].zbin = cpi->uv_zbin[qindex]; |
michael@0 | 286 | x->plane[i].round = cpi->uv_round[qindex]; |
michael@0 | 287 | x->plane[i].zbin_extra = (int16_t)zbin_extra; |
michael@0 | 288 | x->e_mbd.plane[i].dequant = cpi->common.uv_dequant[qindex]; |
michael@0 | 289 | } |
michael@0 | 290 | |
michael@0 | 291 | #if CONFIG_ALPHA |
michael@0 | 292 | x->plane[3].quant = cpi->a_quant[qindex]; |
michael@0 | 293 | x->plane[3].quant_shift = cpi->a_quant_shift[qindex]; |
michael@0 | 294 | x->plane[3].zbin = cpi->a_zbin[qindex]; |
michael@0 | 295 | x->plane[3].round = cpi->a_round[qindex]; |
michael@0 | 296 | x->plane[3].zbin_extra = (int16_t)zbin_extra; |
michael@0 | 297 | x->e_mbd.plane[3].dequant = cpi->common.a_dequant[qindex]; |
michael@0 | 298 | #endif |
michael@0 | 299 | |
michael@0 | 300 | x->skip_block = vp9_segfeature_active(&cpi->common.seg, segment_id, |
michael@0 | 301 | SEG_LVL_SKIP); |
michael@0 | 302 | |
michael@0 | 303 | /* save this macroblock QIndex for vp9_update_zbin_extra() */ |
michael@0 | 304 | x->q_index = qindex; |
michael@0 | 305 | |
michael@0 | 306 | /* R/D setup */ |
michael@0 | 307 | cpi->mb.errorperbit = rdmult >> 6; |
michael@0 | 308 | cpi->mb.errorperbit += (cpi->mb.errorperbit == 0); |
michael@0 | 309 | |
michael@0 | 310 | vp9_initialize_me_consts(cpi, x->q_index); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | void vp9_update_zbin_extra(VP9_COMP *cpi, MACROBLOCK *x) { |
michael@0 | 314 | const int qindex = x->q_index; |
michael@0 | 315 | const int y_zbin_extra = (cpi->common.y_dequant[qindex][1] * |
michael@0 | 316 | (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7; |
michael@0 | 317 | const int uv_zbin_extra = (cpi->common.uv_dequant[qindex][1] * |
michael@0 | 318 | (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7; |
michael@0 | 319 | |
michael@0 | 320 | x->plane[0].zbin_extra = (int16_t)y_zbin_extra; |
michael@0 | 321 | x->plane[1].zbin_extra = (int16_t)uv_zbin_extra; |
michael@0 | 322 | x->plane[2].zbin_extra = (int16_t)uv_zbin_extra; |
michael@0 | 323 | } |
michael@0 | 324 | |
michael@0 | 325 | void vp9_frame_init_quantizer(VP9_COMP *cpi) { |
michael@0 | 326 | // Clear Zbin mode boost for default case |
michael@0 | 327 | cpi->zbin_mode_boost = 0; |
michael@0 | 328 | |
michael@0 | 329 | // MB level quantizer setup |
michael@0 | 330 | vp9_mb_init_quantizer(cpi, &cpi->mb); |
michael@0 | 331 | } |
michael@0 | 332 | |
michael@0 | 333 | void vp9_set_quantizer(struct VP9_COMP *cpi, int q) { |
michael@0 | 334 | VP9_COMMON *cm = &cpi->common; |
michael@0 | 335 | |
michael@0 | 336 | cm->base_qindex = q; |
michael@0 | 337 | |
michael@0 | 338 | // if any of the delta_q values are changing update flag will |
michael@0 | 339 | // have to be set. |
michael@0 | 340 | cm->y_dc_delta_q = 0; |
michael@0 | 341 | cm->uv_dc_delta_q = 0; |
michael@0 | 342 | cm->uv_ac_delta_q = 0; |
michael@0 | 343 | |
michael@0 | 344 | // quantizer has to be reinitialized if any delta_q changes. |
michael@0 | 345 | // As there are not any here for now this is inactive code. |
michael@0 | 346 | // if(update) |
michael@0 | 347 | // vp9_init_quantizer(cpi); |
michael@0 | 348 | } |