vp9_reconinter.c 12.3 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9 10
 */

11
#include <assert.h>
John Koleszar's avatar
John Koleszar committed
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

Yunqing Wang's avatar
Yunqing Wang committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
static void inter_predictor(const uint8_t *src, int src_stride,
                            uint8_t *dst, int dst_stride,
                            const MV32 *mv,
                            const struct scale_factors *scale,
                            int w, int h, int ref,
                            const struct subpix_fn_table *subpix,
                            int xs, int ys) {
  const int subpel_x = mv->col & SUBPEL_MASK;
  const int subpel_y = mv->row & SUBPEL_MASK;

  src += (mv->row >> SUBPEL_BITS) * src_stride + (mv->col >> SUBPEL_BITS);
  scale->sfc->predict[subpel_x != 0][subpel_y != 0][ref](
      src, src_stride, dst, dst_stride,
      subpix->filter_x[subpel_x], xs,
      subpix->filter_y[subpel_y], ys,
      w, h);
}

42 43
void vp9_build_inter_predictor(const uint8_t *src, int src_stride,
                               uint8_t *dst, int dst_stride,
44
                               const MV *src_mv,
45
                               const struct scale_factors *scale,
46
                               int w, int h, int ref,
47 48
                               const struct subpix_fn_table *subpix,
                               enum mv_precision precision) {
49
  const int is_q4 = precision == MV_PRECISION_Q4;
Yaowu Xu's avatar
Yaowu Xu committed
50 51
  const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
                     is_q4 ? src_mv->col : src_mv->col * 2 };
Yunqing Wang's avatar
Yunqing Wang committed
52 53
  const struct scale_factors_common *sfc = scale->sfc;
  const MV32 mv = sfc->scale_mv(&mv_q4, scale);
54

Yunqing Wang's avatar
Yunqing Wang committed
55 56
  inter_predictor(src, src_stride, dst, dst_stride, &mv, scale,
                  w, h, ref, subpix, sfc->x_step_q4, sfc->y_step_q4);
57 58
}

59 60
static INLINE int round_mv_comp_q4(int value) {
  return (value < 0 ? value - 2 : value + 2) / 4;
John Koleszar's avatar
John Koleszar committed
61 62
}

63 64 65 66 67 68 69 70 71 72
static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) {
  MV res = { round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.row +
                              mi->bmi[1].as_mv[idx].as_mv.row +
                              mi->bmi[2].as_mv[idx].as_mv.row +
                              mi->bmi[3].as_mv[idx].as_mv.row),
             round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.col +
                              mi->bmi[1].as_mv[idx].as_mv.col +
                              mi->bmi[2].as_mv[idx].as_mv.col +
                              mi->bmi[3].as_mv[idx].as_mv.col) };
  return res;
73 74
}

75
// TODO(jkoleszar): yet another mv clamping function :-(
76 77
MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv,
                             int bw, int bh, int ss_x, int ss_y) {
78 79 80
  // If the MV points so far into the UMV border that no visible pixels
  // are used for reconstruction, the subpel part of the MV can be
  // discarded and the MV limited to 16 pixels with equivalent results.
81 82 83 84
  const int spel_left = (VP9_INTERP_EXTEND + bw) << SUBPEL_BITS;
  const int spel_right = spel_left - SUBPEL_SHIFTS;
  const int spel_top = (VP9_INTERP_EXTEND + bh) << SUBPEL_BITS;
  const int spel_bottom = spel_top - SUBPEL_SHIFTS;
85
  MV clamped_mv = {
Yaowu Xu's avatar
Yaowu Xu committed
86 87
    src_mv->row * (1 << (1 - ss_y)),
    src_mv->col * (1 << (1 - ss_x))
88
  };
89 90
  assert(ss_x <= 1);
  assert(ss_y <= 1);
91

Yaowu Xu's avatar
Yaowu Xu committed
92 93 94 95 96
  clamp_mv(&clamped_mv,
           xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left,
           xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right,
           xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top,
           xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom);
97

98 99 100
  return clamped_mv;
}

101 102 103 104
// TODO(jkoleszar): In principle, pred_w, pred_h are unnecessary, as we could
// calculate the subsampled BLOCK_SIZE, but that type isn't defined for
// sizes smaller than 16x16 yet.
static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
105 106
                                   int bw, int bh,
                                   int x, int y, int w, int h,
107
                                   int mi_x, int mi_y) {
108
  struct macroblockd_plane *const pd = &xd->plane[plane];
109
  const MODE_INFO *mi = xd->mi_8x8[0];
110
  const int is_compound = has_second_ref(&mi->mbmi);
111
  int ref;
112

113
  for (ref = 0; ref < 1 + is_compound; ++ref) {
114
    struct scale_factors *const scale = &xd->scale_factor[ref];
115 116
    struct buf_2d *const pre_buf = &pd->pre[ref];
    struct buf_2d *const dst_buf = &pd->dst;
117
    uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
118

119 120 121 122
    // TODO(jkoleszar): All chroma MVs in SPLITMV mode are taken as the
    // same MV (the average of the 4 luma MVs) but we could do something
    // smarter for non-4:2:0. Just punt for now, pending the changes to get
    // rid of SPLITMV mode entirely.
123
    const MV mv = mi->mbmi.sb_type < BLOCK_8X8
124 125 126
               ? (plane == 0 ? mi->bmi[block].as_mv[ref].as_mv
                             : mi_mv_pred_q4(mi, ref))
               : mi->mbmi.mv[ref].as_mv;
127 128 129 130 131

    // TODO(jkoleszar): This clamping is done in the incorrect place for the
    // scaling case. It needs to be done on the scaled MV, not the pre-scaling
    // MV. Note however that it performs the subsampling aware scaling so
    // that the result is always q4.
132 133 134 135
    // mv_precision precision is MV_PRECISION_Q4.
    const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
                                               pd->subsampling_x,
                                               pd->subsampling_y);
136

Yunqing Wang's avatar
Yunqing Wang committed
137 138 139 140 141 142
    uint8_t *pre;
    MV32 scaled_mv;
    int xs, ys;

    if (vp9_is_scaled(scale->sfc)) {
      pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, scale);
143
      scale->sfc->set_scaled_offsets(scale, mi_y + y, mi_x + x);
Yunqing Wang's avatar
Yunqing Wang committed
144 145 146 147 148 149 150 151 152 153 154
      scaled_mv = scale->sfc->scale_mv(&mv_q4, scale);
      xs = scale->sfc->x_step_q4;
      ys = scale->sfc->y_step_q4;
    } else {
      pre = pre_buf->buf + (y * pre_buf->stride + x);
      scaled_mv.row = mv_q4.row;
      scaled_mv.col = mv_q4.col;
      xs = ys = 16;
    }

    inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
155
                    &scaled_mv, scale, w, h, ref, &xd->subpix, xs, ys);
156 157
  }
}
158

159
static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
160 161 162
                                              int mi_row, int mi_col,
                                              int plane_from, int plane_to) {
  int plane;
163 164
  const int mi_x = mi_col * MI_SIZE;
  const int mi_y = mi_row * MI_SIZE;
165
  for (plane = plane_from; plane <= plane_to; ++plane) {
166 167 168 169 170 171
    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize,
                                                        &xd->plane[plane]);
    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
    const int bw = 4 * num_4x4_w;
    const int bh = 4 * num_4x4_h;
172 173 174 175

    if (xd->mi_8x8[0]->mbmi.sb_type < BLOCK_8X8) {
      int i = 0, x, y;
      assert(bsize == BLOCK_8X8);
176 177 178 179
      for (y = 0; y < num_4x4_h; ++y)
        for (x = 0; x < num_4x4_w; ++x)
           build_inter_predictors(xd, plane, i++, bw, bh,
                                  4 * x, 4 * y, 4, 4, mi_x, mi_y);
180
    } else {
181 182
      build_inter_predictors(xd, plane, 0, bw, bh,
                             0, 0, bw, bh, mi_x, mi_y);
183
    }
184 185 186
  }
}

187
void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
188
                                    BLOCK_SIZE bsize) {
189
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
190
}
191
void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
192
                                     BLOCK_SIZE bsize) {
193 194
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
                                    MAX_MB_PLANE - 1);
195
}
196
void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
197
                                   BLOCK_SIZE bsize) {
198 199
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
                                    MAX_MB_PLANE - 1);
200
}
201

202 203 204
// TODO(jingning): This function serves as a placeholder for decoder prediction
// using on demand border extension. It should be moved to /decoder/ directory.
static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
205 206
                                       int bw, int bh,
                                       int x, int y, int w, int h,
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
                                       int mi_x, int mi_y) {
  struct macroblockd_plane *const pd = &xd->plane[plane];
  const MODE_INFO *mi = xd->mi_8x8[0];
  const int is_compound = has_second_ref(&mi->mbmi);
  int ref;

  for (ref = 0; ref < 1 + is_compound; ++ref) {
    struct scale_factors *const scale = &xd->scale_factor[ref];
    struct buf_2d *const pre_buf = &pd->pre[ref];
    struct buf_2d *const dst_buf = &pd->dst;
    uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;

    // TODO(jkoleszar): All chroma MVs in SPLITMV mode are taken as the
    // same MV (the average of the 4 luma MVs) but we could do something
    // smarter for non-4:2:0. Just punt for now, pending the changes to get
    // rid of SPLITMV mode entirely.
    const MV mv = mi->mbmi.sb_type < BLOCK_8X8
               ? (plane == 0 ? mi->bmi[block].as_mv[ref].as_mv
                             : mi_mv_pred_q4(mi, ref))
               : mi->mbmi.mv[ref].as_mv;

    // TODO(jkoleszar): This clamping is done in the incorrect place for the
    // scaling case. It needs to be done on the scaled MV, not the pre-scaling
    // MV. Note however that it performs the subsampling aware scaling so
    // that the result is always q4.
    // mv_precision precision is MV_PRECISION_Q4.
    const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
                                               pd->subsampling_x,
                                               pd->subsampling_y);

    uint8_t *pre;
    MV32 scaled_mv;
    int xs, ys;

    if (vp9_is_scaled(scale->sfc)) {
      pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, scale);
      scale->sfc->set_scaled_offsets(scale, mi_y + y, mi_x + x);
      scaled_mv = scale->sfc->scale_mv(&mv_q4, scale);
      xs = scale->sfc->x_step_q4;
      ys = scale->sfc->y_step_q4;
    } else {
      pre = pre_buf->buf + (y * pre_buf->stride + x);
      scaled_mv.row = mv_q4.row;
      scaled_mv.col = mv_q4.col;
      xs = ys = 16;
    }

    inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
255
                    &scaled_mv, scale, w, h, ref, &xd->subpix, xs, ys);
256 257 258 259 260 261
  }
}

void vp9_dec_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
                                       BLOCK_SIZE bsize) {
  int plane;
262 263
  const int mi_x = mi_col * MI_SIZE;
  const int mi_y = mi_row * MI_SIZE;
264
  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
265 266 267 268 269 270
    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize,
                                                        &xd->plane[plane]);
    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
    const int bw = 4 * num_4x4_w;
    const int bh = 4 * num_4x4_h;
271 272 273 274

    if (xd->mi_8x8[0]->mbmi.sb_type < BLOCK_8X8) {
      int i = 0, x, y;
      assert(bsize == BLOCK_8X8);
275 276 277 278
      for (y = 0; y < num_4x4_h; ++y)
        for (x = 0; x < num_4x4_w; ++x)
          dec_build_inter_predictors(xd, plane, i++, bw, bh,
                                     4 * x, 4 * y, 4, 4, mi_x, mi_y);
279
    } else {
280 281
      dec_build_inter_predictors(xd, plane, 0, bw, bh,
                                 0, 0, bw, bh, mi_x, mi_y);
282 283 284 285
    }
  }
}

286 287 288 289
// TODO(dkovalev: find better place for this function)
void vp9_setup_scale_factors(VP9_COMMON *cm, int i) {
  const int ref = cm->active_ref_idx[i];
  struct scale_factors *const sf = &cm->active_ref_scale[i];
Yunqing Wang's avatar
Yunqing Wang committed
290
  struct scale_factors_common *const sfc = &cm->active_ref_scale_comm[i];
291
  if (ref >= cm->fb_count) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
292
    vp9_zero(*sf);
Yunqing Wang's avatar
Yunqing Wang committed
293
    vp9_zero(*sfc);
294 295
  } else {
    YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref];
Yunqing Wang's avatar
Yunqing Wang committed
296
    vp9_setup_scale_factors_for_frame(sf, sfc,
297 298 299 300 301
                                      fb->y_crop_width, fb->y_crop_height,
                                      cm->width, cm->height);
  }
}