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