1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include <schroedinger/schro.h>
6 #include <string.h>
7 #include <limits.h>
8
9 /***
10 struct _SchroHierBm {
11 int ref_count;
12 int ref;
13 int hierarchy_levels;
14 SchroParams* params;
15 SchroFrame** downsampled_src;
16 SchroFrame** downsampled_ref;
17 SchroMotionField** downsampled_mf;
18 };
19 ***/
20
21 static int get_hier_levels (SchroHierBm * schro_hbm);
22 static int schro_hbm_ref_number (SchroHierBm * schro_hbm);
23
24
25 SchroHierBm *
schro_hbm_new(SchroEncoderFrame * frame,int ref)26 schro_hbm_new (SchroEncoderFrame * frame, int ref)
27 {
28 int i;
29 SchroEncoderFrame *ref_frame = frame->ref_frame[ref];
30 SchroHierBm *schro_hbm;
31
32 SCHRO_ASSERT (ref_frame);
33
34 schro_hbm = schro_malloc0 (sizeof (struct _SchroHierBm));
35 schro_hbm->ref_count = 1;
36 schro_hbm->hierarchy_levels = frame->encoder->downsample_levels;
37 if (frame->encoder->enable_chroma_me)
38 schro_hbm->use_chroma = TRUE;
39 else
40 schro_hbm->use_chroma = FALSE;
41 schro_hbm->hierarchy_levels = frame->encoder->downsample_levels;
42 schro_hbm->params = &frame->params;
43 schro_hbm->ref = ref;
44
45 schro_hbm->downsampled_src =
46 schro_malloc0 (sizeof (SchroFrame *) * (schro_hbm->hierarchy_levels + 1));
47 schro_hbm->downsampled_ref =
48 schro_malloc0 (sizeof (SchroFrame *) * (schro_hbm->hierarchy_levels + 1));
49 schro_hbm->downsampled_mf =
50 schro_malloc0 (sizeof (SchroMotionField *) *
51 (schro_hbm->hierarchy_levels + 1));
52
53 schro_hbm->downsampled_src[0] = schro_frame_ref (frame->filtered_frame);
54 schro_hbm->downsampled_ref[0] = schro_frame_ref (ref_frame->filtered_frame);
55 for (i = 0; schro_hbm->hierarchy_levels > i; ++i) {
56 SCHRO_ASSERT (frame->downsampled_frames[i]
57 && ref_frame->downsampled_frames[i]);
58 schro_hbm->downsampled_src[i + 1] =
59 schro_frame_ref (frame->downsampled_frames[i]);
60 schro_hbm->downsampled_ref[i + 1] =
61 schro_frame_ref (ref_frame->downsampled_frames[i]);
62 }
63 return schro_hbm;
64 }
65
66 SchroHierBm *
schro_hbm_ref(SchroHierBm * src)67 schro_hbm_ref (SchroHierBm * src)
68 {
69 SCHRO_ASSERT (src && src->ref_count > 0);
70 ++src->ref_count;
71 return src;
72 }
73
74 static void
schro_hbm_free(SchroHierBm * hbm)75 schro_hbm_free (SchroHierBm * hbm)
76 {
77 int i;
78
79 for (i = 0; hbm->hierarchy_levels + 1 > i; ++i) {
80 if (hbm->downsampled_src[i]) {
81 schro_frame_unref (hbm->downsampled_src[i]);
82 }
83 if (hbm->downsampled_ref[i]) {
84 schro_frame_unref (hbm->downsampled_ref[i]);
85 }
86 if (hbm->downsampled_mf[i]) {
87 schro_motion_field_free (hbm->downsampled_mf[i]);
88 }
89 }
90 schro_free (hbm->downsampled_mf);
91 schro_free (hbm->downsampled_ref);
92 schro_free (hbm->downsampled_src);
93 schro_free (hbm);
94 }
95
96 /* unreferences a SchroHierBm structure - if it is the last reference
97 * it frees the structure and sets its pointer to NULL
98 * if the pointer was already NULL it's a no-op */
99 void
schro_hbm_unref(SchroHierBm * schro_hbm)100 schro_hbm_unref (SchroHierBm * schro_hbm)
101 {
102 if (0 < --schro_hbm->ref_count)
103 return;
104 schro_hbm_free (schro_hbm);
105 }
106
107 static SchroFrame *
schro_hbm_src_frame(SchroHierBm * hbm,int level)108 schro_hbm_src_frame (SchroHierBm * hbm, int level)
109 {
110 SCHRO_ASSERT (hbm && 0 < hbm->ref_count && !(get_hier_levels (hbm) < level));
111 return hbm->downsampled_src[level];
112 }
113
114 static SchroFrame *
schro_hbm_ref_frame(SchroHierBm * hbm,int level)115 schro_hbm_ref_frame (SchroHierBm * hbm, int level)
116 {
117 SCHRO_ASSERT (hbm && 0 < hbm->ref_count && !(get_hier_levels (hbm) < level));
118 return hbm->downsampled_ref[level];
119 }
120
121 /* Note: it doesn't check whether the requested mf is not NULL */
122 SchroMotionField *
schro_hbm_motion_field(SchroHierBm * schro_hbm,int level)123 schro_hbm_motion_field (SchroHierBm * schro_hbm, int level)
124 {
125 SCHRO_ASSERT (schro_hbm && schro_hbm->ref_count > 0
126 && !(get_hier_levels (schro_hbm) < level));
127 return schro_hbm->downsampled_mf[level];
128 }
129
130 static void
schro_hbm_set_motion_field(SchroHierBm * hbm,SchroMotionField * mf,int level)131 schro_hbm_set_motion_field (SchroHierBm * hbm, SchroMotionField * mf, int level)
132 {
133 SCHRO_ASSERT (hbm && 0 < hbm->ref_count && !(get_hier_levels (hbm) < level));
134 hbm->downsampled_mf[level] = mf;
135 }
136
137 static SchroParams *
schro_hbm_params(SchroHierBm * schro_hbm)138 schro_hbm_params (SchroHierBm * schro_hbm)
139 {
140 SCHRO_ASSERT (schro_hbm && 0 < schro_hbm->ref_count);
141 return schro_hbm->params;
142 }
143
144 static int
schro_hbm_ref_number(SchroHierBm * schro_hbm)145 schro_hbm_ref_number (SchroHierBm * schro_hbm)
146 {
147 SCHRO_ASSERT (schro_hbm && schro_hbm->ref_count > 0);
148 return schro_hbm->ref;
149 }
150
151 static int
get_hier_levels(SchroHierBm * schro_hbm)152 get_hier_levels (SchroHierBm * schro_hbm)
153 {
154 SCHRO_ASSERT (schro_hbm);
155 return schro_hbm->hierarchy_levels;
156 }
157
158 void
schro_hbm_scan(SchroHierBm * schro_hbm)159 schro_hbm_scan (SchroHierBm * schro_hbm)
160 {
161 int i;
162 int half_scan_range = 20;
163 int n_levels = get_hier_levels (schro_hbm);
164
165 SCHRO_ASSERT (n_levels > 0);
166
167 schro_hierarchical_bm_scan_hint (schro_hbm, n_levels, half_scan_range);
168 half_scan_range >>= 1;
169 for (i = n_levels - 1; 1 <= i; --i, half_scan_range >>= 1) {
170 schro_hierarchical_bm_scan_hint (schro_hbm, i, MAX (3, half_scan_range));
171 }
172 }
173
174 void
schro_hierarchical_bm_scan_hint(SchroHierBm * schro_hbm,int shift,int h_range)175 schro_hierarchical_bm_scan_hint (SchroHierBm * schro_hbm, int shift,
176 int h_range)
177 {
178 SchroMetricScan scan;
179 SchroMotionVector *mv;
180 SchroMotionField *mf, *hint_mf = NULL;
181 SchroParams *params = schro_hbm_params (schro_hbm);
182 SchroMotionVector zero_mv;
183 SchroMetricInfo info;
184
185 int xblen = params->xbsep_luma, yblen = params->ybsep_luma;
186 int i;
187 int j;
188 int skip;
189 int shift_w[3], shift_h[3];
190 int split = 1 < shift ? 0 : (1 == shift ? 1 : 2);
191 #define LIST_LENGTH 9
192 SchroMotionVector *temp_hint_mv[LIST_LENGTH], *hint_mv[LIST_LENGTH];
193 unsigned int hint_mask;
194 int ref = schro_hbm_ref_number (schro_hbm);
195 int comp_w[3], comp_h[3];
196
197 /* sets up for block matching */
198 scan.frame = schro_hbm_src_frame (schro_hbm, shift);
199 scan.ref_frame = schro_hbm_ref_frame (schro_hbm, shift);
200
201 schro_metric_info_init (&info,
202 schro_hbm_src_frame (schro_hbm, shift),
203 schro_hbm_ref_frame (schro_hbm, shift),
204 xblen, yblen);
205
206 mf = schro_motion_field_new (params->x_num_blocks, params->y_num_blocks);
207 schro_motion_field_set (mf, split, ref + 1);
208
209 if (shift < get_hier_levels (schro_hbm)) {
210 hint_mf = schro_hbm_motion_field (schro_hbm, shift + 1);
211 }
212
213 memset (&zero_mv, 0, sizeof (zero_mv));
214 zero_mv.pred_mode = ref + 1;
215 zero_mv.split = split;
216
217 hint_mask = ~((1 << (shift + 1)) - 1);
218 skip = 1 << shift;
219
220 shift_w[0] = shift_h[0] = shift;
221 shift_w[1] = shift_w[2] =
222 shift + SCHRO_FRAME_FORMAT_H_SHIFT (scan.frame->format);
223 shift_h[1] = shift_h[2] =
224 shift + SCHRO_FRAME_FORMAT_V_SHIFT (scan.frame->format);
225 comp_w[0] = xblen;
226 comp_h[0] = yblen;
227 comp_w[1] = comp_w[2] =
228 xblen >> SCHRO_FRAME_FORMAT_H_SHIFT (scan.frame->format);
229 comp_h[1] = comp_h[2] =
230 yblen >> SCHRO_FRAME_FORMAT_V_SHIFT (scan.frame->format);
231
232 for (j = 0; j < params->y_num_blocks; j += skip) {
233 for (i = 0; i < params->x_num_blocks; i += skip) {
234 SchroFrameData orig[3];
235 int m = 0;
236 int n = 0;
237 int dx, dy;
238 int min_m;
239 int min_metric;
240 int width[3], height[3];
241 int k;
242
243 /* get source data, if possible */
244 if (!(scan.frame->width > (i * xblen) >> shift)
245 || !(scan.frame->height > (j * yblen) >> shift)) {
246 continue;
247 }
248 for (k = 0; 3 > k; ++k) {
249 schro_frame_get_subdata (scan.frame, &orig[k], k,
250 (i * xblen) >> shift_w[k], (j * yblen) >> shift_h[k]);
251 width[k] = MIN (orig[k].width, comp_w[k]);
252 height[k] = MIN (orig[k].height, comp_h[k]);
253 if (0 == k) {
254 SCHRO_ASSERT (0 < width[k] && 0 < height[k]);
255 }
256 }
257
258 /* now check all candidates */
259 /* always test the zero vector */
260 temp_hint_mv[n] = &zero_mv;
261 n++;
262
263 /* inherit from nearby parents (star-like selection) */
264 if (NULL != hint_mf) {
265 int l = i & hint_mask, k = j & hint_mask, ll, kk;
266 int offset[5][2] = { {0, 0}, {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
267 for (m = 0; m < 5; m++) {
268 ll = l + offset[m][0] * skip * 2;
269 kk = k + offset[m][1] * skip * 2;
270 if (ll >= 0 && ll < params->x_num_blocks &&
271 kk >= 0 && kk < params->y_num_blocks) {
272 mv = hint_mf->motion_vectors + kk * params->x_num_blocks + ll;
273 temp_hint_mv[n] = mv;
274 n++;
275 }
276 }
277 }
278
279 /* inherit from neighbours (only towards SE) */
280 if (i > 0) {
281 mv = mf->motion_vectors + j * params->x_num_blocks + i - skip;
282 temp_hint_mv[n] = mv;
283 n++;
284 }
285 if (j > 0) {
286 mv = mf->motion_vectors + (j - skip) * params->x_num_blocks + i;
287 temp_hint_mv[n] = mv;
288 n++;
289 }
290 if (i > 0 && j > 0) {
291 mv = mf->motion_vectors + (j - skip) * params->x_num_blocks + i - skip;
292 temp_hint_mv[n] = mv;
293 n++;
294 }
295
296 SCHRO_ASSERT (n <= LIST_LENGTH);
297
298 /* remove duplicates */
299 m = 0;
300 if (1 < n) {
301 int k, s;
302 SchroMotionVector *mv1, *mv2;
303 for (k = 0; n - 1 > k; ++k) {
304 int skip = 0;
305 mv1 = temp_hint_mv[k];
306 for (s = k + 1; n > s && !skip; ++s) {
307 mv2 = temp_hint_mv[s];
308 if (mv1->u.vec.dx[ref] == mv2->u.vec.dx[ref]
309 && mv1->u.vec.dy[ref] == mv2->u.vec.dy[ref]) {
310 skip = 1;
311 }
312 }
313 if (!skip) {
314 hint_mv[m++] = mv1;
315 }
316 }
317 hint_mv[m++] = temp_hint_mv[n - 1];
318 n = m;
319 } else {
320 hint_mv[0] = temp_hint_mv[0];
321 }
322
323 min_m = -1;
324 min_metric = INT_MAX;
325 /* choose best candidate for refinement based on SAD only. */
326 for (m = 0; m < n; m++) {
327 int metric = 0;
328
329 dx = hint_mv[m]->u.vec.dx[ref];
330 dx >>= shift;
331 dx = CLAMP (dx + ((i*xblen) >> shift), -width[0],
332 (scan.ref_frame->components + 0)->width);
333 dx -= ((i*xblen) >> shift);
334 dy = hint_mv[m]->u.vec.dy[ref];
335 dy >>= shift;
336 dy = CLAMP (dy + ((j*yblen) >> shift), -height[0],
337 (scan.ref_frame->components + 0)->height);
338 dy -= ((j*yblen) >> shift);
339 metric = schro_metric_fast_block (&info, (i*xblen)>>shift,
340 (j*yblen)>>shift, dx, dy);
341
342 if (metric < min_metric) {
343 min_metric = metric;
344 min_m = m;
345 }
346 }
347 SCHRO_ASSERT (-1 < min_m);
348
349 /* finally do block-matching around chosen candidate MV */
350 dx = hint_mv[min_m]->u.vec.dx[ref] >> shift;
351 dy = hint_mv[min_m]->u.vec.dy[ref] >> shift;
352
353 scan.block_width = width[0];
354 scan.block_height = height[0];
355 scan.x = i * xblen >> shift;
356 scan.y = j * yblen >> shift;
357 dx = MAX (-width[0] - scan.x, MIN (scan.ref_frame->width - scan.x, dx));
358 dy = MAX (-height[0] - scan.y, MIN (scan.ref_frame->height - scan.y, dy));
359 scan.gravity_x = dx;
360 scan.gravity_y = dy;
361 schro_metric_scan_setup (&scan, dx, dy, h_range, schro_hbm->use_chroma);
362 SCHRO_ASSERT (!(0 > scan.scan_width) && !(0 > scan.scan_height));
363
364 mv = mf->motion_vectors + j * params->x_num_blocks + i;
365
366 schro_metric_scan_do_scan (&scan);
367 mv->metric =
368 schro_metric_scan_get_min (&scan, &dx, &dy, &mv->chroma_metric);
369 dx <<= shift;
370 dy <<= shift;
371
372 mv->u.vec.dx[ref] = dx;
373 mv->u.vec.dy[ref] = dy;
374
375 mv->using_global = 0;
376
377 mv->pred_mode = ref + 1;
378 }
379 }
380
381 schro_hbm_set_motion_field (schro_hbm, mf, shift);
382 #undef LIST_LENGTH
383 }
384