Home | History | Annotate | Download | only in common
      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