vp9_mvref_common.c 11.8 KB
Newer Older
Paul Wilkins's avatar
Paul Wilkins committed
1
2
3
4
5
6
7
8
9
10
/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

11
#include "vp9/common/vp9_mvref_common.h"
Paul Wilkins's avatar
Paul Wilkins committed
12
13

#define MVREF_NEIGHBOURS 8
Dmitry Kovalev's avatar
Dmitry Kovalev committed
14

15
16
17
18
19
static int b_mv_ref_search[MVREF_NEIGHBOURS][2] = {
  {0, -1}, {-1, 0}, {-1, -1}, {0, -2},
  {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}
};

20
static int mb_mv_ref_search[MVREF_NEIGHBOURS][2] = {
21
22
    {0, -1}, {-1, 0}, {-1, -1}, {0, -3},
    {-3, 0}, {-1, -3}, {-3, -1}, {-3, -3}
23
};
Dmitry Kovalev's avatar
Dmitry Kovalev committed
24

25
static int sb_mv_ref_search[MVREF_NEIGHBOURS][2] = {
26
27
    {0, -1}, {-1, 0}, {2, -1}, {-1, 2},
    {-1, -1}, {0, -3}, {-3, 0}, {-1, -3}
28
};
Dmitry Kovalev's avatar
Dmitry Kovalev committed
29

30
static int sb64_mv_ref_search[MVREF_NEIGHBOURS][2] = {
31
32
33
    {0, -1}, {-1, 0}, {2, -1}, {-1,  2},
    {4, -1}, {-1, 4}, {6, -1}, {-1, -1}
};
34

Paul Wilkins's avatar
Paul Wilkins committed
35
// clamp_mv_ref
Paul Wilkins's avatar
Paul Wilkins committed
36
37
#define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units

Dmitry Kovalev's avatar
Dmitry Kovalev committed
38
static void clamp_mv_ref(const MACROBLOCKD *xd, int_mv *mv) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
39
40
41
42
  mv->as_mv.col = clamp(mv->as_mv.col, xd->mb_to_left_edge - MV_BORDER,
                                       xd->mb_to_right_edge + MV_BORDER);
  mv->as_mv.row = clamp(mv->as_mv.row, xd->mb_to_top_edge - MV_BORDER,
                                       xd->mb_to_bottom_edge + MV_BORDER);
Paul Wilkins's avatar
Paul Wilkins committed
43
44
}

45
46
// Gets a candidate refenence motion vector from the given mode info
// structure if one exists that matches the given reference frame.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
47
static int get_matching_candidate(const MODE_INFO *candidate_mi,
Dmitry Kovalev's avatar
Dmitry Kovalev committed
48
                                  MV_REFERENCE_FRAME ref_frame,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
49
                                  int_mv *c_mv, int block_idx) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
50
  if (ref_frame == candidate_mi->mbmi.ref_frame[0]) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
51
52
53
54
    if (block_idx >= 0 && candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8)
      c_mv->as_int = candidate_mi->bmi[block_idx].as_mv[0].as_int;
    else
      c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
55
  } else if (ref_frame == candidate_mi->mbmi.ref_frame[1]) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
56
57
58
59
    if (block_idx >= 0 && candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8)
      c_mv->as_int = candidate_mi->bmi[block_idx].as_mv[1].as_int;
    else
      c_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
60
  } else {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
61
    return 0;
62
63
  }

Dmitry Kovalev's avatar
Dmitry Kovalev committed
64
  return 1;
65
}
Paul Wilkins's avatar
Paul Wilkins committed
66

67
68
// Gets candidate refenence motion vector(s) from the given mode info
// structure if they exists and do NOT match the given reference frame.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
69
70
71
72
73
74
static void get_non_matching_candidates(const MODE_INFO *candidate_mi,
                                        MV_REFERENCE_FRAME ref_frame,
                                        MV_REFERENCE_FRAME *c_ref_frame,
                                        int_mv *c_mv,
                                        MV_REFERENCE_FRAME *c2_ref_frame,
                                        int_mv *c2_mv) {
Paul Wilkins's avatar
Paul Wilkins committed
75

76
  c_mv->as_int = 0;
Paul Wilkins's avatar
Paul Wilkins committed
77
  c2_mv->as_int = 0;
78
  *c_ref_frame = INTRA_FRAME;
Paul Wilkins's avatar
Paul Wilkins committed
79
  *c2_ref_frame = INTRA_FRAME;
Paul Wilkins's avatar
Paul Wilkins committed
80

81
  // If first candidate not valid neither will be.
Ronald S. Bultje's avatar
Ronald S. Bultje committed
82
  if (candidate_mi->mbmi.ref_frame[0] > INTRA_FRAME) {
83
    // First candidate
Ronald S. Bultje's avatar
Ronald S. Bultje committed
84
85
    if (candidate_mi->mbmi.ref_frame[0] != ref_frame) {
      *c_ref_frame = candidate_mi->mbmi.ref_frame[0];
86
      c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
Paul Wilkins's avatar
Paul Wilkins committed
87
88
    }

89
    // Second candidate
Ronald S. Bultje's avatar
Ronald S. Bultje committed
90
91
    if ((candidate_mi->mbmi.ref_frame[1] > INTRA_FRAME) &&
        (candidate_mi->mbmi.ref_frame[1] != ref_frame) &&
Dmitry Kovalev's avatar
Dmitry Kovalev committed
92
        (candidate_mi->mbmi.mv[1].as_int != candidate_mi->mbmi.mv[0].as_int)) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
93
      *c2_ref_frame = candidate_mi->mbmi.ref_frame[1];
94
      c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
Paul Wilkins's avatar
Paul Wilkins committed
95
    }
Paul Wilkins's avatar
Paul Wilkins committed
96
97
98
  }
}

Paul Wilkins's avatar
Paul Wilkins committed
99
100

// Performs mv sign inversion if indicated by the reference frame combination.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
101
102
103
static void scale_mv(MACROBLOCKD *xd, MV_REFERENCE_FRAME this_ref_frame,
                     MV_REFERENCE_FRAME candidate_ref_frame,
                     int_mv *candidate_mv, int *ref_sign_bias) {
Paul Wilkins's avatar
Paul Wilkins committed
104
105
106
107
108

  // Sign inversion where appropriate.
  if (ref_sign_bias[candidate_ref_frame] != ref_sign_bias[this_ref_frame]) {
    candidate_mv->as_mv.row = -candidate_mv->as_mv.row;
    candidate_mv->as_mv.col = -candidate_mv->as_mv.col;
Paul Wilkins's avatar
Paul Wilkins committed
109
110
111
  }
}

Paul Wilkins's avatar
Paul Wilkins committed
112
113
// Add a candidate mv.
// Discard if it has already been seen.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
114
115
116
static void add_candidate_mv(int_mv *mv_list,  int *mv_scores,
                             int *candidate_count, int_mv candidate_mv,
                             int weight) {
Paul Wilkins's avatar
Paul Wilkins committed
117
118
119
120
121
122
123
124
125
  if (*candidate_count == 0) {
    mv_list[0].as_int = candidate_mv.as_int;
    mv_scores[0] = weight;
    *candidate_count += 1;
  } else if ((*candidate_count == 1) &&
             (candidate_mv.as_int != mv_list[0].as_int)) {
    mv_list[1].as_int = candidate_mv.as_int;
    mv_scores[1] = weight;
    *candidate_count += 1;
Paul Wilkins's avatar
Paul Wilkins committed
126
127
  }
}
Paul Wilkins's avatar
Paul Wilkins committed
128

Paul Wilkins's avatar
Paul Wilkins committed
129
130
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
Paul Wilkins's avatar
Paul Wilkins committed
131
//
Ronald S. Bultje's avatar
Ronald S. Bultje committed
132
133
134
135
void vp9_find_mv_refs_idx(VP9_COMMON *cm, MACROBLOCKD *xd, MODE_INFO *here,
                          MODE_INFO *lf_here, MV_REFERENCE_FRAME ref_frame,
                          int_mv *mv_ref_list, int *ref_sign_bias,
                          int block_idx) {
Paul Wilkins's avatar
Paul Wilkins committed
136
137
  int i;
  MODE_INFO *candidate_mi;
Paul Wilkins's avatar
Paul Wilkins committed
138
  MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
Paul Wilkins's avatar
Paul Wilkins committed
139
  int_mv c_refmv;
Paul Wilkins's avatar
Paul Wilkins committed
140
  int_mv c2_refmv;
Paul Wilkins's avatar
Paul Wilkins committed
141
  MV_REFERENCE_FRAME c_ref_frame;
Paul Wilkins's avatar
Paul Wilkins committed
142
  MV_REFERENCE_FRAME c2_ref_frame;
Paul Wilkins's avatar
Paul Wilkins committed
143
  int candidate_scores[MAX_MV_REF_CANDIDATES];
Paul Wilkins's avatar
Paul Wilkins committed
144
  int refmv_count = 0;
145
  int split_count = 0;
146
  int (*mv_ref_search)[2];
147
  const int mi_col = get_mi_col(xd);
Paul Wilkins's avatar
Paul Wilkins committed
148
149
150
  int intra_count = 0;
  int zero_count = 0;
  int newmv_count = 0;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
151
  int x_idx = 0, y_idx = 0;
Paul Wilkins's avatar
Paul Wilkins committed
152

Paul Wilkins's avatar
Paul Wilkins committed
153
  // Blank the reference vector lists and other local structures.
Paul Wilkins's avatar
Paul Wilkins committed
154
  vpx_memset(mv_ref_list, 0, sizeof(int_mv) * MAX_MV_REF_CANDIDATES);
Paul Wilkins's avatar
Paul Wilkins committed
155
156
  vpx_memset(candidate_scores, 0, sizeof(candidate_scores));

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
    int pixels_wide = 4 * b_width_log2(mbmi->sb_type);
    int pixels_high = 4 * b_height_log2(mbmi->sb_type);
    int pixels_square = 0;

    if (xd->mb_to_right_edge < 0)
      pixels_wide += (xd->mb_to_right_edge >> 3);

    if (xd->mb_to_bottom_edge < 0)
      pixels_high += (xd->mb_to_bottom_edge >> 3);

    if ( pixels_wide < pixels_high )
      pixels_square = pixels_wide;
    else
      pixels_square = pixels_high;

    if (pixels_square == 64) {
      mv_ref_search = sb64_mv_ref_search;
    } else if (pixels_square == 32) {
      mv_ref_search = sb_mv_ref_search;
    } else if (pixels_square == 16) {
      mv_ref_search = mb_mv_ref_search;
    } else {
      mv_ref_search = b_mv_ref_search;
      if (mbmi->sb_type < BLOCK_SIZE_SB8X8) {
        x_idx = block_idx & 1;
        y_idx = block_idx >> 1;
      }
    }
  }
  else {
    if (mbmi->sb_type == BLOCK_SIZE_SB64X64) {
      mv_ref_search = sb64_mv_ref_search;
    } else if (mbmi->sb_type >= BLOCK_SIZE_SB32X32) {
      mv_ref_search = sb_mv_ref_search;
    } else if (mbmi->sb_type >= BLOCK_SIZE_MB16X16) {
      mv_ref_search = mb_mv_ref_search;
    } else {
      mv_ref_search = b_mv_ref_search;
      if (mbmi->sb_type < BLOCK_SIZE_SB8X8) {
        x_idx = block_idx & 1;
        y_idx = block_idx >> 1;
      }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
200
    }
201
  }
202
203
204

  // We first scan for candidate vectors that match the current reference frame
  // Look at nearest neigbours
Paul Wilkins's avatar
Paul Wilkins committed
205
  for (i = 0; i < 2; ++i) {
206
    const int mi_search_col = mi_col + mv_ref_search[i][0];
207

208
209
    if ((mi_search_col >= cm->cur_tile_mi_col_start) &&
        (mi_search_col < cm->cur_tile_mi_col_end) &&
Jingning Han's avatar
Jingning Han committed
210
        ((mv_ref_search[i][1] << 6) >= xd->mb_to_top_edge)) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
211
      int b;
Paul Wilkins's avatar
Paul Wilkins committed
212
213
214
215

      candidate_mi = here + mv_ref_search[i][0] +
                     (mv_ref_search[i][1] * xd->mode_info_stride);

Ronald S. Bultje's avatar
Ronald S. Bultje committed
216
217
218
219
220
221
222
223
224
      if (block_idx >= 0) {
        if (mv_ref_search[i][0])
          b = 1 + y_idx * 2;
        else
          b = 2 + x_idx;
      } else {
        b = -1;
      }
      if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv, b)) {
Paul Wilkins's avatar
Paul Wilkins committed
225
226
        add_candidate_mv(mv_ref_list, candidate_scores,
                         &refmv_count, c_refmv, 16);
Paul Wilkins's avatar
Paul Wilkins committed
227
      }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
228
      split_count += (candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8 &&
Ronald S. Bultje's avatar
Ronald S. Bultje committed
229
                      candidate_mi->mbmi.ref_frame[0] != INTRA_FRAME);
Paul Wilkins's avatar
Paul Wilkins committed
230
231
232
233
234

      // Count number of neihgbours coded intra and zeromv
      intra_count += (candidate_mi->mbmi.mode < NEARESTMV);
      zero_count += (candidate_mi->mbmi.mode == ZEROMV);
      newmv_count += (candidate_mi->mbmi.mode >= NEWMV);
Paul Wilkins's avatar
Paul Wilkins committed
235
236
    }
  }
Paul Wilkins's avatar
Paul Wilkins committed
237

238
239
  // More distant neigbours
  for (i = 2; (i < MVREF_NEIGHBOURS) &&
Paul Wilkins's avatar
Paul Wilkins committed
240
              (refmv_count < MAX_MV_REF_CANDIDATES); ++i) {
241
    const int mi_search_col = mi_col + mv_ref_search[i][0];
242

243
244
    if ((mi_search_col >= cm->cur_tile_mi_col_start) &&
        (mi_search_col < cm->cur_tile_mi_col_end) &&
Jingning Han's avatar
Jingning Han committed
245
        ((mv_ref_search[i][1] << 6) >= xd->mb_to_top_edge)) {
Paul Wilkins's avatar
Paul Wilkins committed
246
247
248
      candidate_mi = here + mv_ref_search[i][0] +
                     (mv_ref_search[i][1] * xd->mode_info_stride);

Ronald S. Bultje's avatar
Ronald S. Bultje committed
249
      if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv, -1)) {
Paul Wilkins's avatar
Paul Wilkins committed
250
251
        add_candidate_mv(mv_ref_list, candidate_scores,
                         &refmv_count, c_refmv, 16);
252
253
254
      }
    }
  }
Paul Wilkins's avatar
Paul Wilkins committed
255

Paul Wilkins's avatar
Paul Wilkins committed
256
257
258
  // Look in the last frame if it exists
  if (lf_here && (refmv_count < MAX_MV_REF_CANDIDATES)) {
    candidate_mi = lf_here;
259
    if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv, -1)) {
Paul Wilkins's avatar
Paul Wilkins committed
260
261
      add_candidate_mv(mv_ref_list, candidate_scores,
                       &refmv_count, c_refmv, 16);
Paul Wilkins's avatar
Paul Wilkins committed
262
263
264
    }
  }

265
266
267
268
  // If we have not found enough candidates consider ones where the
  // reference frame does not match. Break out when we have
  // MAX_MV_REF_CANDIDATES candidates.
  // Look first at spatial neighbours
Paul Wilkins's avatar
Paul Wilkins committed
269
270
  for (i = 0; (i < MVREF_NEIGHBOURS) &&
              (refmv_count < MAX_MV_REF_CANDIDATES); ++i) {
271
    const int mi_search_col = mi_col + mv_ref_search[i][0];
Paul Wilkins's avatar
Paul Wilkins committed
272

273
274
    if ((mi_search_col >= cm->cur_tile_mi_col_start) &&
        (mi_search_col < cm->cur_tile_mi_col_end) &&
Jingning Han's avatar
Jingning Han committed
275
        ((mv_ref_search[i][1] << 6) >= xd->mb_to_top_edge)) {
Paul Wilkins's avatar
Paul Wilkins committed
276
277
278
279
280
281
282
283
284
      candidate_mi = here + mv_ref_search[i][0] +
                     (mv_ref_search[i][1] * xd->mode_info_stride);

      get_non_matching_candidates(candidate_mi, ref_frame,
                                  &c_ref_frame, &c_refmv,
                                  &c2_ref_frame, &c2_refmv);

      if (c_ref_frame != INTRA_FRAME) {
        scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias);
Paul Wilkins's avatar
Paul Wilkins committed
285
286
        add_candidate_mv(mv_ref_list, candidate_scores,
                         &refmv_count, c_refmv, 1);
Paul Wilkins's avatar
Paul Wilkins committed
287
      }
288

Paul Wilkins's avatar
Paul Wilkins committed
289
290
      if (c2_ref_frame != INTRA_FRAME) {
        scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias);
Paul Wilkins's avatar
Paul Wilkins committed
291
292
        add_candidate_mv(mv_ref_list, candidate_scores,
                         &refmv_count, c2_refmv, 1);
293
294
295
      }
    }
  }
Paul Wilkins's avatar
Paul Wilkins committed
296

297
  // Look at the last frame if it exists
Paul Wilkins's avatar
Paul Wilkins committed
298
  if (lf_here && (refmv_count < MAX_MV_REF_CANDIDATES)) {
299
300
301
302
303
304
305
    candidate_mi = lf_here;
    get_non_matching_candidates(candidate_mi, ref_frame,
                                &c_ref_frame, &c_refmv,
                                &c2_ref_frame, &c2_refmv);

    if (c_ref_frame != INTRA_FRAME) {
      scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias);
Paul Wilkins's avatar
Paul Wilkins committed
306
      add_candidate_mv(mv_ref_list, candidate_scores,
Paul Wilkins's avatar
Paul Wilkins committed
307
                       &refmv_count, c_refmv, 1);
308
309
310
311
    }

    if (c2_ref_frame != INTRA_FRAME) {
      scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias);
Paul Wilkins's avatar
Paul Wilkins committed
312
      add_candidate_mv(mv_ref_list, candidate_scores,
Paul Wilkins's avatar
Paul Wilkins committed
313
                       &refmv_count, c2_refmv, 1);
Paul Wilkins's avatar
Paul Wilkins committed
314
315
316
    }
  }

Paul Wilkins's avatar
Paul Wilkins committed
317
318
319
320
321
322
  if (!intra_count) {
    if (!newmv_count) {
      // 0 = both zero mv
      // 1 = one zero mv + one a predicted mv
      // 2 = two predicted mvs
      mbmi->mb_mode_context[ref_frame] = 2 - zero_count;
Paul Wilkins's avatar
Paul Wilkins committed
323
    } else {
Paul Wilkins's avatar
Paul Wilkins committed
324
325
326
      // 3 = one predicted/zero and one new mv
      // 4 = two new mvs
      mbmi->mb_mode_context[ref_frame] = 2 + newmv_count;
Paul Wilkins's avatar
Paul Wilkins committed
327
328
    }
  } else {
Paul Wilkins's avatar
Paul Wilkins committed
329
330
331
    // 5 = one intra neighbour + x
    // 6 = two intra neighbours
    mbmi->mb_mode_context[ref_frame] = 4 + intra_count;
Paul Wilkins's avatar
Paul Wilkins committed
332
333
  }

Paul Wilkins's avatar
Paul Wilkins committed
334
  // Clamp vectors
Paul Wilkins's avatar
Paul Wilkins committed
335
  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
Paul Wilkins's avatar
Paul Wilkins committed
336
    clamp_mv_ref(xd, &mv_ref_list[i]);
337
  }
Paul Wilkins's avatar
Paul Wilkins committed
338
}