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 #include <assert.h>
     12 
     13 #include "./vpx_scale_rtcd.h"
     14 #include "./vpx_config.h"
     15 
     16 #include "vpx/vpx_integer.h"
     17 
     18 #include "vp9/common/vp9_blockd.h"
     19 #include "vp9/common/vp9_filter.h"
     20 #include "vp9/common/vp9_reconinter.h"
     21 #include "vp9/common/vp9_reconintra.h"
     22 
     23 void vp9_setup_interp_filters(MACROBLOCKD *xd,
     24                               INTERPOLATION_TYPE mcomp_filter_type,
     25                               VP9_COMMON *cm) {
     26   if (xd->mi_8x8 && xd->mi_8x8[0]) {
     27     MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
     28 
     29     set_scale_factors(xd, mbmi->ref_frame[0] - LAST_FRAME,
     30                           mbmi->ref_frame[1] - LAST_FRAME,
     31                           cm->active_ref_scale);
     32   } else {
     33     set_scale_factors(xd, -1, -1, cm->active_ref_scale);
     34   }
     35 
     36   xd->subpix.filter_x = xd->subpix.filter_y =
     37       vp9_get_filter_kernel(mcomp_filter_type == SWITCHABLE ?
     38                                EIGHTTAP : mcomp_filter_type);
     39 
     40   assert(((intptr_t)xd->subpix.filter_x & 0xff) == 0);
     41 }
     42 
     43 static void inter_predictor(const uint8_t *src, int src_stride,
     44                             uint8_t *dst, int dst_stride,
     45                             const MV32 *mv,
     46                             const struct scale_factors *scale,
     47                             int w, int h, int ref,
     48                             const struct subpix_fn_table *subpix,
     49                             int xs, int ys) {
     50   const int subpel_x = mv->col & SUBPEL_MASK;
     51   const int subpel_y = mv->row & SUBPEL_MASK;
     52 
     53   src += (mv->row >> SUBPEL_BITS) * src_stride + (mv->col >> SUBPEL_BITS);
     54   scale->sfc->predict[subpel_x != 0][subpel_y != 0][ref](
     55       src, src_stride, dst, dst_stride,
     56       subpix->filter_x[subpel_x], xs,
     57       subpix->filter_y[subpel_y], ys,
     58       w, h);
     59 }
     60 
     61 void vp9_build_inter_predictor(const uint8_t *src, int src_stride,
     62                                uint8_t *dst, int dst_stride,
     63                                const MV *src_mv,
     64                                const struct scale_factors *scale,
     65                                int w, int h, int ref,
     66                                const struct subpix_fn_table *subpix,
     67                                enum mv_precision precision) {
     68   const int is_q4 = precision == MV_PRECISION_Q4;
     69   const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
     70                      is_q4 ? src_mv->col : src_mv->col * 2 };
     71   const struct scale_factors_common *sfc = scale->sfc;
     72   const MV32 mv = sfc->scale_mv(&mv_q4, scale);
     73 
     74   inter_predictor(src, src_stride, dst, dst_stride, &mv, scale,
     75                   w, h, ref, subpix, sfc->x_step_q4, sfc->y_step_q4);
     76 }
     77 
     78 static INLINE int round_mv_comp_q4(int value) {
     79   return (value < 0 ? value - 2 : value + 2) / 4;
     80 }
     81 
     82 static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) {
     83   MV res = { round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.row +
     84                               mi->bmi[1].as_mv[idx].as_mv.row +
     85                               mi->bmi[2].as_mv[idx].as_mv.row +
     86                               mi->bmi[3].as_mv[idx].as_mv.row),
     87              round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.col +
     88                               mi->bmi[1].as_mv[idx].as_mv.col +
     89                               mi->bmi[2].as_mv[idx].as_mv.col +
     90                               mi->bmi[3].as_mv[idx].as_mv.col) };
     91   return res;
     92 }
     93 
     94 // TODO(jkoleszar): yet another mv clamping function :-(
     95 MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv,
     96                              int bw, int bh, int ss_x, int ss_y) {
     97   // If the MV points so far into the UMV border that no visible pixels
     98   // are used for reconstruction, the subpel part of the MV can be
     99   // discarded and the MV limited to 16 pixels with equivalent results.
    100   const int spel_left = (VP9_INTERP_EXTEND + bw) << SUBPEL_BITS;
    101   const int spel_right = spel_left - SUBPEL_SHIFTS;
    102   const int spel_top = (VP9_INTERP_EXTEND + bh) << SUBPEL_BITS;
    103   const int spel_bottom = spel_top - SUBPEL_SHIFTS;
    104   MV clamped_mv = {
    105     src_mv->row * (1 << (1 - ss_y)),
    106     src_mv->col * (1 << (1 - ss_x))
    107   };
    108   assert(ss_x <= 1);
    109   assert(ss_y <= 1);
    110 
    111   clamp_mv(&clamped_mv,
    112            xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left,
    113            xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right,
    114            xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top,
    115            xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom);
    116 
    117   return clamped_mv;
    118 }
    119 
    120 
    121 // TODO(jkoleszar): In principle, pred_w, pred_h are unnecessary, as we could
    122 // calculate the subsampled BLOCK_SIZE, but that type isn't defined for
    123 // sizes smaller than 16x16 yet.
    124 static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
    125                                    BLOCK_SIZE bsize, int pred_w, int pred_h,
    126                                    int mi_x, int mi_y) {
    127   struct macroblockd_plane *const pd = &xd->plane[plane];
    128   const int bwl = b_width_log2(bsize) - pd->subsampling_x;
    129   const int bw = 4 << bwl;
    130   const int bh = plane_block_height(bsize, pd);
    131   const int x = 4 * (block & ((1 << bwl) - 1));
    132   const int y = 4 * (block >> bwl);
    133   const MODE_INFO *mi = xd->mi_8x8[0];
    134   const int is_compound = has_second_ref(&mi->mbmi);
    135   int ref;
    136 
    137   assert(x < bw);
    138   assert(y < bh);
    139   assert(mi->mbmi.sb_type < BLOCK_8X8 || 4 << pred_w == bw);
    140   assert(mi->mbmi.sb_type < BLOCK_8X8 || 4 << pred_h == bh);
    141 
    142   for (ref = 0; ref < 1 + is_compound; ++ref) {
    143     struct scale_factors *const scale = &xd->scale_factor[ref];
    144     struct buf_2d *const pre_buf = &pd->pre[ref];
    145     struct buf_2d *const dst_buf = &pd->dst;
    146     uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
    147 
    148     // TODO(jkoleszar): All chroma MVs in SPLITMV mode are taken as the
    149     // same MV (the average of the 4 luma MVs) but we could do something
    150     // smarter for non-4:2:0. Just punt for now, pending the changes to get
    151     // rid of SPLITMV mode entirely.
    152     const MV mv = mi->mbmi.sb_type < BLOCK_8X8
    153                ? (plane == 0 ? mi->bmi[block].as_mv[ref].as_mv
    154                              : mi_mv_pred_q4(mi, ref))
    155                : mi->mbmi.mv[ref].as_mv;
    156 
    157     // TODO(jkoleszar): This clamping is done in the incorrect place for the
    158     // scaling case. It needs to be done on the scaled MV, not the pre-scaling
    159     // MV. Note however that it performs the subsampling aware scaling so
    160     // that the result is always q4.
    161     // mv_precision precision is MV_PRECISION_Q4.
    162     const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
    163                                                pd->subsampling_x,
    164                                                pd->subsampling_y);
    165 
    166     uint8_t *pre;
    167     MV32 scaled_mv;
    168     int xs, ys;
    169 
    170     if (vp9_is_scaled(scale->sfc)) {
    171       pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, scale);
    172       scale->sfc->set_scaled_offsets(scale, mi_y + y, mi_x + x);
    173       scaled_mv = scale->sfc->scale_mv(&mv_q4, scale);
    174       xs = scale->sfc->x_step_q4;
    175       ys = scale->sfc->y_step_q4;
    176     } else {
    177       pre = pre_buf->buf + (y * pre_buf->stride + x);
    178       scaled_mv.row = mv_q4.row;
    179       scaled_mv.col = mv_q4.col;
    180       xs = ys = 16;
    181     }
    182 
    183     inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
    184                     &scaled_mv, scale,
    185                     4 << pred_w, 4 << pred_h, ref,
    186                     &xd->subpix, xs, ys);
    187   }
    188 }
    189 
    190 static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
    191                                               int mi_row, int mi_col,
    192                                               int plane_from, int plane_to) {
    193   int plane;
    194   for (plane = plane_from; plane <= plane_to; ++plane) {
    195     const int mi_x = mi_col * MI_SIZE;
    196     const int mi_y = mi_row * MI_SIZE;
    197     const int bwl = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
    198     const int bhl = b_height_log2(bsize) - xd->plane[plane].subsampling_y;
    199 
    200     if (xd->mi_8x8[0]->mbmi.sb_type < BLOCK_8X8) {
    201       int i = 0, x, y;
    202       assert(bsize == BLOCK_8X8);
    203       for (y = 0; y < 1 << bhl; ++y)
    204         for (x = 0; x < 1 << bwl; ++x)
    205           build_inter_predictors(xd, plane, i++, bsize, 0, 0, mi_x, mi_y);
    206     } else {
    207       build_inter_predictors(xd, plane, 0, bsize, bwl, bhl, mi_x, mi_y);
    208     }
    209   }
    210 }
    211 
    212 void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
    213                                     BLOCK_SIZE bsize) {
    214   build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
    215 }
    216 void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
    217                                      BLOCK_SIZE bsize) {
    218   build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
    219                                     MAX_MB_PLANE - 1);
    220 }
    221 void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
    222                                    BLOCK_SIZE bsize) {
    223   build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
    224                                     MAX_MB_PLANE - 1);
    225 }
    226 
    227 // TODO(dkovalev: find better place for this function)
    228 void vp9_setup_scale_factors(VP9_COMMON *cm, int i) {
    229   const int ref = cm->active_ref_idx[i];
    230   struct scale_factors *const sf = &cm->active_ref_scale[i];
    231   struct scale_factors_common *const sfc = &cm->active_ref_scale_comm[i];
    232   if (ref >= NUM_YV12_BUFFERS) {
    233     vp9_zero(*sf);
    234     vp9_zero(*sfc);
    235   } else {
    236     YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref];
    237     vp9_setup_scale_factors_for_frame(sf, sfc,
    238                                       fb->y_crop_width, fb->y_crop_height,
    239                                       cm->width, cm->height);
    240 
    241     if (vp9_is_scaled(sfc))
    242       vp9_extend_frame_borders(fb, cm->subsampling_x, cm->subsampling_y);
    243   }
    244 }
    245 
    246