3 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
5 * Use of this source code is governed by a BSD-style license
6 * that can be found in the LICENSE file in the root of the source
7 * tree. An additional intellectual property rights grant can be found
8 * in the file PATENTS. All contributing project authors may
9 * be found in the AUTHORS file in the root of the source tree.
12 #include "vp9/common/vp9_mvref_common.h"
14 // This function searches the neighbourhood 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 const TileInfo
*const tile
,
18 MODE_INFO
*mi
, MV_REFERENCE_FRAME ref_frame
,
20 int block
, int mi_row
, int mi_col
) {
21 const int *ref_sign_bias
= cm
->ref_frame_sign_bias
;
22 int i
, refmv_count
= 0;
23 const MODE_INFO
*prev_mi
= !cm
->error_resilient_mode
&& cm
->prev_mi
24 ? cm
->prev_mi
[mi_row
* xd
->mi_stride
+ mi_col
].src_mi
26 const MB_MODE_INFO
*const prev_mbmi
= prev_mi
? &prev_mi
->src_mi
->mbmi
: NULL
;
27 const POSITION
*const mv_ref_search
= mv_ref_blocks
[mi
->mbmi
.sb_type
];
28 int different_ref_found
= 0;
29 int context_counter
= 0;
31 // Blank the reference vector list
32 vpx_memset(mv_ref_list
, 0, sizeof(*mv_ref_list
) * MAX_MV_REF_CANDIDATES
);
34 // The nearest 2 blocks are treated differently
35 // if the size < 8x8 we get the mv from the bmi substructure,
36 // and we also need to keep a mode count.
37 for (i
= 0; i
< 2; ++i
) {
38 const POSITION
*const mv_ref
= &mv_ref_search
[i
];
39 if (is_inside(tile
, mi_col
, mi_row
, cm
->mi_rows
, mv_ref
)) {
40 const MODE_INFO
*const candidate_mi
= xd
->mi
[mv_ref
->col
+ mv_ref
->row
*
41 xd
->mi_stride
].src_mi
;
42 const MB_MODE_INFO
*const candidate
= &candidate_mi
->mbmi
;
43 // Keep counts for entropy encoding.
44 context_counter
+= mode_2_counter
[candidate
->mode
];
45 different_ref_found
= 1;
47 if (candidate
->ref_frame
[0] == ref_frame
)
48 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi
, 0, mv_ref
->col
, block
),
49 refmv_count
, mv_ref_list
, Done
);
50 else if (candidate
->ref_frame
[1] == ref_frame
)
51 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi
, 1, mv_ref
->col
, block
),
52 refmv_count
, mv_ref_list
, Done
);
56 // Check the rest of the neighbors in much the same way
57 // as before except we don't need to keep track of sub blocks or
59 for (; i
< MVREF_NEIGHBOURS
; ++i
) {
60 const POSITION
*const mv_ref
= &mv_ref_search
[i
];
61 if (is_inside(tile
, mi_col
, mi_row
, cm
->mi_rows
, mv_ref
)) {
62 const MB_MODE_INFO
*const candidate
= &xd
->mi
[mv_ref
->col
+ mv_ref
->row
*
63 xd
->mi_stride
].src_mi
->mbmi
;
64 different_ref_found
= 1;
66 if (candidate
->ref_frame
[0] == ref_frame
)
67 ADD_MV_REF_LIST(candidate
->mv
[0], refmv_count
, mv_ref_list
, Done
);
68 else if (candidate
->ref_frame
[1] == ref_frame
)
69 ADD_MV_REF_LIST(candidate
->mv
[1], refmv_count
, mv_ref_list
, Done
);
73 // Check the last frame's mode and mv info.
75 if (prev_mbmi
->ref_frame
[0] == ref_frame
)
76 ADD_MV_REF_LIST(prev_mbmi
->mv
[0], refmv_count
, mv_ref_list
, Done
);
77 else if (prev_mbmi
->ref_frame
[1] == ref_frame
)
78 ADD_MV_REF_LIST(prev_mbmi
->mv
[1], refmv_count
, mv_ref_list
, Done
);
81 // Since we couldn't find 2 mvs from the same reference frame
82 // go back through the neighbors and find motion vectors from
83 // different reference frames.
84 if (different_ref_found
) {
85 for (i
= 0; i
< MVREF_NEIGHBOURS
; ++i
) {
86 const POSITION
*mv_ref
= &mv_ref_search
[i
];
87 if (is_inside(tile
, mi_col
, mi_row
, cm
->mi_rows
, mv_ref
)) {
88 const MB_MODE_INFO
*const candidate
= &xd
->mi
[mv_ref
->col
+ mv_ref
->row
89 * xd
->mi_stride
].src_mi
->mbmi
;
91 // If the candidate is INTRA we don't want to consider its mv.
92 IF_DIFF_REF_FRAME_ADD_MV(candidate
, ref_frame
, ref_sign_bias
,
93 refmv_count
, mv_ref_list
, Done
);
98 // Since we still don't have a candidate we'll try the last frame.
100 IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi
, ref_frame
, ref_sign_bias
, refmv_count
,
105 mi
->mbmi
.mode_context
[ref_frame
] = counter_to_context
[context_counter
];
108 for (i
= 0; i
< MAX_MV_REF_CANDIDATES
; ++i
)
109 clamp_mv_ref(&mv_ref_list
[i
].as_mv
, xd
);
112 void vp9_find_mv_refs(const VP9_COMMON
*cm
, const MACROBLOCKD
*xd
,
113 const TileInfo
*const tile
,
114 MODE_INFO
*mi
, MV_REFERENCE_FRAME ref_frame
,
116 int mi_row
, int mi_col
) {
117 find_mv_refs_idx(cm
, xd
, tile
, mi
, ref_frame
, mv_ref_list
, -1,
121 static void lower_mv_precision(MV
*mv
, int allow_hp
) {
122 const int use_hp
= allow_hp
&& vp9_use_mv_hp(mv
);
125 mv
->row
+= (mv
->row
> 0 ? -1 : 1);
127 mv
->col
+= (mv
->col
> 0 ? -1 : 1);
131 void vp9_find_best_ref_mvs(MACROBLOCKD
*xd
, int allow_hp
,
132 int_mv
*mvlist
, int_mv
*nearest
, int_mv
*near
) {
134 // Make sure all the candidates are properly clamped etc
135 for (i
= 0; i
< MAX_MV_REF_CANDIDATES
; ++i
) {
136 lower_mv_precision(&mvlist
[i
].as_mv
, allow_hp
);
137 clamp_mv2(&mvlist
[i
].as_mv
, xd
);
139 *nearest
= mvlist
[0];
143 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON
*cm
, MACROBLOCKD
*xd
,
144 const TileInfo
*const tile
,
145 int block
, int ref
, int mi_row
, int mi_col
,
146 int_mv
*nearest
, int_mv
*near
) {
147 int_mv mv_list
[MAX_MV_REF_CANDIDATES
];
148 MODE_INFO
*const mi
= xd
->mi
[0].src_mi
;
149 b_mode_info
*bmi
= mi
->bmi
;
152 assert(MAX_MV_REF_CANDIDATES
== 2);
154 find_mv_refs_idx(cm
, xd
, tile
, mi
, mi
->mbmi
.ref_frame
[ref
], mv_list
, block
,
160 nearest
->as_int
= mv_list
[0].as_int
;
161 near
->as_int
= mv_list
[1].as_int
;
165 nearest
->as_int
= bmi
[0].as_mv
[ref
].as_int
;
166 for (n
= 0; n
< MAX_MV_REF_CANDIDATES
; ++n
)
167 if (nearest
->as_int
!= mv_list
[n
].as_int
) {
168 near
->as_int
= mv_list
[n
].as_int
;
173 int_mv candidates
[2 + MAX_MV_REF_CANDIDATES
];
174 candidates
[0] = bmi
[1].as_mv
[ref
];
175 candidates
[1] = bmi
[0].as_mv
[ref
];
176 candidates
[2] = mv_list
[0];
177 candidates
[3] = mv_list
[1];
179 nearest
->as_int
= bmi
[2].as_mv
[ref
].as_int
;
180 for (n
= 0; n
< 2 + MAX_MV_REF_CANDIDATES
; ++n
)
181 if (nearest
->as_int
!= candidates
[n
].as_int
) {
182 near
->as_int
= candidates
[n
].as_int
;
188 assert("Invalid block index.");