media/libvpx/vp9/encoder/vp9_encodemv.c

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

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
michael@0 13 #include "vp9/common/vp9_common.h"
michael@0 14 #include "vp9/common/vp9_entropymode.h"
michael@0 15 #include "vp9/common/vp9_systemdependent.h"
michael@0 16 #include "vp9/encoder/vp9_encodemv.h"
michael@0 17
michael@0 18
michael@0 19 #ifdef ENTROPY_STATS
michael@0 20 extern unsigned int active_section;
michael@0 21 #endif
michael@0 22
michael@0 23 static void encode_mv_component(vp9_writer* w, int comp,
michael@0 24 const nmv_component* mvcomp, int usehp) {
michael@0 25 int offset;
michael@0 26 const int sign = comp < 0;
michael@0 27 const int mag = sign ? -comp : comp;
michael@0 28 const int mv_class = vp9_get_mv_class(mag - 1, &offset);
michael@0 29 const int d = offset >> 3; // int mv data
michael@0 30 const int fr = (offset >> 1) & 3; // fractional mv data
michael@0 31 const int hp = offset & 1; // high precision mv data
michael@0 32
michael@0 33 assert(comp != 0);
michael@0 34
michael@0 35 // Sign
michael@0 36 vp9_write(w, sign, mvcomp->sign);
michael@0 37
michael@0 38 // Class
michael@0 39 write_token(w, vp9_mv_class_tree, mvcomp->classes,
michael@0 40 &vp9_mv_class_encodings[mv_class]);
michael@0 41
michael@0 42 // Integer bits
michael@0 43 if (mv_class == MV_CLASS_0) {
michael@0 44 write_token(w, vp9_mv_class0_tree, mvcomp->class0,
michael@0 45 &vp9_mv_class0_encodings[d]);
michael@0 46 } else {
michael@0 47 int i;
michael@0 48 const int n = mv_class + CLASS0_BITS - 1; // number of bits
michael@0 49 for (i = 0; i < n; ++i)
michael@0 50 vp9_write(w, (d >> i) & 1, mvcomp->bits[i]);
michael@0 51 }
michael@0 52
michael@0 53 // Fractional bits
michael@0 54 write_token(w, vp9_mv_fp_tree,
michael@0 55 mv_class == MV_CLASS_0 ? mvcomp->class0_fp[d] : mvcomp->fp,
michael@0 56 &vp9_mv_fp_encodings[fr]);
michael@0 57
michael@0 58 // High precision bit
michael@0 59 if (usehp)
michael@0 60 vp9_write(w, hp,
michael@0 61 mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp);
michael@0 62 }
michael@0 63
michael@0 64
michael@0 65 static void build_nmv_component_cost_table(int *mvcost,
michael@0 66 const nmv_component* const mvcomp,
michael@0 67 int usehp) {
michael@0 68 int i, v;
michael@0 69 int sign_cost[2], class_cost[MV_CLASSES], class0_cost[CLASS0_SIZE];
michael@0 70 int bits_cost[MV_OFFSET_BITS][2];
michael@0 71 int class0_fp_cost[CLASS0_SIZE][4], fp_cost[4];
michael@0 72 int class0_hp_cost[2], hp_cost[2];
michael@0 73
michael@0 74 sign_cost[0] = vp9_cost_zero(mvcomp->sign);
michael@0 75 sign_cost[1] = vp9_cost_one(mvcomp->sign);
michael@0 76 vp9_cost_tokens(class_cost, mvcomp->classes, vp9_mv_class_tree);
michael@0 77 vp9_cost_tokens(class0_cost, mvcomp->class0, vp9_mv_class0_tree);
michael@0 78 for (i = 0; i < MV_OFFSET_BITS; ++i) {
michael@0 79 bits_cost[i][0] = vp9_cost_zero(mvcomp->bits[i]);
michael@0 80 bits_cost[i][1] = vp9_cost_one(mvcomp->bits[i]);
michael@0 81 }
michael@0 82
michael@0 83 for (i = 0; i < CLASS0_SIZE; ++i)
michael@0 84 vp9_cost_tokens(class0_fp_cost[i], mvcomp->class0_fp[i], vp9_mv_fp_tree);
michael@0 85 vp9_cost_tokens(fp_cost, mvcomp->fp, vp9_mv_fp_tree);
michael@0 86
michael@0 87 if (usehp) {
michael@0 88 class0_hp_cost[0] = vp9_cost_zero(mvcomp->class0_hp);
michael@0 89 class0_hp_cost[1] = vp9_cost_one(mvcomp->class0_hp);
michael@0 90 hp_cost[0] = vp9_cost_zero(mvcomp->hp);
michael@0 91 hp_cost[1] = vp9_cost_one(mvcomp->hp);
michael@0 92 }
michael@0 93 mvcost[0] = 0;
michael@0 94 for (v = 1; v <= MV_MAX; ++v) {
michael@0 95 int z, c, o, d, e, f, cost = 0;
michael@0 96 z = v - 1;
michael@0 97 c = vp9_get_mv_class(z, &o);
michael@0 98 cost += class_cost[c];
michael@0 99 d = (o >> 3); /* int mv data */
michael@0 100 f = (o >> 1) & 3; /* fractional pel mv data */
michael@0 101 e = (o & 1); /* high precision mv data */
michael@0 102 if (c == MV_CLASS_0) {
michael@0 103 cost += class0_cost[d];
michael@0 104 } else {
michael@0 105 int i, b;
michael@0 106 b = c + CLASS0_BITS - 1; /* number of bits */
michael@0 107 for (i = 0; i < b; ++i)
michael@0 108 cost += bits_cost[i][((d >> i) & 1)];
michael@0 109 }
michael@0 110 if (c == MV_CLASS_0) {
michael@0 111 cost += class0_fp_cost[d][f];
michael@0 112 } else {
michael@0 113 cost += fp_cost[f];
michael@0 114 }
michael@0 115 if (usehp) {
michael@0 116 if (c == MV_CLASS_0) {
michael@0 117 cost += class0_hp_cost[e];
michael@0 118 } else {
michael@0 119 cost += hp_cost[e];
michael@0 120 }
michael@0 121 }
michael@0 122 mvcost[v] = cost + sign_cost[0];
michael@0 123 mvcost[-v] = cost + sign_cost[1];
michael@0 124 }
michael@0 125 }
michael@0 126
michael@0 127 static int update_mv(vp9_writer *w, const unsigned int ct[2], vp9_prob *cur_p,
michael@0 128 vp9_prob upd_p) {
michael@0 129 const vp9_prob new_p = get_binary_prob(ct[0], ct[1]);
michael@0 130 vp9_prob mod_p = new_p | 1;
michael@0 131 const int cur_b = cost_branch256(ct, *cur_p);
michael@0 132 const int mod_b = cost_branch256(ct, mod_p);
michael@0 133 const int cost = 7 * 256 + (vp9_cost_one(upd_p) - vp9_cost_zero(upd_p));
michael@0 134 if (cur_b - mod_b > cost) {
michael@0 135 *cur_p = mod_p;
michael@0 136 vp9_write(w, 1, upd_p);
michael@0 137 vp9_write_literal(w, mod_p >> 1, 7);
michael@0 138 return 1;
michael@0 139 } else {
michael@0 140 vp9_write(w, 0, upd_p);
michael@0 141 return 0;
michael@0 142 }
michael@0 143 }
michael@0 144
michael@0 145 static void counts_to_nmv_context(
michael@0 146 nmv_context_counts *nmv_count,
michael@0 147 int usehp,
michael@0 148 unsigned int (*branch_ct_joint)[2],
michael@0 149 unsigned int (*branch_ct_sign)[2],
michael@0 150 unsigned int (*branch_ct_classes)[MV_CLASSES - 1][2],
michael@0 151 unsigned int (*branch_ct_class0)[CLASS0_SIZE - 1][2],
michael@0 152 unsigned int (*branch_ct_bits)[MV_OFFSET_BITS][2],
michael@0 153 unsigned int (*branch_ct_class0_fp)[CLASS0_SIZE][4 - 1][2],
michael@0 154 unsigned int (*branch_ct_fp)[4 - 1][2],
michael@0 155 unsigned int (*branch_ct_class0_hp)[2],
michael@0 156 unsigned int (*branch_ct_hp)[2]) {
michael@0 157 int i, j, k;
michael@0 158 vp9_tree_probs_from_distribution(vp9_mv_joint_tree, branch_ct_joint,
michael@0 159 nmv_count->joints);
michael@0 160 for (i = 0; i < 2; ++i) {
michael@0 161 const uint32_t s0 = nmv_count->comps[i].sign[0];
michael@0 162 const uint32_t s1 = nmv_count->comps[i].sign[1];
michael@0 163
michael@0 164 branch_ct_sign[i][0] = s0;
michael@0 165 branch_ct_sign[i][1] = s1;
michael@0 166 vp9_tree_probs_from_distribution(vp9_mv_class_tree,
michael@0 167 branch_ct_classes[i],
michael@0 168 nmv_count->comps[i].classes);
michael@0 169 vp9_tree_probs_from_distribution(vp9_mv_class0_tree,
michael@0 170 branch_ct_class0[i],
michael@0 171 nmv_count->comps[i].class0);
michael@0 172 for (j = 0; j < MV_OFFSET_BITS; ++j) {
michael@0 173 const uint32_t b0 = nmv_count->comps[i].bits[j][0];
michael@0 174 const uint32_t b1 = nmv_count->comps[i].bits[j][1];
michael@0 175
michael@0 176 branch_ct_bits[i][j][0] = b0;
michael@0 177 branch_ct_bits[i][j][1] = b1;
michael@0 178 }
michael@0 179 }
michael@0 180 for (i = 0; i < 2; ++i) {
michael@0 181 for (k = 0; k < CLASS0_SIZE; ++k) {
michael@0 182 vp9_tree_probs_from_distribution(vp9_mv_fp_tree,
michael@0 183 branch_ct_class0_fp[i][k],
michael@0 184 nmv_count->comps[i].class0_fp[k]);
michael@0 185 }
michael@0 186 vp9_tree_probs_from_distribution(vp9_mv_fp_tree,
michael@0 187 branch_ct_fp[i],
michael@0 188 nmv_count->comps[i].fp);
michael@0 189 }
michael@0 190 if (usehp) {
michael@0 191 for (i = 0; i < 2; ++i) {
michael@0 192 const uint32_t c0_hp0 = nmv_count->comps[i].class0_hp[0];
michael@0 193 const uint32_t c0_hp1 = nmv_count->comps[i].class0_hp[1];
michael@0 194 const uint32_t hp0 = nmv_count->comps[i].hp[0];
michael@0 195 const uint32_t hp1 = nmv_count->comps[i].hp[1];
michael@0 196
michael@0 197 branch_ct_class0_hp[i][0] = c0_hp0;
michael@0 198 branch_ct_class0_hp[i][1] = c0_hp1;
michael@0 199
michael@0 200 branch_ct_hp[i][0] = hp0;
michael@0 201 branch_ct_hp[i][1] = hp1;
michael@0 202 }
michael@0 203 }
michael@0 204 }
michael@0 205
michael@0 206 void vp9_write_nmv_probs(VP9_COMP* const cpi, int usehp, vp9_writer* const bc) {
michael@0 207 int i, j;
michael@0 208 unsigned int branch_ct_joint[MV_JOINTS - 1][2];
michael@0 209 unsigned int branch_ct_sign[2][2];
michael@0 210 unsigned int branch_ct_classes[2][MV_CLASSES - 1][2];
michael@0 211 unsigned int branch_ct_class0[2][CLASS0_SIZE - 1][2];
michael@0 212 unsigned int branch_ct_bits[2][MV_OFFSET_BITS][2];
michael@0 213 unsigned int branch_ct_class0_fp[2][CLASS0_SIZE][4 - 1][2];
michael@0 214 unsigned int branch_ct_fp[2][4 - 1][2];
michael@0 215 unsigned int branch_ct_class0_hp[2][2];
michael@0 216 unsigned int branch_ct_hp[2][2];
michael@0 217 nmv_context *mvc = &cpi->common.fc.nmvc;
michael@0 218
michael@0 219 counts_to_nmv_context(&cpi->NMVcount, usehp,
michael@0 220 branch_ct_joint, branch_ct_sign, branch_ct_classes,
michael@0 221 branch_ct_class0, branch_ct_bits,
michael@0 222 branch_ct_class0_fp, branch_ct_fp,
michael@0 223 branch_ct_class0_hp, branch_ct_hp);
michael@0 224
michael@0 225 for (j = 0; j < MV_JOINTS - 1; ++j)
michael@0 226 update_mv(bc, branch_ct_joint[j], &mvc->joints[j], NMV_UPDATE_PROB);
michael@0 227
michael@0 228 for (i = 0; i < 2; ++i) {
michael@0 229 update_mv(bc, branch_ct_sign[i], &mvc->comps[i].sign, NMV_UPDATE_PROB);
michael@0 230 for (j = 0; j < MV_CLASSES - 1; ++j)
michael@0 231 update_mv(bc, branch_ct_classes[i][j], &mvc->comps[i].classes[j],
michael@0 232 NMV_UPDATE_PROB);
michael@0 233
michael@0 234 for (j = 0; j < CLASS0_SIZE - 1; ++j)
michael@0 235 update_mv(bc, branch_ct_class0[i][j], &mvc->comps[i].class0[j],
michael@0 236 NMV_UPDATE_PROB);
michael@0 237
michael@0 238 for (j = 0; j < MV_OFFSET_BITS; ++j)
michael@0 239 update_mv(bc, branch_ct_bits[i][j], &mvc->comps[i].bits[j],
michael@0 240 NMV_UPDATE_PROB);
michael@0 241 }
michael@0 242
michael@0 243 for (i = 0; i < 2; ++i) {
michael@0 244 for (j = 0; j < CLASS0_SIZE; ++j) {
michael@0 245 int k;
michael@0 246 for (k = 0; k < 3; ++k)
michael@0 247 update_mv(bc, branch_ct_class0_fp[i][j][k],
michael@0 248 &mvc->comps[i].class0_fp[j][k], NMV_UPDATE_PROB);
michael@0 249 }
michael@0 250
michael@0 251 for (j = 0; j < 3; ++j)
michael@0 252 update_mv(bc, branch_ct_fp[i][j], &mvc->comps[i].fp[j], NMV_UPDATE_PROB);
michael@0 253 }
michael@0 254
michael@0 255 if (usehp) {
michael@0 256 for (i = 0; i < 2; ++i) {
michael@0 257 update_mv(bc, branch_ct_class0_hp[i], &mvc->comps[i].class0_hp,
michael@0 258 NMV_UPDATE_PROB);
michael@0 259 update_mv(bc, branch_ct_hp[i], &mvc->comps[i].hp,
michael@0 260 NMV_UPDATE_PROB);
michael@0 261 }
michael@0 262 }
michael@0 263 }
michael@0 264
michael@0 265 void vp9_encode_mv(VP9_COMP* cpi, vp9_writer* w,
michael@0 266 const MV* mv, const MV* ref,
michael@0 267 const nmv_context* mvctx, int usehp) {
michael@0 268 const MV diff = {mv->row - ref->row,
michael@0 269 mv->col - ref->col};
michael@0 270 const MV_JOINT_TYPE j = vp9_get_mv_joint(&diff);
michael@0 271 usehp = usehp && vp9_use_mv_hp(ref);
michael@0 272
michael@0 273 write_token(w, vp9_mv_joint_tree, mvctx->joints, &vp9_mv_joint_encodings[j]);
michael@0 274 if (mv_joint_vertical(j))
michael@0 275 encode_mv_component(w, diff.row, &mvctx->comps[0], usehp);
michael@0 276
michael@0 277 if (mv_joint_horizontal(j))
michael@0 278 encode_mv_component(w, diff.col, &mvctx->comps[1], usehp);
michael@0 279
michael@0 280 // If auto_mv_step_size is enabled then keep track of the largest
michael@0 281 // motion vector component used.
michael@0 282 if (!cpi->dummy_packing && cpi->sf.auto_mv_step_size) {
michael@0 283 unsigned int maxv = MAX(abs(mv->row), abs(mv->col)) >> 3;
michael@0 284 cpi->max_mv_magnitude = MAX(maxv, cpi->max_mv_magnitude);
michael@0 285 }
michael@0 286 }
michael@0 287
michael@0 288 void vp9_build_nmv_cost_table(int *mvjoint,
michael@0 289 int *mvcost[2],
michael@0 290 const nmv_context* const mvctx,
michael@0 291 int usehp,
michael@0 292 int mvc_flag_v,
michael@0 293 int mvc_flag_h) {
michael@0 294 vp9_clear_system_state();
michael@0 295 vp9_cost_tokens(mvjoint, mvctx->joints, vp9_mv_joint_tree);
michael@0 296 if (mvc_flag_v)
michael@0 297 build_nmv_component_cost_table(mvcost[0], &mvctx->comps[0], usehp);
michael@0 298 if (mvc_flag_h)
michael@0 299 build_nmv_component_cost_table(mvcost[1], &mvctx->comps[1], usehp);
michael@0 300 }
michael@0 301
michael@0 302 static void inc_mvs(int_mv mv[2], int_mv ref[2], int is_compound,
michael@0 303 nmv_context_counts *counts) {
michael@0 304 int i;
michael@0 305 for (i = 0; i < 1 + is_compound; ++i) {
michael@0 306 const MV diff = { mv[i].as_mv.row - ref[i].as_mv.row,
michael@0 307 mv[i].as_mv.col - ref[i].as_mv.col };
michael@0 308 vp9_inc_mv(&diff, counts);
michael@0 309 }
michael@0 310 }
michael@0 311
michael@0 312 void vp9_update_mv_count(VP9_COMP *cpi, MACROBLOCK *x, int_mv best_ref_mv[2]) {
michael@0 313 MODE_INFO *mi = x->e_mbd.mi_8x8[0];
michael@0 314 MB_MODE_INFO *const mbmi = &mi->mbmi;
michael@0 315 const int is_compound = has_second_ref(mbmi);
michael@0 316
michael@0 317 if (mbmi->sb_type < BLOCK_8X8) {
michael@0 318 const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type];
michael@0 319 const int num_4x4_h = num_4x4_blocks_high_lookup[mbmi->sb_type];
michael@0 320 int idx, idy;
michael@0 321
michael@0 322 for (idy = 0; idy < 2; idy += num_4x4_h) {
michael@0 323 for (idx = 0; idx < 2; idx += num_4x4_w) {
michael@0 324 const int i = idy * 2 + idx;
michael@0 325 if (mi->bmi[i].as_mode == NEWMV)
michael@0 326 inc_mvs(mi->bmi[i].as_mv, best_ref_mv, is_compound, &cpi->NMVcount);
michael@0 327 }
michael@0 328 }
michael@0 329 } else if (mbmi->mode == NEWMV) {
michael@0 330 inc_mvs(mbmi->mv, best_ref_mv, is_compound, &cpi->NMVcount);
michael@0 331 }
michael@0 332 }

mercurial