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 | |
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_ |