|
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 |
|
12 #include <limits.h> |
|
13 #include "vpx_config.h" |
|
14 #include "onyx_int.h" |
|
15 #include "mr_dissim.h" |
|
16 #include "vpx_mem/vpx_mem.h" |
|
17 #include "rdopt.h" |
|
18 |
|
19 void vp8_cal_low_res_mb_cols(VP8_COMP *cpi) |
|
20 { |
|
21 int low_res_w; |
|
22 |
|
23 /* Support arbitrary down-sampling factor */ |
|
24 unsigned int iw = cpi->oxcf.Width*cpi->oxcf.mr_down_sampling_factor.den |
|
25 + cpi->oxcf.mr_down_sampling_factor.num - 1; |
|
26 |
|
27 low_res_w = iw/cpi->oxcf.mr_down_sampling_factor.num; |
|
28 cpi->mr_low_res_mb_cols = ((low_res_w + 15) >> 4); |
|
29 } |
|
30 |
|
31 #define GET_MV(x) \ |
|
32 if(x->mbmi.ref_frame !=INTRA_FRAME) \ |
|
33 { \ |
|
34 mvx[cnt] = x->mbmi.mv.as_mv.row; \ |
|
35 mvy[cnt] = x->mbmi.mv.as_mv.col; \ |
|
36 cnt++; \ |
|
37 } |
|
38 |
|
39 #define GET_MV_SIGN(x) \ |
|
40 if(x->mbmi.ref_frame !=INTRA_FRAME) \ |
|
41 { \ |
|
42 mvx[cnt] = x->mbmi.mv.as_mv.row; \ |
|
43 mvy[cnt] = x->mbmi.mv.as_mv.col; \ |
|
44 if (cm->ref_frame_sign_bias[x->mbmi.ref_frame] \ |
|
45 != cm->ref_frame_sign_bias[tmp->mbmi.ref_frame]) \ |
|
46 { \ |
|
47 mvx[cnt] *= -1; \ |
|
48 mvy[cnt] *= -1; \ |
|
49 } \ |
|
50 cnt++; \ |
|
51 } |
|
52 |
|
53 void vp8_cal_dissimilarity(VP8_COMP *cpi) |
|
54 { |
|
55 VP8_COMMON *cm = &cpi->common; |
|
56 int i; |
|
57 |
|
58 /* Note: The first row & first column in mip are outside the frame, which |
|
59 * were initialized to all 0.(ref_frame, mode, mv...) |
|
60 * Their ref_frame = 0 means they won't be counted in the following |
|
61 * calculation. |
|
62 */ |
|
63 if (cpi->oxcf.mr_total_resolutions >1 |
|
64 && cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) |
|
65 { |
|
66 /* Store info for show/no-show frames for supporting alt_ref. |
|
67 * If parent frame is alt_ref, child has one too. |
|
68 */ |
|
69 LOWER_RES_FRAME_INFO* store_info |
|
70 = (LOWER_RES_FRAME_INFO*)cpi->oxcf.mr_low_res_mode_info; |
|
71 |
|
72 store_info->frame_type = cm->frame_type; |
|
73 |
|
74 if(cm->frame_type != KEY_FRAME) |
|
75 { |
|
76 store_info->is_frame_dropped = 0; |
|
77 for (i = 1; i < MAX_REF_FRAMES; i++) |
|
78 store_info->low_res_ref_frames[i] = cpi->current_ref_frames[i]; |
|
79 } |
|
80 |
|
81 if(cm->frame_type != KEY_FRAME) |
|
82 { |
|
83 int mb_row; |
|
84 int mb_col; |
|
85 /* Point to beginning of allocated MODE_INFO arrays. */ |
|
86 MODE_INFO *tmp = cm->mip + cm->mode_info_stride; |
|
87 LOWER_RES_MB_INFO* store_mode_info = store_info->mb_info; |
|
88 |
|
89 for (mb_row = 0; mb_row < cm->mb_rows; mb_row ++) |
|
90 { |
|
91 tmp++; |
|
92 for (mb_col = 0; mb_col < cm->mb_cols; mb_col ++) |
|
93 { |
|
94 int dissim = INT_MAX; |
|
95 |
|
96 if(tmp->mbmi.ref_frame !=INTRA_FRAME) |
|
97 { |
|
98 int mvx[8]; |
|
99 int mvy[8]; |
|
100 int mmvx; |
|
101 int mmvy; |
|
102 int cnt=0; |
|
103 const MODE_INFO *here = tmp; |
|
104 const MODE_INFO *above = here - cm->mode_info_stride; |
|
105 const MODE_INFO *left = here - 1; |
|
106 const MODE_INFO *aboveleft = above - 1; |
|
107 const MODE_INFO *aboveright = NULL; |
|
108 const MODE_INFO *right = NULL; |
|
109 const MODE_INFO *belowleft = NULL; |
|
110 const MODE_INFO *below = NULL; |
|
111 const MODE_INFO *belowright = NULL; |
|
112 |
|
113 /* If alternate reference frame is used, we have to |
|
114 * check sign of MV. */ |
|
115 if(cpi->oxcf.play_alternate) |
|
116 { |
|
117 /* Gather mv of neighboring MBs */ |
|
118 GET_MV_SIGN(above) |
|
119 GET_MV_SIGN(left) |
|
120 GET_MV_SIGN(aboveleft) |
|
121 |
|
122 if(mb_col < (cm->mb_cols-1)) |
|
123 { |
|
124 right = here + 1; |
|
125 aboveright = above + 1; |
|
126 GET_MV_SIGN(right) |
|
127 GET_MV_SIGN(aboveright) |
|
128 } |
|
129 |
|
130 if(mb_row < (cm->mb_rows-1)) |
|
131 { |
|
132 below = here + cm->mode_info_stride; |
|
133 belowleft = below - 1; |
|
134 GET_MV_SIGN(below) |
|
135 GET_MV_SIGN(belowleft) |
|
136 } |
|
137 |
|
138 if(mb_col < (cm->mb_cols-1) |
|
139 && mb_row < (cm->mb_rows-1)) |
|
140 { |
|
141 belowright = below + 1; |
|
142 GET_MV_SIGN(belowright) |
|
143 } |
|
144 }else |
|
145 { |
|
146 /* No alt_ref and gather mv of neighboring MBs */ |
|
147 GET_MV(above) |
|
148 GET_MV(left) |
|
149 GET_MV(aboveleft) |
|
150 |
|
151 if(mb_col < (cm->mb_cols-1)) |
|
152 { |
|
153 right = here + 1; |
|
154 aboveright = above + 1; |
|
155 GET_MV(right) |
|
156 GET_MV(aboveright) |
|
157 } |
|
158 |
|
159 if(mb_row < (cm->mb_rows-1)) |
|
160 { |
|
161 below = here + cm->mode_info_stride; |
|
162 belowleft = below - 1; |
|
163 GET_MV(below) |
|
164 GET_MV(belowleft) |
|
165 } |
|
166 |
|
167 if(mb_col < (cm->mb_cols-1) |
|
168 && mb_row < (cm->mb_rows-1)) |
|
169 { |
|
170 belowright = below + 1; |
|
171 GET_MV(belowright) |
|
172 } |
|
173 } |
|
174 |
|
175 if (cnt > 0) |
|
176 { |
|
177 int max_mvx = mvx[0]; |
|
178 int min_mvx = mvx[0]; |
|
179 int max_mvy = mvy[0]; |
|
180 int min_mvy = mvy[0]; |
|
181 int i; |
|
182 |
|
183 if (cnt > 1) |
|
184 { |
|
185 for (i=1; i< cnt; i++) |
|
186 { |
|
187 if (mvx[i] > max_mvx) max_mvx = mvx[i]; |
|
188 else if (mvx[i] < min_mvx) min_mvx = mvx[i]; |
|
189 if (mvy[i] > max_mvy) max_mvy = mvy[i]; |
|
190 else if (mvy[i] < min_mvy) min_mvy = mvy[i]; |
|
191 } |
|
192 } |
|
193 |
|
194 mmvx = MAX(abs(min_mvx - here->mbmi.mv.as_mv.row), |
|
195 abs(max_mvx - here->mbmi.mv.as_mv.row)); |
|
196 mmvy = MAX(abs(min_mvy - here->mbmi.mv.as_mv.col), |
|
197 abs(max_mvy - here->mbmi.mv.as_mv.col)); |
|
198 dissim = MAX(mmvx, mmvy); |
|
199 } |
|
200 } |
|
201 |
|
202 /* Store mode info for next resolution encoding */ |
|
203 store_mode_info->mode = tmp->mbmi.mode; |
|
204 store_mode_info->ref_frame = tmp->mbmi.ref_frame; |
|
205 store_mode_info->mv.as_int = tmp->mbmi.mv.as_int; |
|
206 store_mode_info->dissim = dissim; |
|
207 tmp++; |
|
208 store_mode_info++; |
|
209 } |
|
210 } |
|
211 } |
|
212 } |
|
213 } |
|
214 |
|
215 /* This function is called only when this frame is dropped at current |
|
216 resolution level. */ |
|
217 void vp8_store_drop_frame_info(VP8_COMP *cpi) |
|
218 { |
|
219 /* If the frame is dropped in lower-resolution encoding, this information |
|
220 is passed to higher resolution level so that the encoder knows there |
|
221 is no mode & motion info available. |
|
222 */ |
|
223 if (cpi->oxcf.mr_total_resolutions >1 |
|
224 && cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) |
|
225 { |
|
226 /* Store info for show/no-show frames for supporting alt_ref. |
|
227 * If parent frame is alt_ref, child has one too. |
|
228 */ |
|
229 LOWER_RES_FRAME_INFO* store_info |
|
230 = (LOWER_RES_FRAME_INFO*)cpi->oxcf.mr_low_res_mode_info; |
|
231 |
|
232 /* Set frame_type to be INTER_FRAME since we won't drop key frame. */ |
|
233 store_info->frame_type = INTER_FRAME; |
|
234 store_info->is_frame_dropped = 1; |
|
235 } |
|
236 } |