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_reconinter.h" 20 #include "vp9/common/vp9_reconintra.h" 21 22 #if CONFIG_VP9_HIGHBITDEPTH 23 void vp9_highbd_build_inter_predictor( 24 const uint16_t *src, int src_stride, uint16_t *dst, int dst_stride, 25 const MV *src_mv, const struct scale_factors *sf, int w, int h, int ref, 26 const InterpKernel *kernel, enum mv_precision precision, int x, int y, 27 int bd) { 28 const int is_q4 = precision == MV_PRECISION_Q4; 29 const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2, 30 is_q4 ? src_mv->col : src_mv->col * 2 }; 31 MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf); 32 const int subpel_x = mv.col & SUBPEL_MASK; 33 const int subpel_y = mv.row & SUBPEL_MASK; 34 35 src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS); 36 37 highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, 38 sf, w, h, ref, kernel, sf->x_step_q4, sf->y_step_q4, 39 bd); 40 } 41 #endif // CONFIG_VP9_HIGHBITDEPTH 42 43 void vp9_build_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst, 44 int dst_stride, const MV *src_mv, 45 const struct scale_factors *sf, int w, int h, 46 int ref, const InterpKernel *kernel, 47 enum mv_precision precision, int x, int y) { 48 const int is_q4 = precision == MV_PRECISION_Q4; 49 const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2, 50 is_q4 ? src_mv->col : src_mv->col * 2 }; 51 MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf); 52 const int subpel_x = mv.col & SUBPEL_MASK; 53 const int subpel_y = mv.row & SUBPEL_MASK; 54 55 src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS); 56 57 inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w, 58 h, ref, kernel, sf->x_step_q4, sf->y_step_q4); 59 } 60 61 static INLINE int round_mv_comp_q4(int value) { 62 return (value < 0 ? value - 2 : value + 2) / 4; 63 } 64 65 static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) { 66 MV res = { 67 round_mv_comp_q4( 68 mi->bmi[0].as_mv[idx].as_mv.row + mi->bmi[1].as_mv[idx].as_mv.row + 69 mi->bmi[2].as_mv[idx].as_mv.row + mi->bmi[3].as_mv[idx].as_mv.row), 70 round_mv_comp_q4( 71 mi->bmi[0].as_mv[idx].as_mv.col + mi->bmi[1].as_mv[idx].as_mv.col + 72 mi->bmi[2].as_mv[idx].as_mv.col + mi->bmi[3].as_mv[idx].as_mv.col) 73 }; 74 return res; 75 } 76 77 static INLINE int round_mv_comp_q2(int value) { 78 return (value < 0 ? value - 1 : value + 1) / 2; 79 } 80 81 static MV mi_mv_pred_q2(const MODE_INFO *mi, int idx, int block0, int block1) { 82 MV res = { round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.row + 83 mi->bmi[block1].as_mv[idx].as_mv.row), 84 round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.col + 85 mi->bmi[block1].as_mv[idx].as_mv.col) }; 86 return res; 87 } 88 89 // TODO(jkoleszar): yet another mv clamping function :-( 90 MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv, int bw, 91 int bh, int ss_x, int ss_y) { 92 // If the MV points so far into the UMV border that no visible pixels 93 // are used for reconstruction, the subpel part of the MV can be 94 // discarded and the MV limited to 16 pixels with equivalent results. 95 const int spel_left = (VP9_INTERP_EXTEND + bw) << SUBPEL_BITS; 96 const int spel_right = spel_left - SUBPEL_SHIFTS; 97 const int spel_top = (VP9_INTERP_EXTEND + bh) << SUBPEL_BITS; 98 const int spel_bottom = spel_top - SUBPEL_SHIFTS; 99 MV clamped_mv = { src_mv->row * (1 << (1 - ss_y)), 100 src_mv->col * (1 << (1 - ss_x)) }; 101 assert(ss_x <= 1); 102 assert(ss_y <= 1); 103 104 clamp_mv(&clamped_mv, xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left, 105 xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right, 106 xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top, 107 xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom); 108 109 return clamped_mv; 110 } 111 112 MV average_split_mvs(const struct macroblockd_plane *pd, const MODE_INFO *mi, 113 int ref, int block) { 114 const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0); 115 MV res = { 0, 0 }; 116 switch (ss_idx) { 117 case 0: res = mi->bmi[block].as_mv[ref].as_mv; break; 118 case 1: res = mi_mv_pred_q2(mi, ref, block, block + 2); break; 119 case 2: res = mi_mv_pred_q2(mi, ref, block, block + 1); break; 120 case 3: res = mi_mv_pred_q4(mi, ref); break; 121 default: assert(ss_idx <= 3 && ss_idx >= 0); 122 } 123 return res; 124 } 125 126 static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block, 127 int bw, int bh, int x, int y, int w, int h, 128 int mi_x, int mi_y) { 129 struct macroblockd_plane *const pd = &xd->plane[plane]; 130 const MODE_INFO *mi = xd->mi[0]; 131 const int is_compound = has_second_ref(mi); 132 const InterpKernel *kernel = vp9_filter_kernels[mi->interp_filter]; 133 int ref; 134 135 for (ref = 0; ref < 1 + is_compound; ++ref) { 136 const struct scale_factors *const sf = &xd->block_refs[ref]->sf; 137 struct buf_2d *const pre_buf = &pd->pre[ref]; 138 struct buf_2d *const dst_buf = &pd->dst; 139 uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x; 140 const MV mv = mi->sb_type < BLOCK_8X8 141 ? average_split_mvs(pd, mi, ref, block) 142 : mi->mv[ref].as_mv; 143 144 // TODO(jkoleszar): This clamping is done in the incorrect place for the 145 // scaling case. It needs to be done on the scaled MV, not the pre-scaling 146 // MV. Note however that it performs the subsampling aware scaling so 147 // that the result is always q4. 148 // mv_precision precision is MV_PRECISION_Q4. 149 const MV mv_q4 = clamp_mv_to_umv_border_sb( 150 xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y); 151 152 uint8_t *pre; 153 MV32 scaled_mv; 154 int xs, ys, subpel_x, subpel_y; 155 const int is_scaled = vp9_is_scaled(sf); 156 157 if (is_scaled) { 158 // Co-ordinate of containing block to pixel precision. 159 const int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)); 160 const int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)); 161 #if 0 // CONFIG_BETTER_HW_COMPATIBILITY 162 assert(xd->mi[0]->sb_type != BLOCK_4X8 && 163 xd->mi[0]->sb_type != BLOCK_8X4); 164 assert(mv_q4.row == mv.row * (1 << (1 - pd->subsampling_y)) && 165 mv_q4.col == mv.col * (1 << (1 - pd->subsampling_x))); 166 #endif 167 if (plane == 0) 168 pre_buf->buf = xd->block_refs[ref]->buf->y_buffer; 169 else if (plane == 1) 170 pre_buf->buf = xd->block_refs[ref]->buf->u_buffer; 171 else 172 pre_buf->buf = xd->block_refs[ref]->buf->v_buffer; 173 174 pre_buf->buf += 175 scaled_buffer_offset(x_start + x, y_start + y, pre_buf->stride, sf); 176 pre = pre_buf->buf; 177 scaled_mv = vp9_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf); 178 xs = sf->x_step_q4; 179 ys = sf->y_step_q4; 180 } else { 181 pre = pre_buf->buf + (y * pre_buf->stride + x); 182 scaled_mv.row = mv_q4.row; 183 scaled_mv.col = mv_q4.col; 184 xs = ys = 16; 185 } 186 subpel_x = scaled_mv.col & SUBPEL_MASK; 187 subpel_y = scaled_mv.row & SUBPEL_MASK; 188 pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride + 189 (scaled_mv.col >> SUBPEL_BITS); 190 191 #if CONFIG_VP9_HIGHBITDEPTH 192 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { 193 highbd_inter_predictor(CONVERT_TO_SHORTPTR(pre), pre_buf->stride, 194 CONVERT_TO_SHORTPTR(dst), dst_buf->stride, 195 subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys, 196 xd->bd); 197 } else { 198 inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, 199 subpel_y, sf, w, h, ref, kernel, xs, ys); 200 } 201 #else 202 inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, 203 subpel_y, sf, w, h, ref, kernel, xs, ys); 204 #endif // CONFIG_VP9_HIGHBITDEPTH 205 } 206 } 207 208 static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize, 209 int mi_row, int mi_col, 210 int plane_from, int plane_to) { 211 int plane; 212 const int mi_x = mi_col * MI_SIZE; 213 const int mi_y = mi_row * MI_SIZE; 214 for (plane = plane_from; plane <= plane_to; ++plane) { 215 const BLOCK_SIZE plane_bsize = 216 get_plane_block_size(bsize, &xd->plane[plane]); 217 const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize]; 218 const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize]; 219 const int bw = 4 * num_4x4_w; 220 const int bh = 4 * num_4x4_h; 221 222 if (xd->mi[0]->sb_type < BLOCK_8X8) { 223 int i = 0, x, y; 224 assert(bsize == BLOCK_8X8); 225 for (y = 0; y < num_4x4_h; ++y) 226 for (x = 0; x < num_4x4_w; ++x) 227 build_inter_predictors(xd, plane, i++, bw, bh, 4 * x, 4 * y, 4, 4, 228 mi_x, mi_y); 229 } else { 230 build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh, mi_x, mi_y); 231 } 232 } 233 } 234 235 void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col, 236 BLOCK_SIZE bsize) { 237 build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0); 238 } 239 240 void vp9_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col, 241 BLOCK_SIZE bsize, int plane) { 242 build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane); 243 } 244 245 void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col, 246 BLOCK_SIZE bsize) { 247 build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1, 248 MAX_MB_PLANE - 1); 249 } 250 251 void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col, 252 BLOCK_SIZE bsize) { 253 build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 254 MAX_MB_PLANE - 1); 255 } 256 257 void vp9_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE], 258 const YV12_BUFFER_CONFIG *src, int mi_row, 259 int mi_col) { 260 uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer, 261 src->v_buffer }; 262 const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride, 263 src->uv_stride }; 264 int i; 265 266 for (i = 0; i < MAX_MB_PLANE; ++i) { 267 struct macroblockd_plane *const pd = &planes[i]; 268 setup_pred_plane(&pd->dst, buffers[i], strides[i], mi_row, mi_col, NULL, 269 pd->subsampling_x, pd->subsampling_y); 270 } 271 } 272 273 void vp9_setup_pre_planes(MACROBLOCKD *xd, int idx, 274 const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col, 275 const struct scale_factors *sf) { 276 if (src != NULL) { 277 int i; 278 uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer, 279 src->v_buffer }; 280 const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride, 281 src->uv_stride }; 282 for (i = 0; i < MAX_MB_PLANE; ++i) { 283 struct macroblockd_plane *const pd = &xd->plane[i]; 284 setup_pred_plane(&pd->pre[idx], buffers[i], strides[i], mi_row, mi_col, 285 sf, pd->subsampling_x, pd->subsampling_y); 286 } 287 } 288 } 289