findnearmv.c 13.4 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
12
 */


#include "findnearmv.h"
13
#include "vp9/common/sadmxn.h"
14
#include "vp9/common/subpelvar.h"
15
#include <limits.h>
John Koleszar's avatar
John Koleszar committed
16

17
const unsigned char vp9_mbsplit_offset[4][16] = {
John Koleszar's avatar
John Koleszar committed
18
19
20
21
  { 0,  8,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
  { 0,  2,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
  { 0,  2,  8, 10,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
  { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
22
23
};

24
static void lower_mv_precision(int_mv *mv, int usehp)
25
{
26
  if (!usehp || !vp9_use_nmv_hp(&mv->as_mv)) {
27
28
29
30
31
    if (mv->as_mv.row & 1)
      mv->as_mv.row += (mv->as_mv.row > 0 ? -1 : 1);
    if (mv->as_mv.col & 1)
      mv->as_mv.col += (mv->as_mv.col > 0 ? -1 : 1);
  }
32
33
}

John Koleszar's avatar
John Koleszar committed
34
35
36
/* Predict motion vectors using those from already-decoded nearby blocks.
   Note that we only consider one 4x4 subblock from each candidate 16x16
   macroblock.   */
37

38
void vp9_find_near_mvs
John Koleszar's avatar
John Koleszar committed
39
(
John Koleszar's avatar
John Koleszar committed
40
41
42
43
44
45
46
47
  MACROBLOCKD *xd,
  const MODE_INFO *here,
  const MODE_INFO *lf_here,
  int_mv *nearest,
  int_mv *nearby,
  int_mv *best_mv,
  int cnt[4],
  int refframe,
48
  int *ref_frame_sign_bias) {
John Koleszar's avatar
John Koleszar committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  const MODE_INFO *above = here - xd->mode_info_stride;
  const MODE_INFO *left = here - 1;
  const MODE_INFO *aboveleft = above - 1;
  const MODE_INFO *third = NULL;
  int_mv            near_mvs[4];
  int_mv           *mv = near_mvs;
  int             *cntx = cnt;
  enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};

  /* Zero accumulators */
  mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
  cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;

  /* Process above */
  if (above->mbmi.ref_frame != INTRA_FRAME) {
64
    if (above->mbmi.mv[0].as_int) {
65
      ++ mv;
66
      mv->as_int = above->mbmi.mv[0].as_int;
John Koleszar's avatar
John Koleszar committed
67
68
69
      mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
              refframe, mv, ref_frame_sign_bias);
      ++cntx;
70
    }
John Koleszar's avatar
John Koleszar committed
71
72
73
74
75
    *cntx += 2;
  }

  /* Process left */
  if (left->mbmi.ref_frame != INTRA_FRAME) {
76
    if (left->mbmi.mv[0].as_int) {
John Koleszar's avatar
John Koleszar committed
77
      int_mv this_mv;
78
      this_mv.as_int = left->mbmi.mv[0].as_int;
John Koleszar's avatar
John Koleszar committed
79
80
      mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
              refframe, &this_mv, ref_frame_sign_bias);
81

John Koleszar's avatar
John Koleszar committed
82
      if (this_mv.as_int != mv->as_int) {
83
84
85
        ++ mv;
        mv->as_int = this_mv.as_int;
        ++ cntx;
John Koleszar's avatar
John Koleszar committed
86
87
88
89
90
91
92
93
      }
      *cntx += 2;
    } else
      cnt[CNT_INTRA] += 2;
  }
  /* Process above left or the one from last frame */
  if (aboveleft->mbmi.ref_frame != INTRA_FRAME ||
      (lf_here->mbmi.ref_frame == LAST_FRAME && refframe == LAST_FRAME)) {
94
    if (aboveleft->mbmi.mv[0].as_int) {
John Koleszar's avatar
John Koleszar committed
95
      third = aboveleft;
96
    } else if (lf_here->mbmi.mv[0].as_int) {
John Koleszar's avatar
John Koleszar committed
97
      third = lf_here;
98
    }
John Koleszar's avatar
John Koleszar committed
99
100
    if (third) {
      int_mv this_mv;
101
      this_mv.as_int = third->mbmi.mv[0].as_int;
John Koleszar's avatar
John Koleszar committed
102
103
104
105
      mv_bias(ref_frame_sign_bias[third->mbmi.ref_frame],
              refframe, &this_mv, ref_frame_sign_bias);

      if (this_mv.as_int != mv->as_int) {
106
107
108
        ++ mv;
        mv->as_int = this_mv.as_int;
        ++ cntx;
John Koleszar's avatar
John Koleszar committed
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
      }
      *cntx += 1;
    } else
      cnt[CNT_INTRA] += 1;
  }

  /* If we have three distinct MV's ... */
  if (cnt[CNT_SPLITMV]) {
    /* See if the third MV can be merged with NEAREST */
    if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
      cnt[CNT_NEAREST] += 1;
  }

  cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
                      + (left->mbmi.mode == SPLITMV)) * 2
                     + (
                       lf_here->mbmi.mode == SPLITMV ||
126
127
                       aboveleft->mbmi.mode == SPLITMV);

John Koleszar's avatar
John Koleszar committed
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  /* Swap near and nearest if necessary */
  if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
    int tmp;
    tmp = cnt[CNT_NEAREST];
    cnt[CNT_NEAREST] = cnt[CNT_NEAR];
    cnt[CNT_NEAR] = tmp;
    tmp = near_mvs[CNT_NEAREST].as_int;
    near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
    near_mvs[CNT_NEAR].as_int = tmp;
  }

  /* Use near_mvs[0] to store the "best" MV */
  if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA])
    near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];

  /* Set up return values */
  best_mv->as_int = near_mvs[0].as_int;
  nearest->as_int = near_mvs[CNT_NEAREST].as_int;
  nearby->as_int = near_mvs[CNT_NEAR].as_int;

  /* Make sure that the 1/8th bits of the Mvs are zero if high_precision
   * is not being used, by truncating the last bit towards 0
   */
151
152
153
  lower_mv_precision(best_mv, xd->allow_high_precision_mv);
  lower_mv_precision(nearest, xd->allow_high_precision_mv);
  lower_mv_precision(nearby, xd->allow_high_precision_mv);
154

John Koleszar's avatar
John Koleszar committed
155
  // TODO: move clamp outside findnearmv
156
157
158
  clamp_mv2(nearest, xd);
  clamp_mv2(nearby, xd);
  clamp_mv2(best_mv, xd);
159
160
}

161
162
vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc,
                           vp9_prob p[VP9_MVREFS - 1], const int near_mv_ref_ct[4]
John Koleszar's avatar
John Koleszar committed
163
164
165
166
167
168
                          ) {
  p[0] = pc->fc.vp8_mode_contexts [near_mv_ref_ct[0]] [0];
  p[1] = pc->fc.vp8_mode_contexts [near_mv_ref_ct[1]] [1];
  p[2] = pc->fc.vp8_mode_contexts [near_mv_ref_ct[2]] [2];
  p[3] = pc->fc.vp8_mode_contexts [near_mv_ref_ct[3]] [3];
  return p;
John Koleszar's avatar
John Koleszar committed
169
}
170
171

#if CONFIG_NEWBESTREFMV
172
#define SP(x) (((x) & 7) << 1)
173
unsigned int vp9_sad3x16_c(
174
175
176
177
178
179
180
  const unsigned char *src_ptr,
  int  src_stride,
  const unsigned char *ref_ptr,
  int  ref_stride,
  int max_sad) {
  return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 3, 16);
}
181
unsigned int vp9_sad16x3_c(
182
183
184
185
186
187
188
189
  const unsigned char *src_ptr,
  int  src_stride,
  const unsigned char *ref_ptr,
  int  ref_stride,
  int max_sad) {
  return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 16, 3);
}

190
191
192
193
194
195
196
197
198
199
200
#if CONFIG_SUBPELREFMV
unsigned int vp9_variance2x16_c(const unsigned char *src_ptr,
                                const int  source_stride,
                                const unsigned char *ref_ptr,
                                const int  recon_stride,
                                unsigned int *sse) {
  unsigned int var;
  int avg;

  variance(src_ptr, source_stride, ref_ptr, recon_stride, 2, 16, &var, &avg);
  *sse = var;
201
  return (var - (((unsigned int)avg * avg) >> 5));
202
203
204
205
206
207
208
209
210
211
212
213
}

unsigned int vp9_variance16x2_c(const unsigned char *src_ptr,
                                const int  source_stride,
                                const unsigned char *ref_ptr,
                                const int  recon_stride,
                                unsigned int *sse) {
  unsigned int var;
  int avg;

  variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 2, &var, &avg);
  *sse = var;
214
  return (var - (((unsigned int)avg * avg) >> 5));
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
255
256
257
258
259
}

unsigned int vp9_sub_pixel_variance16x2_c(const unsigned char  *src_ptr,
                                          const int  src_pixels_per_line,
                                          const int  xoffset,
                                          const int  yoffset,
                                          const unsigned char *dst_ptr,
                                          const int dst_pixels_per_line,
                                          unsigned int *sse) {
  unsigned short FData3[16 * 3];  // Temp data bufffer used in filtering
  unsigned char  temp2[20 * 16];
  const short *HFilter, *VFilter;

  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];

  var_filter_block2d_bil_first_pass(src_ptr, FData3,
                                    src_pixels_per_line, 1, 3, 16, HFilter);
  var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 2, 16, VFilter);

  return vp9_variance16x2_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
}

unsigned int vp9_sub_pixel_variance2x16_c(const unsigned char  *src_ptr,
                                          const int  src_pixels_per_line,
                                          const int  xoffset,
                                          const int  yoffset,
                                          const unsigned char *dst_ptr,
                                          const int dst_pixels_per_line,
                                          unsigned int *sse) {
  unsigned short FData3[2 * 17];  // Temp data bufffer used in filtering
  unsigned char  temp2[2 * 16];
  const short *HFilter, *VFilter;

  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];

  var_filter_block2d_bil_first_pass(src_ptr, FData3,
                                    src_pixels_per_line, 1, 17, 2, HFilter);
  var_filter_block2d_bil_second_pass(FData3, temp2, 2, 2, 16, 2, VFilter);

  return vp9_variance2x16_c(temp2, 2, dst_ptr, dst_pixels_per_line, sse);
}
#endif

260
261
262
263
/* check a list of motion vectors by sad score using a number rows of pixels
 * above and a number cols of pixels in the left to select the one with best
 * score to use as ref motion vector
 */
264
void vp9_find_best_ref_mvs(MACROBLOCKD *xd,
Paul Wilkins's avatar
Paul Wilkins committed
265
266
                           unsigned char *ref_y_buffer,
                           int ref_y_stride,
Paul Wilkins's avatar
Paul Wilkins committed
267
                           int_mv *mvlist,
Paul Wilkins's avatar
Paul Wilkins committed
268
269
270
271
272
273
274
275
                           int_mv *best_mv,
                           int_mv *nearest,
                           int_mv *near) {
  int i, j;
  unsigned char *above_src;
  unsigned char *left_src;
  unsigned char *above_ref;
  unsigned char *left_ref;
276
  int score;
277
  int sse;
278
  int ref_scores[MAX_MV_REFS] = {0};
Paul Wilkins's avatar
Paul Wilkins committed
279
280
281
282
283
284
285
  int_mv sorted_mvs[MAX_MV_REFS];
  int zero_seen = FALSE;

  // Default all to 0,0 if nothing else available
  best_mv->as_int = nearest->as_int = near->as_int = 0;
  vpx_memset(sorted_mvs, 0, sizeof(sorted_mvs));

286
#if CONFIG_SUBPELREFMV
287
288
289
290
  above_src = xd->dst.y_buffer - xd->dst.y_stride * 2;
  left_src  = xd->dst.y_buffer - 2;
  above_ref = ref_y_buffer - ref_y_stride * 2;
  left_ref  = ref_y_buffer - 2;
291
292
293
294
295
296
#else
  above_src = xd->dst.y_buffer - xd->dst.y_stride * 3;
  left_src  = xd->dst.y_buffer - 3;
  above_ref = ref_y_buffer - ref_y_stride * 3;
  left_ref  = ref_y_buffer - 3;
#endif
Paul Wilkins's avatar
Paul Wilkins committed
297

Paul Wilkins's avatar
Paul Wilkins committed
298
299
300
  //for(i = 0; i < MAX_MV_REFS; ++i) {
  // Limit search to the predicted best 4
  for(i = 0; i < 4; ++i) {
Paul Wilkins's avatar
Paul Wilkins committed
301
    int_mv this_mv;
302
    int offset = 0;
Paul Wilkins's avatar
Paul Wilkins committed
303
304
    int row_offset, col_offset;

Paul Wilkins's avatar
Paul Wilkins committed
305
    this_mv.as_int = mvlist[i].as_int;
Paul Wilkins's avatar
Paul Wilkins committed
306
307
308

    // If we see a 0,0 vector for a second time we have reached the end of
    // the list of valid candidate vectors.
Yaowu Xu's avatar
Yaowu Xu committed
309
310
311
312
    if (!this_mv.as_int && zero_seen)
      break;

    zero_seen = zero_seen || !this_mv.as_int;
Paul Wilkins's avatar
Paul Wilkins committed
313

314
315
316
317
318
    clamp_mv(&this_mv,
             xd->mb_to_left_edge - LEFT_TOP_MARGIN + 24,
             xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
             xd->mb_to_top_edge - LEFT_TOP_MARGIN + 24,
             xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
319
#if CONFIG_SUBPELREFMV
320
321
    row_offset = this_mv.as_mv.row >> 3;
    col_offset = this_mv.as_mv.col >> 3;
Paul Wilkins's avatar
Paul Wilkins committed
322
    offset = ref_y_stride * row_offset + col_offset;
323
    score = 0;
324
    if (xd->up_available) {
325
      vp9_sub_pixel_variance16x2_c(above_ref + offset, ref_y_stride,
326
327
                                   SP(this_mv.as_mv.col), SP(this_mv.as_mv.row),
                                   above_src, xd->dst.y_stride, &sse);
328
      score += sse;
329
330
    }
    if (xd->left_available) {
331
      vp9_sub_pixel_variance2x16_c(left_ref + offset, ref_y_stride,
332
333
                                   SP(this_mv.as_mv.col), SP(this_mv.as_mv.row),
                                   left_src, xd->dst.y_stride, &sse);
334
335
336
337
338
339
340
341
342
343
      score += sse;
    }
#else
    row_offset = (this_mv.as_mv.row > 0) ?
      ((this_mv.as_mv.row + 3) >> 3):((this_mv.as_mv.row + 4) >> 3);
    col_offset = (this_mv.as_mv.col > 0) ?
      ((this_mv.as_mv.col + 3) >> 3):((this_mv.as_mv.col + 4) >> 3);
    offset = ref_y_stride * row_offset + col_offset;
    score = 0;
    if (xd->up_available) {
344
      score += vp9_sad16x3(above_src, xd->dst.y_stride,
345
346
347
                           above_ref + offset, ref_y_stride, INT_MAX);
    }
    if (xd->left_available) {
348
      score += vp9_sad3x16(left_src, xd->dst.y_stride,
349
                           left_ref + offset, ref_y_stride, INT_MAX);
350
    }
351
#endif
Paul Wilkins's avatar
Paul Wilkins committed
352
    // Add the entry to our list and then resort the list on score.
353
    ref_scores[i] = score;
Paul Wilkins's avatar
Paul Wilkins committed
354
355
356
    sorted_mvs[i].as_int = this_mv.as_int;
    j = i;
    while (j > 0) {
357
358
      if (ref_scores[j] < ref_scores[j-1]) {
        ref_scores[j] = ref_scores[j-1];
Paul Wilkins's avatar
Paul Wilkins committed
359
        sorted_mvs[j].as_int = sorted_mvs[j-1].as_int;
360
        ref_scores[j-1] = score;
Paul Wilkins's avatar
Paul Wilkins committed
361
362
363
364
365
366
367
        sorted_mvs[j-1].as_int = this_mv.as_int;
        j--;
      } else
        break;
    }
  }

368
369
370
  // Make sure all the candidates are properly clamped etc
  for (i = 0; i < 4; ++i) {
    lower_mv_precision(&sorted_mvs[i], xd->allow_high_precision_mv);
371
    clamp_mv2(&sorted_mvs[i], xd);
372
373
  }

Paul Wilkins's avatar
Paul Wilkins committed
374
375
376
377
378
379
380
  // Set the best mv to the first entry in the sorted list
  best_mv->as_int = sorted_mvs[0].as_int;

  // Provided that there are non zero vectors available there will not
  // be more than one 0,0 entry in the sorted list.
  // The best ref mv is always set to the first entry (which gave the best
  // results. The nearest is set to the first non zero vector if available and
381
  // near to the second non zero vector if available.
Paul Wilkins's avatar
Paul Wilkins committed
382
383
384
385
386
387
388
389
390
391
392
393
  // We do not use 0,0 as a nearest or near as 0,0 has its own mode.
  if ( sorted_mvs[0].as_int ) {
    nearest->as_int = sorted_mvs[0].as_int;
    if ( sorted_mvs[1].as_int )
      near->as_int = sorted_mvs[1].as_int;
    else
      near->as_int = sorted_mvs[2].as_int;
  } else {
      nearest->as_int = sorted_mvs[1].as_int;
      near->as_int = sorted_mvs[2].as_int;
  }

Paul Wilkins's avatar
Paul Wilkins committed
394
395
  // Copy back the re-ordered mv list
  vpx_memcpy(mvlist, sorted_mvs, sizeof(sorted_mvs));
Paul Wilkins's avatar
Paul Wilkins committed
396
397
398
}

#endif  // CONFIG_NEWBESTREFMV