vp9_mvref_common.c 7.36 KB
Newer Older
1

2 3 4 5 6 7 8 9 10 11
/*
 *  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.
 */

12
#include "vp9/common/vp9_mvref_common.h"
13

14
// This function searches the neighborhood of a given MB/SB
15
// to try and find candidate reference vectors.
16
static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
17
                             MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
18
                             int_mv *mv_ref_list,
19
                             int block, int mi_row, int mi_col,
20
                             uint8_t *mode_context) {
21 22
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
  int i, refmv_count = 0;
23
  const POSITION *const mv_ref_search = mv_ref_blocks[mi->sb_type];
Jim Bankoski's avatar
Jim Bankoski committed
24 25
  int different_ref_found = 0;
  int context_counter = 0;
26
  const MV_REF *const prev_frame_mvs = cm->use_prev_frame_mvs ?
27
      cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col : NULL;
Scott LaVarnway's avatar
Scott LaVarnway committed
28
  const TileInfo *const tile = &xd->tile;
Jim Bankoski's avatar
Jim Bankoski committed
29 30

  // Blank the reference vector list
James Zern's avatar
James Zern committed
31
  memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
Jim Bankoski's avatar
Jim Bankoski committed
32 33 34 35

  // The nearest 2 blocks are treated differently
  // if the size < 8x8 we get the mv from the bmi substructure,
  // and we also need to keep a mode count.
36
  for (i = 0; i < 2; ++i) {
37
    const POSITION *const mv_ref = &mv_ref_search[i];
James Zern's avatar
James Zern committed
38
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
39
      const MODE_INFO *const candidate_mi = xd->mi[mv_ref->col + mv_ref->row *
40
                                                   xd->mi_stride];
41
      // Keep counts for entropy encoding.
42
      context_counter += mode_2_counter[candidate_mi->mode];
43
      different_ref_found = 1;
44

45
      if (candidate_mi->ref_frame[0] == ref_frame)
46 47
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
                        refmv_count, mv_ref_list, Done);
48
      else if (candidate_mi->ref_frame[1] == ref_frame)
49 50
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
                        refmv_count, mv_ref_list, Done);
51 52
    }
  }
53

Jim Bankoski's avatar
Jim Bankoski committed
54 55 56
  // Check the rest of the neighbors in much the same way
  // as before except we don't need to keep track of sub blocks or
  // mode counts.
57
  for (; i < MVREF_NEIGHBOURS; ++i) {
58
    const POSITION *const mv_ref = &mv_ref_search[i];
James Zern's avatar
James Zern committed
59
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
60 61
      const MODE_INFO *const candidate_mi =
          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
62
      different_ref_found = 1;
63

64 65 66 67
      if (candidate_mi->ref_frame[0] == ref_frame)
        ADD_MV_REF_LIST(candidate_mi->mv[0], refmv_count, mv_ref_list, Done);
      else if (candidate_mi->ref_frame[1] == ref_frame)
        ADD_MV_REF_LIST(candidate_mi->mv[1], refmv_count, mv_ref_list, Done);
68 69
    }
  }
70

Jim Bankoski's avatar
Jim Bankoski committed
71
  // Check the last frame's mode and mv info.
72 73 74 75 76 77
  if (cm->use_prev_frame_mvs) {
    if (prev_frame_mvs->ref_frame[0] == ref_frame) {
      ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, Done);
    } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
      ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, Done);
    }
Jim Bankoski's avatar
Jim Bankoski committed
78 79 80 81 82 83
  }

  // Since we couldn't find 2 mvs from the same reference frame
  // go back through the neighbors and find motion vectors from
  // different reference frames.
  if (different_ref_found) {
84
    for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
85
      const POSITION *mv_ref = &mv_ref_search[i];
James Zern's avatar
James Zern committed
86
      if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
87 88
        const MODE_INFO *const candidate_mi =
            xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
89 90

        // If the candidate is INTRA we don't want to consider its mv.
91
        IF_DIFF_REF_FRAME_ADD_MV(candidate_mi, ref_frame, ref_sign_bias,
92
                                 refmv_count, mv_ref_list, Done);
93
      }
94 95 96
    }
  }

Jim Bankoski's avatar
Jim Bankoski committed
97
  // Since we still don't have a candidate we'll try the last frame.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
  if (cm->use_prev_frame_mvs) {
    if (prev_frame_mvs->ref_frame[0] != ref_frame &&
        prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
      int_mv mv = prev_frame_mvs->mv[0];
      if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
          ref_sign_bias[ref_frame]) {
        mv.as_mv.row *= -1;
        mv.as_mv.col *= -1;
      }
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
    }

    if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
        prev_frame_mvs->ref_frame[1] != ref_frame &&
        prev_frame_mvs->mv[1].as_int != prev_frame_mvs->mv[0].as_int) {
      int_mv mv = prev_frame_mvs->mv[1];
      if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
          ref_sign_bias[ref_frame]) {
        mv.as_mv.row *= -1;
        mv.as_mv.col *= -1;
      }
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
    }
  }
Paul Wilkins's avatar
Paul Wilkins committed
122

Jim Bankoski's avatar
Jim Bankoski committed
123 124
 Done:

125
  mode_context[ref_frame] = counter_to_context[context_counter];
Jim Bankoski's avatar
Jim Bankoski committed
126

127
  // Clamp vectors
128 129
  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
    clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
130
}
131

132
void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
hkuang's avatar
hkuang committed
133 134
                      MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
                      int_mv *mv_ref_list,
135
                      int mi_row, int mi_col,
136
                      uint8_t *mode_context) {
Scott LaVarnway's avatar
Scott LaVarnway committed
137
  find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1,
138
                   mi_row, mi_col, mode_context);
139 140
}

141
void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
142 143
                           int_mv *mvlist, int_mv *nearest_mv,
                           int_mv *near_mv) {
144 145 146 147 148 149
  int i;
  // Make sure all the candidates are properly clamped etc
  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
    lower_mv_precision(&mvlist[i].as_mv, allow_hp);
    clamp_mv2(&mvlist[i].as_mv, xd);
  }
150 151
  *nearest_mv = mvlist[0];
  *near_mv = mvlist[1];
152 153 154 155
}

void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
                                   int block, int ref, int mi_row, int mi_col,
156 157
                                   int_mv *nearest_mv, int_mv *near_mv,
                                   uint8_t *mode_context) {
158
  int_mv mv_list[MAX_MV_REF_CANDIDATES];
159
  MODE_INFO *const mi = xd->mi[0];
160 161 162 163 164
  b_mode_info *bmi = mi->bmi;
  int n;

  assert(MAX_MV_REF_CANDIDATES == 2);

165
  find_mv_refs_idx(cm, xd, mi, mi->ref_frame[ref], mv_list, block,
166
                   mi_row, mi_col, mode_context);
167

168
  near_mv->as_int = 0;
169 170
  switch (block) {
    case 0:
171 172
      nearest_mv->as_int = mv_list[0].as_int;
      near_mv->as_int = mv_list[1].as_int;
173 174 175
      break;
    case 1:
    case 2:
176
      nearest_mv->as_int = bmi[0].as_mv[ref].as_int;
177
      for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
178 179
        if (nearest_mv->as_int != mv_list[n].as_int) {
          near_mv->as_int = mv_list[n].as_int;
180 181 182 183 184 185 186 187 188 189
          break;
        }
      break;
    case 3: {
      int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
      candidates[0] = bmi[1].as_mv[ref];
      candidates[1] = bmi[0].as_mv[ref];
      candidates[2] = mv_list[0];
      candidates[3] = mv_list[1];

190
      nearest_mv->as_int = bmi[2].as_mv[ref].as_int;
191
      for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
192 193
        if (nearest_mv->as_int != candidates[n].as_int) {
          near_mv->as_int = candidates[n].as_int;
194 195 196 197 198
          break;
        }
      break;
    }
    default:
199
      assert(0 && "Invalid block index.");
200 201
  }
}