media/libvpx/vp9/common/vp9_blockd.h

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
michael@0 12 #ifndef VP9_COMMON_VP9_BLOCKD_H_
michael@0 13 #define VP9_COMMON_VP9_BLOCKD_H_
michael@0 14
michael@0 15 #include "./vpx_config.h"
michael@0 16
michael@0 17 #include "vpx_ports/mem.h"
michael@0 18 #include "vpx_scale/yv12config.h"
michael@0 19
michael@0 20 #include "vp9/common/vp9_common.h"
michael@0 21 #include "vp9/common/vp9_common_data.h"
michael@0 22 #include "vp9/common/vp9_enums.h"
michael@0 23 #include "vp9/common/vp9_filter.h"
michael@0 24 #include "vp9/common/vp9_mv.h"
michael@0 25 #include "vp9/common/vp9_scale.h"
michael@0 26 #include "vp9/common/vp9_seg_common.h"
michael@0 27 #include "vp9/common/vp9_treecoder.h"
michael@0 28
michael@0 29 #define BLOCK_SIZE_GROUPS 4
michael@0 30 #define MBSKIP_CONTEXTS 3
michael@0 31
michael@0 32 /* Segment Feature Masks */
michael@0 33 #define MAX_MV_REF_CANDIDATES 2
michael@0 34
michael@0 35 #define INTRA_INTER_CONTEXTS 4
michael@0 36 #define COMP_INTER_CONTEXTS 5
michael@0 37 #define REF_CONTEXTS 5
michael@0 38
michael@0 39 typedef enum {
michael@0 40 PLANE_TYPE_Y_WITH_DC,
michael@0 41 PLANE_TYPE_UV,
michael@0 42 } PLANE_TYPE;
michael@0 43
michael@0 44 typedef char ENTROPY_CONTEXT;
michael@0 45
michael@0 46 typedef char PARTITION_CONTEXT;
michael@0 47
michael@0 48 static INLINE int combine_entropy_contexts(ENTROPY_CONTEXT a,
michael@0 49 ENTROPY_CONTEXT b) {
michael@0 50 return (a != 0) + (b != 0);
michael@0 51 }
michael@0 52
michael@0 53 typedef enum {
michael@0 54 KEY_FRAME = 0,
michael@0 55 INTER_FRAME = 1,
michael@0 56 FRAME_TYPES,
michael@0 57 } FRAME_TYPE;
michael@0 58
michael@0 59 typedef enum {
michael@0 60 DC_PRED, // Average of above and left pixels
michael@0 61 V_PRED, // Vertical
michael@0 62 H_PRED, // Horizontal
michael@0 63 D45_PRED, // Directional 45 deg = round(arctan(1/1) * 180/pi)
michael@0 64 D135_PRED, // Directional 135 deg = 180 - 45
michael@0 65 D117_PRED, // Directional 117 deg = 180 - 63
michael@0 66 D153_PRED, // Directional 153 deg = 180 - 27
michael@0 67 D207_PRED, // Directional 207 deg = 180 + 27
michael@0 68 D63_PRED, // Directional 63 deg = round(arctan(2/1) * 180/pi)
michael@0 69 TM_PRED, // True-motion
michael@0 70 NEARESTMV,
michael@0 71 NEARMV,
michael@0 72 ZEROMV,
michael@0 73 NEWMV,
michael@0 74 MB_MODE_COUNT
michael@0 75 } MB_PREDICTION_MODE;
michael@0 76
michael@0 77 static INLINE int is_inter_mode(MB_PREDICTION_MODE mode) {
michael@0 78 return mode >= NEARESTMV && mode <= NEWMV;
michael@0 79 }
michael@0 80
michael@0 81 #define INTRA_MODES (TM_PRED + 1)
michael@0 82
michael@0 83 #define INTER_MODES (1 + NEWMV - NEARESTMV)
michael@0 84
michael@0 85 #define INTER_OFFSET(mode) ((mode) - NEARESTMV)
michael@0 86
michael@0 87
michael@0 88 /* For keyframes, intra block modes are predicted by the (already decoded)
michael@0 89 modes for the Y blocks to the left and above us; for interframes, there
michael@0 90 is a single probability table. */
michael@0 91
michael@0 92 typedef struct {
michael@0 93 MB_PREDICTION_MODE as_mode;
michael@0 94 int_mv as_mv[2]; // first, second inter predictor motion vectors
michael@0 95 } b_mode_info;
michael@0 96
michael@0 97 typedef enum {
michael@0 98 NONE = -1,
michael@0 99 INTRA_FRAME = 0,
michael@0 100 LAST_FRAME = 1,
michael@0 101 GOLDEN_FRAME = 2,
michael@0 102 ALTREF_FRAME = 3,
michael@0 103 MAX_REF_FRAMES = 4
michael@0 104 } MV_REFERENCE_FRAME;
michael@0 105
michael@0 106 static INLINE int b_width_log2(BLOCK_SIZE sb_type) {
michael@0 107 return b_width_log2_lookup[sb_type];
michael@0 108 }
michael@0 109 static INLINE int b_height_log2(BLOCK_SIZE sb_type) {
michael@0 110 return b_height_log2_lookup[sb_type];
michael@0 111 }
michael@0 112
michael@0 113 static INLINE int mi_width_log2(BLOCK_SIZE sb_type) {
michael@0 114 return mi_width_log2_lookup[sb_type];
michael@0 115 }
michael@0 116
michael@0 117 static INLINE int mi_height_log2(BLOCK_SIZE sb_type) {
michael@0 118 return mi_height_log2_lookup[sb_type];
michael@0 119 }
michael@0 120
michael@0 121 // This structure now relates to 8x8 block regions.
michael@0 122 typedef struct {
michael@0 123 MB_PREDICTION_MODE mode, uv_mode;
michael@0 124 MV_REFERENCE_FRAME ref_frame[2];
michael@0 125 TX_SIZE tx_size;
michael@0 126 int_mv mv[2]; // for each reference frame used
michael@0 127 int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
michael@0 128 int_mv best_mv[2];
michael@0 129
michael@0 130 uint8_t mode_context[MAX_REF_FRAMES];
michael@0 131
michael@0 132 unsigned char skip_coeff; // 0=need to decode coeffs, 1=no coefficients
michael@0 133 unsigned char segment_id; // Segment id for this block.
michael@0 134
michael@0 135 // Flags used for prediction status of various bit-stream signals
michael@0 136 unsigned char seg_id_predicted;
michael@0 137
michael@0 138 INTERPOLATION_TYPE interp_filter;
michael@0 139
michael@0 140 BLOCK_SIZE sb_type;
michael@0 141 } MB_MODE_INFO;
michael@0 142
michael@0 143 typedef struct {
michael@0 144 MB_MODE_INFO mbmi;
michael@0 145 b_mode_info bmi[4];
michael@0 146 } MODE_INFO;
michael@0 147
michael@0 148 static INLINE int is_inter_block(const MB_MODE_INFO *mbmi) {
michael@0 149 return mbmi->ref_frame[0] > INTRA_FRAME;
michael@0 150 }
michael@0 151
michael@0 152 static INLINE int has_second_ref(const MB_MODE_INFO *mbmi) {
michael@0 153 return mbmi->ref_frame[1] > INTRA_FRAME;
michael@0 154 }
michael@0 155
michael@0 156 enum mv_precision {
michael@0 157 MV_PRECISION_Q3,
michael@0 158 MV_PRECISION_Q4
michael@0 159 };
michael@0 160
michael@0 161 #if CONFIG_ALPHA
michael@0 162 enum { MAX_MB_PLANE = 4 };
michael@0 163 #else
michael@0 164 enum { MAX_MB_PLANE = 3 };
michael@0 165 #endif
michael@0 166
michael@0 167 struct buf_2d {
michael@0 168 uint8_t *buf;
michael@0 169 int stride;
michael@0 170 };
michael@0 171
michael@0 172 struct macroblockd_plane {
michael@0 173 int16_t *qcoeff;
michael@0 174 int16_t *dqcoeff;
michael@0 175 uint16_t *eobs;
michael@0 176 PLANE_TYPE plane_type;
michael@0 177 int subsampling_x;
michael@0 178 int subsampling_y;
michael@0 179 struct buf_2d dst;
michael@0 180 struct buf_2d pre[2];
michael@0 181 int16_t *dequant;
michael@0 182 ENTROPY_CONTEXT *above_context;
michael@0 183 ENTROPY_CONTEXT *left_context;
michael@0 184 };
michael@0 185
michael@0 186 #define BLOCK_OFFSET(x, i) ((x) + (i) * 16)
michael@0 187
michael@0 188 typedef struct macroblockd {
michael@0 189 struct macroblockd_plane plane[MAX_MB_PLANE];
michael@0 190
michael@0 191 struct scale_factors scale_factor[2];
michael@0 192
michael@0 193 MODE_INFO *last_mi;
michael@0 194 int mode_info_stride;
michael@0 195
michael@0 196 // A NULL indicates that the 8x8 is not part of the image
michael@0 197 MODE_INFO **mi_8x8;
michael@0 198 MODE_INFO **prev_mi_8x8;
michael@0 199 MODE_INFO *mi_stream;
michael@0 200
michael@0 201 int up_available;
michael@0 202 int left_available;
michael@0 203
michael@0 204 /* Distance of MB away from frame edges */
michael@0 205 int mb_to_left_edge;
michael@0 206 int mb_to_right_edge;
michael@0 207 int mb_to_top_edge;
michael@0 208 int mb_to_bottom_edge;
michael@0 209
michael@0 210 int lossless;
michael@0 211 /* Inverse transform function pointers. */
michael@0 212 void (*itxm_add)(const int16_t *input, uint8_t *dest, int stride, int eob);
michael@0 213
michael@0 214 struct subpix_fn_table subpix;
michael@0 215
michael@0 216 int corrupted;
michael@0 217
michael@0 218 /* Y,U,V,(A) */
michael@0 219 ENTROPY_CONTEXT *above_context[MAX_MB_PLANE];
michael@0 220 ENTROPY_CONTEXT left_context[MAX_MB_PLANE][16];
michael@0 221
michael@0 222 PARTITION_CONTEXT *above_seg_context;
michael@0 223 PARTITION_CONTEXT left_seg_context[8];
michael@0 224 } MACROBLOCKD;
michael@0 225
michael@0 226
michael@0 227
michael@0 228 static BLOCK_SIZE get_subsize(BLOCK_SIZE bsize, PARTITION_TYPE partition) {
michael@0 229 const BLOCK_SIZE subsize = subsize_lookup[partition][bsize];
michael@0 230 assert(subsize < BLOCK_SIZES);
michael@0 231 return subsize;
michael@0 232 }
michael@0 233
michael@0 234 extern const TX_TYPE mode2txfm_map[MB_MODE_COUNT];
michael@0 235
michael@0 236 static INLINE TX_TYPE get_tx_type_4x4(PLANE_TYPE plane_type,
michael@0 237 const MACROBLOCKD *xd, int ib) {
michael@0 238 const MODE_INFO *const mi = xd->mi_8x8[0];
michael@0 239 const MB_MODE_INFO *const mbmi = &mi->mbmi;
michael@0 240
michael@0 241 if (plane_type != PLANE_TYPE_Y_WITH_DC ||
michael@0 242 xd->lossless ||
michael@0 243 is_inter_block(mbmi))
michael@0 244 return DCT_DCT;
michael@0 245
michael@0 246 return mode2txfm_map[mbmi->sb_type < BLOCK_8X8 ?
michael@0 247 mi->bmi[ib].as_mode : mbmi->mode];
michael@0 248 }
michael@0 249
michael@0 250 static INLINE TX_TYPE get_tx_type_8x8(PLANE_TYPE plane_type,
michael@0 251 const MACROBLOCKD *xd) {
michael@0 252 return plane_type == PLANE_TYPE_Y_WITH_DC ?
michael@0 253 mode2txfm_map[xd->mi_8x8[0]->mbmi.mode] : DCT_DCT;
michael@0 254 }
michael@0 255
michael@0 256 static INLINE TX_TYPE get_tx_type_16x16(PLANE_TYPE plane_type,
michael@0 257 const MACROBLOCKD *xd) {
michael@0 258 return plane_type == PLANE_TYPE_Y_WITH_DC ?
michael@0 259 mode2txfm_map[xd->mi_8x8[0]->mbmi.mode] : DCT_DCT;
michael@0 260 }
michael@0 261
michael@0 262 static void setup_block_dptrs(MACROBLOCKD *xd, int ss_x, int ss_y) {
michael@0 263 int i;
michael@0 264
michael@0 265 for (i = 0; i < MAX_MB_PLANE; i++) {
michael@0 266 xd->plane[i].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y_WITH_DC;
michael@0 267 xd->plane[i].subsampling_x = i ? ss_x : 0;
michael@0 268 xd->plane[i].subsampling_y = i ? ss_y : 0;
michael@0 269 }
michael@0 270 #if CONFIG_ALPHA
michael@0 271 // TODO(jkoleszar): Using the Y w/h for now
michael@0 272 xd->plane[3].subsampling_x = 0;
michael@0 273 xd->plane[3].subsampling_y = 0;
michael@0 274 #endif
michael@0 275 }
michael@0 276
michael@0 277
michael@0 278 static INLINE TX_SIZE get_uv_tx_size(const MB_MODE_INFO *mbmi) {
michael@0 279 return MIN(mbmi->tx_size, max_uv_txsize_lookup[mbmi->sb_type]);
michael@0 280 }
michael@0 281
michael@0 282 static BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
michael@0 283 const struct macroblockd_plane *pd) {
michael@0 284 BLOCK_SIZE bs = ss_size_lookup[bsize][pd->subsampling_x][pd->subsampling_y];
michael@0 285 assert(bs < BLOCK_SIZES);
michael@0 286 return bs;
michael@0 287 }
michael@0 288
michael@0 289 static INLINE int plane_block_width(BLOCK_SIZE bsize,
michael@0 290 const struct macroblockd_plane* plane) {
michael@0 291 return 4 << (b_width_log2(bsize) - plane->subsampling_x);
michael@0 292 }
michael@0 293
michael@0 294 static INLINE int plane_block_height(BLOCK_SIZE bsize,
michael@0 295 const struct macroblockd_plane* plane) {
michael@0 296 return 4 << (b_height_log2(bsize) - plane->subsampling_y);
michael@0 297 }
michael@0 298
michael@0 299 typedef void (*foreach_transformed_block_visitor)(int plane, int block,
michael@0 300 BLOCK_SIZE plane_bsize,
michael@0 301 TX_SIZE tx_size,
michael@0 302 void *arg);
michael@0 303
michael@0 304 static INLINE void foreach_transformed_block_in_plane(
michael@0 305 const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
michael@0 306 foreach_transformed_block_visitor visit, void *arg) {
michael@0 307 const struct macroblockd_plane *const pd = &xd->plane[plane];
michael@0 308 const MB_MODE_INFO* mbmi = &xd->mi_8x8[0]->mbmi;
michael@0 309 // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
michael@0 310 // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
michael@0 311 // transform size varies per plane, look it up in a common way.
michael@0 312 const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi)
michael@0 313 : mbmi->tx_size;
michael@0 314 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
michael@0 315 const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
michael@0 316 const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
michael@0 317 const int step = 1 << (tx_size << 1);
michael@0 318 int i;
michael@0 319
michael@0 320 // If mb_to_right_edge is < 0 we are in a situation in which
michael@0 321 // the current block size extends into the UMV and we won't
michael@0 322 // visit the sub blocks that are wholly within the UMV.
michael@0 323 if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
michael@0 324 int r, c;
michael@0 325
michael@0 326 int max_blocks_wide = num_4x4_w;
michael@0 327 int max_blocks_high = num_4x4_h;
michael@0 328
michael@0 329 // xd->mb_to_right_edge is in units of pixels * 8. This converts
michael@0 330 // it to 4x4 block sizes.
michael@0 331 if (xd->mb_to_right_edge < 0)
michael@0 332 max_blocks_wide += (xd->mb_to_right_edge >> (5 + pd->subsampling_x));
michael@0 333
michael@0 334 if (xd->mb_to_bottom_edge < 0)
michael@0 335 max_blocks_high += (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
michael@0 336
michael@0 337 i = 0;
michael@0 338 // Unlike the normal case - in here we have to keep track of the
michael@0 339 // row and column of the blocks we use so that we know if we are in
michael@0 340 // the unrestricted motion border.
michael@0 341 for (r = 0; r < num_4x4_h; r += (1 << tx_size)) {
michael@0 342 for (c = 0; c < num_4x4_w; c += (1 << tx_size)) {
michael@0 343 if (r < max_blocks_high && c < max_blocks_wide)
michael@0 344 visit(plane, i, plane_bsize, tx_size, arg);
michael@0 345 i += step;
michael@0 346 }
michael@0 347 }
michael@0 348 } else {
michael@0 349 for (i = 0; i < num_4x4_w * num_4x4_h; i += step)
michael@0 350 visit(plane, i, plane_bsize, tx_size, arg);
michael@0 351 }
michael@0 352 }
michael@0 353
michael@0 354 static INLINE void foreach_transformed_block(
michael@0 355 const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
michael@0 356 foreach_transformed_block_visitor visit, void *arg) {
michael@0 357 int plane;
michael@0 358
michael@0 359 for (plane = 0; plane < MAX_MB_PLANE; plane++)
michael@0 360 foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
michael@0 361 }
michael@0 362
michael@0 363 static INLINE void foreach_transformed_block_uv(
michael@0 364 const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
michael@0 365 foreach_transformed_block_visitor visit, void *arg) {
michael@0 366 int plane;
michael@0 367
michael@0 368 for (plane = 1; plane < MAX_MB_PLANE; plane++)
michael@0 369 foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
michael@0 370 }
michael@0 371
michael@0 372 static int raster_block_offset(BLOCK_SIZE plane_bsize,
michael@0 373 int raster_block, int stride) {
michael@0 374 const int bw = b_width_log2(plane_bsize);
michael@0 375 const int y = 4 * (raster_block >> bw);
michael@0 376 const int x = 4 * (raster_block & ((1 << bw) - 1));
michael@0 377 return y * stride + x;
michael@0 378 }
michael@0 379 static int16_t* raster_block_offset_int16(BLOCK_SIZE plane_bsize,
michael@0 380 int raster_block, int16_t *base) {
michael@0 381 const int stride = 4 << b_width_log2(plane_bsize);
michael@0 382 return base + raster_block_offset(plane_bsize, raster_block, stride);
michael@0 383 }
michael@0 384 static uint8_t* raster_block_offset_uint8(BLOCK_SIZE plane_bsize,
michael@0 385 int raster_block, uint8_t *base,
michael@0 386 int stride) {
michael@0 387 return base + raster_block_offset(plane_bsize, raster_block, stride);
michael@0 388 }
michael@0 389
michael@0 390 static int txfrm_block_to_raster_block(BLOCK_SIZE plane_bsize,
michael@0 391 TX_SIZE tx_size, int block) {
michael@0 392 const int bwl = b_width_log2(plane_bsize);
michael@0 393 const int tx_cols_log2 = bwl - tx_size;
michael@0 394 const int tx_cols = 1 << tx_cols_log2;
michael@0 395 const int raster_mb = block >> (tx_size << 1);
michael@0 396 const int x = (raster_mb & (tx_cols - 1)) << tx_size;
michael@0 397 const int y = (raster_mb >> tx_cols_log2) << tx_size;
michael@0 398 return x + (y << bwl);
michael@0 399 }
michael@0 400
michael@0 401 static void txfrm_block_to_raster_xy(BLOCK_SIZE plane_bsize,
michael@0 402 TX_SIZE tx_size, int block,
michael@0 403 int *x, int *y) {
michael@0 404 const int bwl = b_width_log2(plane_bsize);
michael@0 405 const int tx_cols_log2 = bwl - tx_size;
michael@0 406 const int tx_cols = 1 << tx_cols_log2;
michael@0 407 const int raster_mb = block >> (tx_size << 1);
michael@0 408 *x = (raster_mb & (tx_cols - 1)) << tx_size;
michael@0 409 *y = (raster_mb >> tx_cols_log2) << tx_size;
michael@0 410 }
michael@0 411
michael@0 412 static void extend_for_intra(MACROBLOCKD *xd, BLOCK_SIZE plane_bsize,
michael@0 413 int plane, int block, TX_SIZE tx_size) {
michael@0 414 struct macroblockd_plane *const pd = &xd->plane[plane];
michael@0 415 uint8_t *const buf = pd->dst.buf;
michael@0 416 const int stride = pd->dst.stride;
michael@0 417
michael@0 418 int x, y;
michael@0 419 txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
michael@0 420 x = x * 4 - 1;
michael@0 421 y = y * 4 - 1;
michael@0 422 // Copy a pixel into the umv if we are in a situation where the block size
michael@0 423 // extends into the UMV.
michael@0 424 // TODO(JBB): Should be able to do the full extend in place so we don't have
michael@0 425 // to do this multiple times.
michael@0 426 if (xd->mb_to_right_edge < 0) {
michael@0 427 const int bw = 4 << b_width_log2(plane_bsize);
michael@0 428 const int umv_border_start = bw + (xd->mb_to_right_edge >>
michael@0 429 (3 + pd->subsampling_x));
michael@0 430
michael@0 431 if (x + bw > umv_border_start)
michael@0 432 vpx_memset(&buf[y * stride + umv_border_start],
michael@0 433 buf[y * stride + umv_border_start - 1], bw);
michael@0 434 }
michael@0 435
michael@0 436 if (xd->mb_to_bottom_edge < 0) {
michael@0 437 if (xd->left_available || x >= 0) {
michael@0 438 const int bh = 4 << b_height_log2(plane_bsize);
michael@0 439 const int umv_border_start =
michael@0 440 bh + (xd->mb_to_bottom_edge >> (3 + pd->subsampling_y));
michael@0 441
michael@0 442 if (y + bh > umv_border_start) {
michael@0 443 const uint8_t c = buf[(umv_border_start - 1) * stride + x];
michael@0 444 uint8_t *d = &buf[umv_border_start * stride + x];
michael@0 445 int i;
michael@0 446 for (i = 0; i < bh; ++i, d += stride)
michael@0 447 *d = c;
michael@0 448 }
michael@0 449 }
michael@0 450 }
michael@0 451 }
michael@0 452
michael@0 453 static void set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
michael@0 454 BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
michael@0 455 int has_eob, int aoff, int loff) {
michael@0 456 ENTROPY_CONTEXT *const a = pd->above_context + aoff;
michael@0 457 ENTROPY_CONTEXT *const l = pd->left_context + loff;
michael@0 458 const int tx_size_in_blocks = 1 << tx_size;
michael@0 459
michael@0 460 // above
michael@0 461 if (has_eob && xd->mb_to_right_edge < 0) {
michael@0 462 int i;
michael@0 463 const int blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize] +
michael@0 464 (xd->mb_to_right_edge >> (5 + pd->subsampling_x));
michael@0 465 int above_contexts = tx_size_in_blocks;
michael@0 466 if (above_contexts + aoff > blocks_wide)
michael@0 467 above_contexts = blocks_wide - aoff;
michael@0 468
michael@0 469 for (i = 0; i < above_contexts; ++i)
michael@0 470 a[i] = has_eob;
michael@0 471 for (i = above_contexts; i < tx_size_in_blocks; ++i)
michael@0 472 a[i] = 0;
michael@0 473 } else {
michael@0 474 vpx_memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
michael@0 475 }
michael@0 476
michael@0 477 // left
michael@0 478 if (has_eob && xd->mb_to_bottom_edge < 0) {
michael@0 479 int i;
michael@0 480 const int blocks_high = num_4x4_blocks_high_lookup[plane_bsize] +
michael@0 481 (xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
michael@0 482 int left_contexts = tx_size_in_blocks;
michael@0 483 if (left_contexts + loff > blocks_high)
michael@0 484 left_contexts = blocks_high - loff;
michael@0 485
michael@0 486 for (i = 0; i < left_contexts; ++i)
michael@0 487 l[i] = has_eob;
michael@0 488 for (i = left_contexts; i < tx_size_in_blocks; ++i)
michael@0 489 l[i] = 0;
michael@0 490 } else {
michael@0 491 vpx_memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
michael@0 492 }
michael@0 493 }
michael@0 494
michael@0 495 static int get_tx_eob(const struct segmentation *seg, int segment_id,
michael@0 496 TX_SIZE tx_size) {
michael@0 497 const int eob_max = 16 << (tx_size << 1);
michael@0 498 return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
michael@0 499 }
michael@0 500
michael@0 501 #endif // VP9_COMMON_VP9_BLOCKD_H_

mercurial