1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include <schroedinger/schro.h>
6 #include <schroedinger/schrophasecorrelation.h>
7 #include <string.h>
8 #include <math.h>
9
10 #define DC_BIAS 50
11 #define DC_METRIC 50
12 #define BIDIR_LIMIT (10*8*8)
13
14 #define SCHRO_METRIC_INVALID_2 0x7fffffff
15
16 #define motion_field_get(mf,x,y) \
17 ((mf)->motion_vectors + (y)*(mf)->x_num_blocks + (x))
18
19 void schro_encoder_bigblock_estimation (SchroMotionEst * me);
20 static SchroFrame *get_downsampled (SchroEncoderFrame * frame, int i);
21
22
23 SchroMotionEst *
schro_motionest_new(SchroEncoderFrame * frame)24 schro_motionest_new (SchroEncoderFrame * frame)
25 {
26 SchroMotionEst *me;
27
28 me = schro_malloc0 (sizeof (SchroMotionEst));
29
30 me->encoder_frame = frame;
31 me->params = &frame->params;
32
33 me->downsampled_src0[0] = frame->ref_frame[0]->filtered_frame;
34 me->downsampled_src0[1] = frame->ref_frame[0]->downsampled_frames[0];
35 me->downsampled_src0[2] = frame->ref_frame[0]->downsampled_frames[1];
36 me->downsampled_src0[3] = frame->ref_frame[0]->downsampled_frames[2];
37 me->downsampled_src0[4] = frame->ref_frame[0]->downsampled_frames[3];
38
39 if (me->params->num_refs > 1) {
40 me->downsampled_src1[0] = frame->ref_frame[1]->filtered_frame;
41 me->downsampled_src1[1] = frame->ref_frame[1]->downsampled_frames[0];
42 me->downsampled_src1[2] = frame->ref_frame[1]->downsampled_frames[1];
43 me->downsampled_src1[3] = frame->ref_frame[1]->downsampled_frames[2];
44 me->downsampled_src1[4] = frame->ref_frame[1]->downsampled_frames[3];
45 }
46
47 me->scan_distance = frame->encoder->magic_scan_distance;
48
49 return me;
50 }
51
52 void
schro_motionest_free(SchroMotionEst * me)53 schro_motionest_free (SchroMotionEst * me)
54 {
55 schro_free (me);
56 }
57
58
59 void
schro_encoder_motion_predict_rough(SchroEncoderFrame * frame)60 schro_encoder_motion_predict_rough (SchroEncoderFrame * frame)
61 {
62 SchroParams *params = &frame->params;
63 SchroEncoder *encoder = frame->encoder;
64 int ref;
65
66 SCHRO_ASSERT (params->x_num_blocks != 0);
67 SCHRO_ASSERT (params->y_num_blocks != 0);
68 SCHRO_ASSERT (params->num_refs > 0);
69
70 if (encoder->enable_hierarchical_estimation) {
71 for (ref = 0; ref < params->num_refs; ref++) {
72 if (encoder->enable_bigblock_estimation) {
73 frame->rme[ref] = schro_rough_me_new (frame, frame->ref_frame[ref]);
74 schro_rough_me_heirarchical_scan (frame->rme[ref]);
75 } else if (encoder->enable_deep_estimation) {
76 frame->hier_bm[ref] = schro_hbm_new (frame, ref);
77 schro_hbm_scan (frame->hier_bm[ref]);
78 }
79
80 if (encoder->enable_phasecorr_estimation) {
81 frame->phasecorr[ref] = schro_phasecorr_new (frame,
82 frame->ref_frame[ref]);
83 schro_encoder_phasecorr_estimation (frame->phasecorr[ref]);
84 }
85 }
86 if (encoder->enable_global_motion) {
87 schro_encoder_global_estimation (frame);
88 }
89 }
90
91 if (encoder->enable_bigblock_estimation) {
92 frame->me = schro_motionest_new (frame);
93 } else if (encoder->enable_deep_estimation) {
94 frame->deep_me = schro_me_new (frame);
95 }
96
97 frame->motion = schro_motion_new (params, NULL, NULL);
98 if (encoder->enable_bigblock_estimation) {
99 frame->me->motion = frame->motion;
100 }
101
102 }
103
104 void
schro_encoder_motion_predict_pel(SchroEncoderFrame * frame)105 schro_encoder_motion_predict_pel (SchroEncoderFrame * frame)
106 {
107 SchroParams *params = &frame->params;
108 int ref;
109
110 SCHRO_ASSERT (params->x_num_blocks != 0);
111 SCHRO_ASSERT (params->y_num_blocks != 0);
112 SCHRO_ASSERT (params->num_refs > 0);
113
114 if (frame->encoder->enable_bigblock_estimation) {
115 schro_encoder_bigblock_estimation (frame->me);
116
117 schro_motion_calculate_stats (frame->motion, frame);
118 frame->estimated_mc_bits = schro_motion_estimate_entropy (frame->motion);
119
120 frame->badblock_ratio =
121 (double) frame->me->badblocks / (params->x_num_blocks *
122 params->y_num_blocks / 16);
123 } else if (frame->encoder->enable_deep_estimation) {
124 for (ref = 0; params->num_refs > ref; ++ref) {
125 SCHRO_ASSERT (frame->hier_bm[ref]);
126 schro_hierarchical_bm_scan_hint (frame->hier_bm[ref], 0, 3);
127 }
128 } else
129 SCHRO_ASSERT (0);
130 }
131
132 static void
schro_encoder_motion_refine_block_subpel(SchroEncoderFrame * frame,SchroBlock * block,int i,int j)133 schro_encoder_motion_refine_block_subpel (SchroEncoderFrame * frame,
134 SchroBlock * block, int i, int j)
135 {
136 SchroParams *params = &frame->params;
137 int skip;
138 int ii, jj;
139
140 skip = 4 >> block->mv[0][0].split;
141 for (jj = 0; jj < 4; jj += skip) {
142 for (ii = 0; ii < 4; ii += skip) {
143 if (block->mv[jj][ii].pred_mode & 1) {
144 block->mv[jj][ii].u.vec.dx[0] <<= params->mv_precision;
145 block->mv[jj][ii].u.vec.dy[0] <<= params->mv_precision;
146 }
147 if (block->mv[jj][ii].pred_mode & 2) {
148 block->mv[jj][ii].u.vec.dx[1] <<= params->mv_precision;
149 block->mv[jj][ii].u.vec.dy[1] <<= params->mv_precision;
150 }
151 }
152 }
153
154 if (block->mv[0][0].split < 3) {
155 for (jj = 0; jj < 4; jj += skip) {
156 for (ii = 0; ii < 4; ii += skip) {
157 if (SCHRO_METRIC_INVALID == block->mv[jj][ii].metric) {
158 continue;
159 }
160 if (block->mv[jj][ii].pred_mode == 1
161 || block->mv[jj][ii].pred_mode == 2) {
162 SchroUpsampledFrame *ref_upframe;
163 SchroFrameData orig;
164 SchroFrameData ref_fd;
165 int dx, dy;
166 int x, y;
167 int metric = SCHRO_METRIC_INVALID_2;
168 int width, height;
169 int min_metric;
170 int min_dx, min_dy;
171 int ref;
172
173 ref = block->mv[jj][ii].pred_mode - 1;
174 ref_upframe = frame->ref_frame[ref]->upsampled_original_frame;
175
176 x = MAX ((i + ii) * frame->params.xbsep_luma, 0);
177 y = MAX ((j + jj) * frame->params.ybsep_luma, 0);
178
179 schro_frame_get_subdata (get_downsampled (frame, 0), &orig, 0, x, y);
180
181 width = MIN (skip * frame->params.xbsep_luma, orig.width);
182 height = MIN (skip * frame->params.ybsep_luma, orig.height);
183
184
185 min_metric = 0x7fffffff;
186 min_dx = 0;
187 min_dy = 0;
188 for (dx = -1; dx <= 1; dx++) {
189 for (dy = -1; dy <= 1; dy++) {
190 schro_upsampled_frame_get_subdata_prec1 (ref_upframe, 0,
191 2 * x + block->mv[jj][ii].u.vec.dx[ref] + dx,
192 2 * y + block->mv[jj][ii].u.vec.dy[ref] + dy, &ref_fd);
193
194 metric = schro_metric_get (&orig, &ref_fd, width, height);
195 if (metric < min_metric) {
196 min_dx = dx;
197 min_dy = dy;
198 min_metric = metric;
199 }
200 }
201 }
202 if (SCHRO_METRIC_INVALID > min_metric) {
203 block->mv[ii][ii].u.vec.dx[ref] += min_dx;
204 block->mv[jj][ii].u.vec.dy[ref] += min_dy;
205 block->mv[jj][ii].metric = min_metric;
206 }
207 }
208 }
209 }
210 }
211
212 }
213
214 void
schro_encoder_motion_predict_subpel(SchroEncoderFrame * frame)215 schro_encoder_motion_predict_subpel (SchroEncoderFrame * frame)
216 {
217 SchroParams *params = &frame->params;
218 int i;
219 int j;
220
221 SCHRO_ASSERT (frame->upsampled_original_frame);
222 SCHRO_ASSERT (frame->ref_frame[0]->upsampled_original_frame);
223 if (frame->ref_frame[1]) {
224 SCHRO_ASSERT (frame->ref_frame[1]->upsampled_original_frame);
225 }
226
227 for (j = 0; j < params->y_num_blocks; j += 4) {
228 for (i = 0; i < params->x_num_blocks; i += 4) {
229 SchroBlock block = { 0 };
230
231 schro_motion_copy_from (frame->me->motion, i, j, &block);
232 schro_encoder_motion_refine_block_subpel (frame, &block, i, j);
233 schro_block_fixup (&block);
234 schro_motion_copy_to (frame->me->motion, i, j, &block);
235 }
236 }
237 }
238
239 typedef struct
240 {
241 int dx;
242 int dy;
243 } MatchPos;
244
245
246 void
schro_encoder_motion_predict_subpel_deep(SchroMe * me)247 schro_encoder_motion_predict_subpel_deep (SchroMe * me)
248 {
249 SchroParams *params = schro_me_params (me);
250 double lambda = schro_me_lambda (me);
251 int mvprec = 0, ref;
252 int xblen = params->xbsep_luma, yblen = params->ybsep_luma;
253 int i, j;
254 int x_min, x_max, y_min, y_max;
255 SchroMotionField *mf = NULL;
256 SchroMotionVector *mv;
257 SchroFrameData fd;
258 SchroFrame *orig_frame = schro_me_src (me);
259 const MatchPos sp_matches[] = { {-1, -1}, {0, -1}, {1, -1}
260 , {-1, 0}, {1, 0}
261 , {-1, 1}, {0, 1}, {1, 1}
262 };
263
264
265 x_min = y_min = -orig_frame->extension;
266
267 if (1 < params->mv_precision) {
268 fd.data = schro_malloc (xblen * yblen * sizeof (uint8_t));
269 fd.stride = xblen;
270 fd.height = yblen;
271 fd.width = xblen;
272 fd.format = SCHRO_FRAME_FORMAT_U8_420;
273
274 }
275
276 while (!(params->mv_precision < ++mvprec)) {
277 x_max = (orig_frame->width << mvprec) + orig_frame->extension;
278 y_max = (orig_frame->height << mvprec) + orig_frame->extension;
279 for (ref = 0; ref < params->num_refs; ++ref) {
280 SchroUpsampledFrame *upframe = schro_me_ref (me, ref);
281 mf = schro_me_subpel_mf (me, ref);
282 for (j = 0; params->y_num_blocks > j; ++j) {
283 for (i = 0; params->x_num_blocks > i; ++i) {
284 int error, entropy, min_error = INT_MAX, m = -1;
285 double score, min_score = HUGE_VAL;
286 int x, y, k;
287 int dx, dy;
288 int pred_x, pred_y;
289 SchroFrameData orig, ref_data;
290 int width, height;
291
292 mv = &mf->motion_vectors[j * params->x_num_blocks + i];
293
294 /* fetch source data (only process valid MVs) */
295 if (!schro_frame_get_data (orig_frame, &orig, 0, i * xblen,
296 j * yblen)) {
297 continue;
298 }
299 width = MIN (xblen, orig.width);
300 height = MIN (yblen, orig.height);
301 /* adjust MV precision */
302 mv->u.vec.dx[ref] <<= 1;
303 mv->u.vec.dy[ref] <<= 1;
304
305 /* calculate score for current MV */
306 schro_mf_vector_prediction (mf, i, j, &pred_x, &pred_y, ref + 1);
307 entropy = schro_pack_estimate_sint (mv->u.vec.dx[ref] - pred_x);
308 entropy += schro_pack_estimate_sint (mv->u.vec.dy[ref] - pred_y);
309 min_score = entropy + lambda * mv->metric;
310 x = i * (xblen << mvprec) + mv->u.vec.dx[ref];
311 y = j * (yblen << mvprec) + mv->u.vec.dy[ref];
312 /* check what matches are valid */
313 for (k = 0; sizeof (sp_matches) / sizeof (sp_matches[0]) > k; ++k) {
314 dx = x + sp_matches[k].dx;
315 dy = y + sp_matches[k].dy;
316 if (!(x_min < dx) || !(x_max > dx + xblen - 1)
317 || !(y_min < dy) || !(y_max > dy + yblen - 1)) {
318 continue;
319 }
320 fd.width = width;
321 fd.height = height;
322 schro_upsampled_frame_get_block_fast_precN (upframe, 0, dx, dy,
323 mvprec, &ref_data, &fd);
324 error =
325 schro_metric_absdiff_u8 (orig.data, orig.stride, ref_data.data,
326 ref_data.stride, width, height);
327 /* calculate score */
328 entropy =
329 schro_pack_estimate_sint (mv->u.vec.dx[ref] + sp_matches[k].dx -
330 pred_x);
331 entropy +=
332 schro_pack_estimate_sint (mv->u.vec.dy[ref] + sp_matches[k].dy -
333 pred_y);
334 score = entropy + lambda * error;
335 if (min_score > score) {
336 min_score = score;
337 min_error = error;
338 m = k;
339 }
340 }
341 if (-1 != m) {
342 mv->u.vec.dx[ref] += sp_matches[m].dx;
343 mv->u.vec.dy[ref] += sp_matches[m].dy;
344 mv->metric = min_error;
345 }
346 }
347 }
348
349 }
350 }
351 if (1 < params->mv_precision) {
352 schro_free (fd.data);
353 }
354 }
355
356 void
schro_motion_calculate_stats(SchroMotion * motion,SchroEncoderFrame * frame)357 schro_motion_calculate_stats (SchroMotion * motion, SchroEncoderFrame * frame)
358 {
359 int i, j;
360 SchroMotionVector *mv;
361 int ref1 = 0;
362 int ref2 = 0;
363 int bidir = 0;
364
365 frame->stats_dc = 0;
366 frame->stats_global = 0;
367 frame->stats_motion = 0;
368 for (j = 0; j < motion->params->y_num_blocks; j++) {
369 for (i = 0; i < motion->params->x_num_blocks; i++) {
370 mv = SCHRO_MOTION_GET_BLOCK (motion, i, j);
371 if (mv->pred_mode == 0) {
372 frame->stats_dc++;
373 } else {
374 if (mv->using_global) {
375 frame->stats_global++;
376 } else {
377 frame->stats_motion++;
378 }
379 if (mv->pred_mode == 1) {
380 ref1++;
381 } else if (mv->pred_mode == 2) {
382 ref2++;
383 } else {
384 bidir++;
385 }
386 }
387 }
388 }
389 SCHRO_DEBUG ("dc %d global %d motion %d ref1 %d ref2 %d bidir %d",
390 frame->stats_dc, frame->stats_global, frame->stats_motion,
391 ref1, ref2, bidir);
392 }
393
394
395 SchroMotionField *
schro_motion_field_new(int x_num_blocks,int y_num_blocks)396 schro_motion_field_new (int x_num_blocks, int y_num_blocks)
397 {
398 SchroMotionField *mf;
399
400 mf = schro_malloc0 (sizeof (SchroMotionField));
401 mf->x_num_blocks = x_num_blocks;
402 mf->y_num_blocks = y_num_blocks;
403 mf->motion_vectors = schro_malloc0 (sizeof (SchroMotionVector) *
404 x_num_blocks * y_num_blocks);
405
406 return mf;
407 }
408
409 void
schro_motion_field_free(SchroMotionField * field)410 schro_motion_field_free (SchroMotionField * field)
411 {
412 schro_free (field->motion_vectors);
413 schro_free (field);
414 }
415
416 void
schro_motion_field_set(SchroMotionField * field,int split,int pred_mode)417 schro_motion_field_set (SchroMotionField * field, int split, int pred_mode)
418 {
419 SchroMotionVector *mv;
420 int i;
421 int j;
422
423 for (j = 0; j < field->y_num_blocks; j++) {
424 for (i = 0; i < field->x_num_blocks; i++) {
425 mv = field->motion_vectors + j * field->x_num_blocks + i;
426 memset (mv, 0, sizeof (*mv));
427 mv->split = split;
428 mv->pred_mode = pred_mode;
429 mv->metric = 0;
430 }
431 }
432 }
433
434 void
schro_motion_field_copy(SchroMotionField * field,SchroMotionField * parent)435 schro_motion_field_copy (SchroMotionField * field, SchroMotionField * parent)
436 {
437 SchroMotionVector *mv;
438 SchroMotionVector *pv;
439 int i;
440 int j;
441
442 for (j = 0; j < field->y_num_blocks; j++) {
443 for (i = 0; i < field->x_num_blocks; i++) {
444 mv = field->motion_vectors + j * field->x_num_blocks + i;
445 pv = parent->motion_vectors + (j >> 1) * parent->x_num_blocks + (i >> 1);
446 *mv = *pv;
447 }
448 }
449 }
450
451 #if 0
452 void
453 schro_motion_field_dump (SchroMotionField * field)
454 {
455 SchroMotionVector *mv;
456 int i;
457 int j;
458
459 for (j = 0; j < field->y_num_blocks; j++) {
460 for (i = 0; i < field->x_num_blocks; i++) {
461 mv = field->motion_vectors + j * field->x_num_blocks + i;
462 printf ("%d %d %d %d\n", i, j, mv->u.vec.dx[0], mv->u.vec.dy[0]);
463 }
464 }
465 exit (0);
466 }
467 #endif
468
469 static SchroFrame *
get_downsampled(SchroEncoderFrame * frame,int i)470 get_downsampled (SchroEncoderFrame * frame, int i)
471 {
472 SCHRO_ASSERT (frame->have_downsampling);
473
474 if (i == 0) {
475 return frame->filtered_frame;
476 }
477 return frame->downsampled_frames[i - 1];
478 }
479
480 static int
schro_block_average(int16_t * dest,SchroFrameData * comp,int x,int y,int w,int h)481 schro_block_average (int16_t * dest, SchroFrameData * comp,
482 int x, int y, int w, int h)
483 {
484 int xmax = MIN (x + w, comp->width);
485 int ymax = MIN (y + h, comp->height);
486 int i, j;
487 int n = 0;
488 int sum = 0;
489 int ave;
490
491 if (x >= comp->width || y >= comp->height)
492 return SCHRO_METRIC_INVALID_2;
493
494 for (j = y; j < ymax; j++) {
495 for (i = x; i < xmax; i++) {
496 sum += SCHRO_GET (comp->data, j * comp->stride + i, uint8_t);
497 }
498 n += xmax - x;
499 }
500
501 if (n == 0) {
502 return SCHRO_METRIC_INVALID_2;
503 }
504
505 ave = (sum + n / 2) / n;
506
507 sum = 0;
508 for (j = y; j < ymax; j++) {
509 for (i = x; i < xmax; i++) {
510 sum += abs (ave - SCHRO_GET (comp->data, j * comp->stride + i, uint8_t));
511 }
512 }
513
514 *dest = ave - 128;
515 return sum;
516 }
517
518
519 static void
schro_motionest_superblock_scan_one(SchroMotionEst * me,int ref,int distance,SchroBlock * block,int i,int j)520 schro_motionest_superblock_scan_one (SchroMotionEst * me, int ref, int distance,
521 SchroBlock * block, int i, int j)
522 {
523 SchroParams *params = me->params;
524 SchroMotionVector *mv;
525 SchroMetricScan scan;
526 SchroMotionField *hint_mf;
527 SchroMotionVector *hint_mv;
528 int dx, dy;
529 uint32_t dummy;
530
531 scan.frame = get_downsampled (me->encoder_frame, 0);
532 scan.ref_frame = get_downsampled (me->encoder_frame->ref_frame[ref], 0);
533
534 //hint_mf = me->downsampled_mf[ref][2];
535 hint_mf = me->encoder_frame->rme[ref]->motion_fields[2];
536
537 scan.x = i * params->xbsep_luma;
538 scan.y = j * params->ybsep_luma;
539 scan.block_width = MIN (4 * params->xbsep_luma, scan.frame->width - scan.x);
540 scan.block_height = MIN (4 * params->ybsep_luma, scan.frame->height - scan.y);
541 scan.gravity_scale = 0;
542 scan.gravity_x = 0;
543 scan.gravity_y = 0;
544
545 mv = &block->mv[0][0];
546 hint_mv = motion_field_get (hint_mf, i, j);
547
548 dx = hint_mv->u.vec.dx[ref];
549 dy = hint_mv->u.vec.dy[ref];
550 scan.gravity_x = dx;
551 scan.gravity_y = dy;
552
553 schro_metric_scan_setup (&scan, dx, dy, distance, FALSE);
554 if (scan.scan_width <= 0 || scan.scan_height <= 0) {
555 mv->u.vec.dx[ref] = 0;
556 mv->u.vec.dy[ref] = 0;
557 mv->metric = SCHRO_METRIC_INVALID;
558 block->valid = FALSE;
559 return;
560 }
561
562 schro_metric_scan_do_scan (&scan);
563 block->error = schro_metric_scan_get_min (&scan, &dx, &dy, &dummy);
564 mv->metric = block->error / 16;
565
566 mv->split = 0;
567 mv->pred_mode = 1 << ref;
568 mv->using_global = 0;
569 mv->u.vec.dx[ref] = dx;
570 mv->u.vec.dy[ref] = dy;
571
572 schro_block_fixup (block);
573 block->entropy = schro_motion_superblock_try_estimate_entropy (me->motion,
574 i, j, block);
575 block->valid = TRUE;
576 }
577
578 static void
schro_motionest_superblock_predicted(SchroMotionEst * me,int ref,SchroBlock * block,int i,int j)579 schro_motionest_superblock_predicted (SchroMotionEst * me, int ref,
580 SchroBlock * block, int i, int j)
581 {
582 SchroMotionVector *mv;
583 int pred_x, pred_y;
584
585 schro_motion_vector_prediction (me->motion, i, j, &pred_x, &pred_y,
586 (1 << ref));
587
588 mv = &block->mv[0][0];
589 mv->split = 0;
590 mv->pred_mode = 1 << ref;
591 mv->using_global = 0;
592 mv->u.vec.dx[ref] = pred_x;
593 mv->u.vec.dy[ref] = pred_y;
594 block->error = schro_motionest_superblock_get_metric (me, block, i, j);
595 block->entropy = 0;
596 schro_block_fixup (block);
597
598 block->valid = (block->error != SCHRO_METRIC_INVALID_2);
599 }
600
601 static void
schro_motionest_superblock_biref_zero(SchroMotionEst * me,SchroBlock * block,int i,int j)602 schro_motionest_superblock_biref_zero (SchroMotionEst * me,
603 SchroBlock * block, int i, int j)
604 {
605 SchroMotionVector *mv;
606
607 mv = &block->mv[0][0];
608 mv->split = 0;
609 mv->pred_mode = 3;
610 mv->using_global = 0;
611 mv->u.vec.dx[0] = 0;
612 mv->u.vec.dy[0] = 0;
613 mv->u.vec.dx[1] = 0;
614 mv->u.vec.dy[1] = 0;
615 block->error = schro_motionest_superblock_get_metric (me, block, i, j);
616 schro_block_fixup (block);
617 block->entropy = schro_motion_superblock_try_estimate_entropy (me->motion,
618 i, j, block);
619 block->valid = (block->error != SCHRO_METRIC_INVALID_2);
620 }
621
622 static void
schro_motionest_superblock_dc(SchroMotionEst * me,SchroBlock * block,int i,int j)623 schro_motionest_superblock_dc (SchroMotionEst * me,
624 SchroBlock * block, int i, int j)
625 {
626 SchroParams *params = me->params;
627 SchroMotionVector *mv;
628 int chroma_w, chroma_h;
629 SchroFrame *frame;
630 int metric;
631
632 frame = get_downsampled (me->encoder_frame, 0);
633
634 mv = &block->mv[0][0];
635 mv->split = 0;
636 mv->pred_mode = 0;
637
638 metric = schro_block_average (&mv->u.dc.dc[0], frame->components + 0,
639 i * params->xbsep_luma, j * params->ybsep_luma,
640 4 * params->xbsep_luma, 4 * params->ybsep_luma);
641 if (metric == SCHRO_METRIC_INVALID_2) {
642 block->valid = FALSE;
643 return;
644 }
645 chroma_w =
646 params->xbsep_luma >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
647 video_format->chroma_format);
648 chroma_h =
649 params->ybsep_luma >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
650 video_format->chroma_format);
651 schro_block_average (&mv->u.dc.dc[1], frame->components + 1, i * chroma_w,
652 j * chroma_h, 4 * chroma_w, 4 * chroma_h);
653 schro_block_average (&mv->u.dc.dc[2], frame->components + 2, i * chroma_w,
654 j * chroma_h, 4 * chroma_w, 4 * chroma_h);
655
656 mv->metric = metric;
657 block->error = metric;
658 block->error += 4 * 2 * me->params->xbsep_luma *
659 me->encoder_frame->encoder->magic_dc_metric_offset;
660
661 schro_block_fixup (block);
662
663 block->entropy = schro_motion_superblock_try_estimate_entropy (me->motion,
664 i, j, block);
665 block->valid = TRUE;
666 }
667
668 static void
schro_motionest_superblock_dc_predicted(SchroMotionEst * me,SchroBlock * block,int i,int j)669 schro_motionest_superblock_dc_predicted (SchroMotionEst * me,
670 SchroBlock * block, int i, int j)
671 {
672 SchroMotionVector *mv;
673 int pred[3];
674
675 schro_motion_dc_prediction (me->motion, i, j, pred);
676
677 mv = &block->mv[0][0];
678 mv->split = 0;
679 mv->pred_mode = 0;
680 mv->u.dc.dc[0] = pred[0];
681 mv->u.dc.dc[1] = pred[1];
682 mv->u.dc.dc[2] = pred[2];
683
684 block->error = schro_motionest_superblock_get_metric (me, block, i, j);
685 mv->metric = block->error;
686 block->error += 4 * 2 * me->params->xbsep_luma *
687 me->encoder_frame->encoder->magic_dc_metric_offset;
688
689 schro_block_fixup (block);
690 block->entropy = 0;
691 block->valid = TRUE;
692 }
693
694 #ifdef unused
695 static void
schro_motion_splat_4x4(SchroMotion * motion,int i,int j)696 schro_motion_splat_4x4 (SchroMotion * motion, int i, int j)
697 {
698 SchroMotionVector *mv;
699
700 mv = SCHRO_MOTION_GET_BLOCK (motion, i, j);
701 mv[1] = mv[0];
702 mv[2] = mv[0];
703 mv[3] = mv[0];
704 memcpy (SCHRO_MOTION_GET_BLOCK (motion, i, j + 1), mv, 4 * sizeof (*mv));
705 memcpy (SCHRO_MOTION_GET_BLOCK (motion, i, j + 2), mv, 4 * sizeof (*mv));
706 memcpy (SCHRO_MOTION_GET_BLOCK (motion, i, j + 3), mv, 4 * sizeof (*mv));
707 }
708 #endif
709
710 #ifdef unused
711 static void
motion_field_splat_4x4(SchroMotionField * mf,int i,int j)712 motion_field_splat_4x4 (SchroMotionField * mf, int i, int j)
713 {
714 SchroMotionVector *mv;
715
716 mv = motion_field_get (mf, i, j);
717 mv[1] = mv[0];
718 mv[2] = mv[0];
719 mv[3] = mv[0];
720 memcpy (motion_field_get (mf, i, j + 1), mv, 4 * sizeof (*mv));
721 memcpy (motion_field_get (mf, i, j + 2), mv, 4 * sizeof (*mv));
722 memcpy (motion_field_get (mf, i, j + 3), mv, 4 * sizeof (*mv));
723 }
724 #endif
725
726 #ifdef unused
727 static void
schro_motionest_block_scan_one(SchroMotionEst * me,int ref,int distance,SchroBlock * block,int i,int j)728 schro_motionest_block_scan_one (SchroMotionEst * me, int ref, int distance,
729 SchroBlock * block, int i, int j)
730 {
731 SchroParams *params = me->params;
732 SchroMotionVector *mv;
733 SchroMetricScan scan;
734 SchroMotionField *hint_mf;
735 SchroMotionVector *hint_mv;
736 int dx, dy;
737 int ii, jj;
738
739 scan.frame = get_downsampled (me->encoder_frame, 0);
740 scan.ref_frame = get_downsampled (me->encoder_frame->ref_frame[ref], 0);
741
742 hint_mf = me->encoder_frame->rme[ref]->motion_fields[1];
743
744 scan.block_width = params->xbsep_luma;
745 scan.block_height = params->ybsep_luma;
746 scan.gravity_scale = 0;
747 scan.gravity_x = 0;
748 scan.gravity_y = 0;
749
750 block->error = 0;
751 block->valid = TRUE;
752 for (jj = 0; jj < 4; jj++) {
753 for (ii = 0; ii < 4; ii++) {
754 mv = &block->mv[jj][ii];
755 hint_mv = motion_field_get (hint_mf, i + (ii & 2), j + (jj & 2));
756
757 dx = hint_mv->u.vec.dx[ref];
758 dy = hint_mv->u.vec.dy[ref];
759 scan.gravity_x = dx;
760 scan.gravity_y = dy;
761
762 scan.x = (i + ii) * params->xbsep_luma;
763 scan.y = (j + jj) * params->ybsep_luma;
764 schro_metric_scan_setup (&scan, dx, dy, distance, FALSE);
765 if (scan.scan_width <= 0 || scan.scan_height <= 0) {
766 mv->u.vec.dx[ref] = 0;
767 mv->u.vec.dy[ref] = 0;
768 mv->metric = SCHRO_METRIC_INVALID;
769 block->error += mv->metric;
770 block->valid = FALSE;
771 continue;
772 }
773
774 schro_metric_scan_do_scan (&scan);
775 uint32_t dummy;
776 mv->metric = schro_metric_scan_get_min (&scan, &dx, &dy, &dummy);
777 block->error += mv->metric;
778 block->valid &= (mv->metric != SCHRO_METRIC_INVALID);
779
780 mv->split = 2;
781 mv->pred_mode = 1 << ref;
782 mv->using_global = 0;
783 mv->u.vec.dx[ref] = dx;
784 mv->u.vec.dy[ref] = dy;
785 }
786 }
787
788 schro_block_fixup (block);
789 block->entropy = schro_motion_superblock_try_estimate_entropy (me->motion,
790 i, j, block);
791 }
792 #endif
793
794
795 #define MAGIC_SUPERBLOCK_METRIC 5
796 #define MAGIC_BLOCK_METRIC 50
797
798 #define TRYBLOCK \
799 score = tryblock.entropy + me->lambda * tryblock.error; \
800 if (tryblock.valid && score < min_score) { \
801 memcpy (&block, &tryblock, sizeof(block)); \
802 min_score = score; \
803 }
804
805 static void
schro_motionest_block_scan(SchroMotionEst * me,int ref,int distance,SchroBlock * block,int i,int j,int ii,int jj)806 schro_motionest_block_scan (SchroMotionEst * me, int ref, int distance,
807 SchroBlock * block, int i, int j, int ii, int jj)
808 {
809 SchroParams *params = me->params;
810 SchroMotionVector *mv;
811 SchroMetricScan scan;
812 SchroMotionField *hint_mf;
813 SchroMotionVector *hint_mv;
814 int dx, dy;
815 uint32_t dummy;
816
817 scan.frame = get_downsampled (me->encoder_frame, 0);
818 scan.ref_frame = get_downsampled (me->encoder_frame->ref_frame[ref], 0);
819
820 hint_mf = me->encoder_frame->rme[ref]->motion_fields[1];
821
822 scan.block_width = params->xbsep_luma;
823 scan.block_height = params->ybsep_luma;
824
825 scan.gravity_scale = 0;
826 scan.gravity_x = 0;
827 scan.gravity_y = 0;
828
829 mv = &block->mv[jj][ii];
830 hint_mv = motion_field_get (hint_mf, i + (ii & 2), j + (jj & 2));
831
832 dx = hint_mv->u.vec.dx[ref];
833 dy = hint_mv->u.vec.dy[ref];
834 scan.gravity_x = dx;
835 scan.gravity_y = dy;
836
837 scan.x = (i + ii) * params->xbsep_luma;
838 scan.y = (j + jj) * params->ybsep_luma;
839 if (!(scan.x < scan.frame->width) || !(scan.y < scan.frame->height)) {
840 mv->u.vec.dx[ref] = 0;
841 mv->u.vec.dy[ref] = 0;
842 mv->metric = SCHRO_METRIC_INVALID;
843 block->error += mv->metric;
844 block->valid = FALSE;
845 return;
846 }
847 scan.block_width = MIN (params->xbsep_luma, scan.frame->width - scan.x);
848 scan.block_height = MIN (params->ybsep_luma, scan.frame->height - scan.y);
849 schro_metric_scan_setup (&scan, dx, dy, distance, FALSE);
850 if (scan.scan_width <= 0 || scan.scan_height <= 0) {
851 mv->u.vec.dx[ref] = 0;
852 mv->u.vec.dy[ref] = 0;
853 mv->metric = SCHRO_METRIC_INVALID;
854 block->error += mv->metric;
855 block->valid = FALSE;
856 return;
857 }
858
859 schro_metric_scan_do_scan (&scan);
860 mv->metric = schro_metric_scan_get_min (&scan, &dx, &dy, &dummy);
861 block->error = mv->metric;
862 block->valid = (mv->metric != SCHRO_METRIC_INVALID);
863
864 mv->split = 2;
865 mv->pred_mode = 1 << ref;
866 mv->using_global = 0;
867 mv->u.vec.dx[ref] = dx;
868 mv->u.vec.dy[ref] = dy;
869
870 schro_block_fixup (block);
871
872 mv = SCHRO_MOTION_GET_BLOCK (me->motion, i + ii, j + jj);
873 *mv = block->mv[jj][ii];
874 block->entropy = schro_motion_block_estimate_entropy (me->motion,
875 i + ii, j + jj);
876 }
877
878 static void
schro_motionest_block_dc(SchroMotionEst * me,SchroBlock * block,int i,int j,int ii,int jj)879 schro_motionest_block_dc (SchroMotionEst * me,
880 SchroBlock * block, int i, int j, int ii, int jj)
881 {
882 SchroParams *params = me->params;
883 SchroMotionVector *mv;
884 int chroma_w, chroma_h;
885 SchroFrame *frame;
886 int metric;
887
888 frame = get_downsampled (me->encoder_frame, 0);
889
890 mv = &(block->mv[jj][ii]);
891 mv->split = 2;
892 mv->pred_mode = 0;
893
894 metric = schro_block_average (&mv->u.dc.dc[0], frame->components + 0,
895 (i + ii) * params->xbsep_luma, (j + jj) * params->ybsep_luma,
896 params->xbsep_luma, params->ybsep_luma);
897 if (metric == SCHRO_METRIC_INVALID_2) {
898 block->valid = FALSE;
899 return;
900 }
901 chroma_w =
902 params->xbsep_luma >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
903 video_format->chroma_format);
904 chroma_h =
905 params->ybsep_luma >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
906 video_format->chroma_format);
907 schro_block_average (&mv->u.dc.dc[1], frame->components + 1,
908 (i + ii) * chroma_w, (j + jj) * chroma_h, chroma_w, chroma_h);
909 schro_block_average (&mv->u.dc.dc[2], frame->components + 2,
910 (i + ii) * chroma_w, (j + jj) * chroma_h, chroma_w, chroma_h);
911
912 mv->metric = metric;
913 block->error = metric;
914 block->error += 4 * 2 * me->params->xbsep_luma *
915 me->encoder_frame->encoder->magic_dc_metric_offset;
916
917 block->entropy = schro_motion_block_estimate_entropy (me->motion,
918 i + ii, j + jj);
919 block->valid = TRUE;
920 }
921
922 static void
schro_motionest_superblock_block(SchroMotionEst * me,SchroBlock * p_block,int i,int j)923 schro_motionest_superblock_block (SchroMotionEst * me,
924 SchroBlock * p_block, int i, int j)
925 {
926 SchroParams *params = me->params;
927 int ii, jj;
928 SchroBlock block = { 0 };
929 int total_error = 0;
930
931 for (jj = 0; jj < 4; jj++) {
932 for (ii = 0; ii < 4; ii++) {
933 block.mv[jj][ii].split = 2;
934 block.mv[jj][ii].pred_mode = 1;
935 block.mv[jj][ii].u.vec.dx[0] = 0;
936 block.mv[jj][ii].u.vec.dy[0] = 0;
937 }
938 }
939 schro_motion_copy_to (me->motion, i, j, &block);
940
941 for (jj = 0; jj < 4; jj++) {
942 for (ii = 0; ii < 4; ii++) {
943 SchroBlock tryblock = { 0 };
944 double score;
945 double min_score;
946
947 /* FIXME use better default than DC */
948 schro_motionest_block_dc (me, &tryblock, i, j, ii, jj);
949 min_score = block.entropy + me->lambda * block.error;
950
951 if (me->encoder_frame->encoder->enable_hierarchical_estimation) {
952 memcpy (&tryblock, &block, sizeof (block));
953 schro_motionest_block_scan (me, 0, me->scan_distance, &block, i, j, ii,
954 jj);
955 min_score = block.entropy + me->lambda * block.error;
956
957 if (params->num_refs > 1) {
958 memcpy (&tryblock, &block, sizeof (block));
959 schro_motionest_block_scan (me, 1, me->scan_distance, &tryblock, i, j,
960 ii, jj);
961 TRYBLOCK}
962 }
963
964 memcpy (&tryblock, &block, sizeof (block));
965 schro_motionest_block_dc (me, &tryblock, i, j, ii, jj);
966 TRYBLOCK total_error += block.error;
967 }
968 }
969 block.entropy = schro_motion_superblock_try_estimate_entropy (me->motion,
970 i, j, &block);
971 block.error = total_error;
972
973 memcpy (p_block, &block, sizeof (block));
974 }
975
976 static void
schro_motionest_subsuperblock_scan(SchroMotionEst * me,int ref,int distance,SchroBlock * block,int i,int j,int ii,int jj)977 schro_motionest_subsuperblock_scan (SchroMotionEst * me, int ref, int distance,
978 SchroBlock * block, int i, int j, int ii, int jj)
979 {
980 SchroParams *params = me->params;
981 SchroMotionVector *mv;
982 SchroMetricScan scan;
983 SchroMotionField *hint_mf;
984 SchroMotionVector *hint_mv;
985 int dx, dy;
986 uint32_t dummy;
987
988 scan.frame = get_downsampled (me->encoder_frame, 0);
989 scan.ref_frame = get_downsampled (me->encoder_frame->ref_frame[ref], 0);
990
991 hint_mf = me->encoder_frame->rme[ref]->motion_fields[1];
992
993 scan.block_width = 2 * params->xbsep_luma;
994 scan.block_height = 2 * params->ybsep_luma;
995
996 scan.gravity_scale = 0;
997 scan.gravity_x = 0;
998 scan.gravity_y = 0;
999
1000 mv = &block->mv[jj][ii];
1001 hint_mv = motion_field_get (hint_mf, i + (ii & 2), j + (jj & 2));
1002
1003 dx = hint_mv->u.vec.dx[ref];
1004 dy = hint_mv->u.vec.dy[ref];
1005 scan.gravity_x = dx;
1006 scan.gravity_y = dy;
1007
1008 scan.x = (i + ii) * params->xbsep_luma;
1009 scan.y = (j + jj) * params->ybsep_luma;
1010 if (!(scan.x < scan.frame->width) || !(scan.y < scan.frame->height)) {
1011 mv->u.vec.dx[ref] = mv->u.vec.dy[ref] = 0;
1012 mv->metric = SCHRO_METRIC_INVALID;
1013 block->error += mv->metric;
1014 block->valid = FALSE;
1015 return;
1016 }
1017 scan.block_width = MIN (2 * params->xbsep_luma, scan.frame->width - scan.x);
1018 scan.block_height = MIN (2 * params->ybsep_luma, scan.frame->height - scan.y);
1019 schro_metric_scan_setup (&scan, dx, dy, distance, FALSE);
1020 if (scan.scan_width <= 0 || scan.scan_height <= 0) {
1021 mv->u.vec.dx[ref] = 0;
1022 mv->u.vec.dy[ref] = 0;
1023 mv->metric = SCHRO_METRIC_INVALID;
1024 block->error += mv->metric;
1025 block->valid = FALSE;
1026 return;
1027 }
1028
1029 schro_metric_scan_do_scan (&scan);
1030 mv->metric = schro_metric_scan_get_min (&scan, &dx, &dy, &dummy);
1031 block->error = mv->metric;
1032 block->valid = (mv->metric != SCHRO_METRIC_INVALID);
1033
1034 mv->split = 1;
1035 mv->pred_mode = 1 << ref;
1036 mv->using_global = 0;
1037 mv->u.vec.dx[ref] = dx;
1038 mv->u.vec.dy[ref] = dy;
1039
1040 schro_block_fixup (block);
1041
1042 mv = SCHRO_MOTION_GET_BLOCK (me->motion, i + ii, j + jj);
1043 *mv = block->mv[jj][ii];
1044 block->entropy = schro_motion_block_estimate_entropy (me->motion,
1045 i + ii, j + jj);
1046 }
1047
1048 static void
schro_motionest_subsuperblock_dc(SchroMotionEst * me,SchroBlock * block,int i,int j,int ii,int jj)1049 schro_motionest_subsuperblock_dc (SchroMotionEst * me,
1050 SchroBlock * block, int i, int j, int ii, int jj)
1051 {
1052 SchroParams *params = me->params;
1053 SchroMotionVector *mv;
1054 int chroma_w, chroma_h;
1055 SchroFrame *frame;
1056 int metric;
1057
1058 frame = get_downsampled (me->encoder_frame, 0);
1059
1060 mv = (SchroMotionVector *) & block->mv[jj][ii];
1061 mv->split = 1;
1062 mv->pred_mode = 0;
1063
1064 metric = schro_block_average (&mv->u.dc.dc[0], frame->components + 0,
1065 (i + ii) * params->xbsep_luma, (j + jj) * params->ybsep_luma,
1066 2 * params->xbsep_luma, 2 * params->ybsep_luma);
1067 if (metric == SCHRO_METRIC_INVALID_2) {
1068 block->valid = FALSE;
1069 return;
1070 }
1071 chroma_w =
1072 params->xbsep_luma >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
1073 video_format->chroma_format);
1074 chroma_h =
1075 params->ybsep_luma >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
1076 video_format->chroma_format);
1077 schro_block_average (&mv->u.dc.dc[1], frame->components + 1,
1078 (i + ii) * chroma_w, (j + jj) * chroma_h, 2 * chroma_w, 2 * chroma_h);
1079 schro_block_average (&mv->u.dc.dc[2], frame->components + 2,
1080 (i + ii) * chroma_w, (j + jj) * chroma_h, 2 * chroma_w, 2 * chroma_h);
1081
1082 mv->metric = metric;
1083 block->error = metric;
1084 block->error += 4 * 2 * me->params->xbsep_luma *
1085 me->encoder_frame->encoder->magic_dc_metric_offset;
1086
1087 block->entropy = schro_motion_block_estimate_entropy (me->motion,
1088 i + ii, j + jj);
1089 block->valid = TRUE;
1090 }
1091
1092 static void
schro_motionest_superblock_subsuperblock(SchroMotionEst * me,SchroBlock * p_block,int i,int j)1093 schro_motionest_superblock_subsuperblock (SchroMotionEst * me,
1094 SchroBlock * p_block, int i, int j)
1095 {
1096 SchroParams *params = me->params;
1097 int ii, jj;
1098 SchroBlock block = { 0 };
1099 int total_error = 0;
1100
1101 for (jj = 0; jj < 4; jj++) {
1102 for (ii = 0; ii < 4; ii++) {
1103 block.mv[jj][ii].split = 1;
1104 block.mv[jj][ii].pred_mode = 1;
1105 block.mv[jj][ii].u.vec.dx[0] = 0;
1106 block.mv[jj][ii].u.vec.dy[0] = 0;
1107 }
1108 }
1109 schro_motion_copy_to (me->motion, i, j, &block);
1110
1111 for (jj = 0; jj < 4; jj += 2) {
1112 for (ii = 0; ii < 4; ii += 2) {
1113 SchroBlock tryblock = { 0 };
1114 double score;
1115 double min_score;
1116
1117 /* FIXME use better default than DC */
1118 schro_motionest_subsuperblock_dc (me, &block, i, j, ii, jj);
1119 min_score = block.entropy + me->lambda * block.error;
1120
1121 if (me->encoder_frame->encoder->enable_hierarchical_estimation) {
1122 memcpy (&tryblock, &block, sizeof (block));
1123 schro_motionest_subsuperblock_scan (me, 0, me->scan_distance, &tryblock,
1124 i, j, ii, jj);
1125 TRYBLOCK if (params->num_refs > 1)
1126 {
1127 memcpy (&tryblock, &block, sizeof (block));
1128 schro_motionest_subsuperblock_scan (me, 1, me->scan_distance,
1129 &tryblock, i, j, ii, jj);
1130 TRYBLOCK
1131 #if 0
1132 memcpy (&tryblock, &block, sizeof (block));
1133 schro_motionest_block_biref_zero (me, 1, &tryblock, i, j, ii, jj);
1134 TRYBLOCK
1135 #endif
1136 }
1137 }
1138
1139 memcpy (&tryblock, &block, sizeof (block));
1140 schro_motionest_subsuperblock_dc (me, &tryblock, i, j, ii, jj);
1141 TRYBLOCK total_error += block.error;
1142 }
1143 }
1144 block.entropy = schro_motion_superblock_try_estimate_entropy (me->motion,
1145 i, j, &block);
1146 block.error = total_error;
1147
1148 memcpy (p_block, &block, sizeof (block));
1149 }
1150
1151
1152 void
schro_encoder_bigblock_estimation(SchroMotionEst * me)1153 schro_encoder_bigblock_estimation (SchroMotionEst * me)
1154 {
1155 SchroParams *params = me->params;
1156 int i, j;
1157 double total_error = 0;
1158 int block_size;
1159 int block_threshold;
1160
1161 me->lambda = me->encoder_frame->frame_me_lambda;
1162
1163 block_size = 16 * params->xbsep_luma * params->ybsep_luma;
1164 block_threshold = params->xbsep_luma * params->ybsep_luma *
1165 me->encoder_frame->encoder->magic_block_search_threshold;
1166
1167 for (j = 0; j < params->y_num_blocks; j += 4) {
1168 for (i = 0; i < params->x_num_blocks; i += 4) {
1169 SchroBlock block = { 0 };
1170 SchroBlock tryblock = { 0 };
1171 double score;
1172 double min_score;
1173
1174 /* base 119 s */
1175 schro_motionest_superblock_predicted (me, 0, &block, i, j);
1176 min_score = block.entropy + me->lambda * block.error;
1177 if (params->num_refs > 1) {
1178 schro_motionest_superblock_predicted (me, 1, &tryblock, i, j);
1179 TRYBLOCK}
1180
1181 if (me->encoder_frame->encoder->enable_hierarchical_estimation) {
1182 /* 16 s */
1183 schro_motionest_superblock_scan_one (me, 0, me->scan_distance,
1184 &tryblock, i, j);
1185 TRYBLOCK if (params->num_refs > 1)
1186 {
1187 schro_motionest_superblock_scan_one (me, 1, me->scan_distance,
1188 &tryblock, i, j);
1189 TRYBLOCK}
1190 }
1191
1192 /* 2.5 s */
1193 schro_motionest_superblock_dc_predicted (me, &tryblock, i, j);
1194 TRYBLOCK schro_motionest_superblock_dc (me, &tryblock, i, j);
1195 TRYBLOCK
1196 /* 3.0 s */
1197 if (params->num_refs > 1) {
1198 schro_motionest_superblock_biref_zero (me, &tryblock, i, j);
1199 TRYBLOCK}
1200
1201 if (min_score > block_threshold || block.mv[0][0].pred_mode == 0) {
1202 schro_motionest_superblock_subsuperblock (me, &tryblock, i, j);
1203 TRYBLOCK schro_motionest_superblock_block (me, &tryblock, i, j);
1204 TRYBLOCK}
1205
1206 if (me->encoder_frame->encoder->enable_phasecorr_estimation) {
1207 schro_motionest_superblock_phasecorr1 (me, 0, &tryblock, i, j);
1208 TRYBLOCK if (params->num_refs > 1)
1209 {
1210 schro_motionest_superblock_phasecorr1 (me, 1, &tryblock, i, j);
1211 TRYBLOCK}
1212 }
1213
1214 if (me->encoder_frame->encoder->enable_global_motion) {
1215 schro_motionest_superblock_global (me, 0, &tryblock, i, j);
1216 TRYBLOCK if (params->num_refs > 1)
1217 {
1218 schro_motionest_superblock_global (me, 1, &tryblock, i, j);
1219 TRYBLOCK}
1220 }
1221
1222 if (block.error > 10 * block_size) {
1223 me->badblocks++;
1224 }
1225
1226 schro_block_fixup (&block);
1227 schro_motion_copy_to (me->motion, i, j, &block);
1228
1229 total_error +=
1230 (double) block.error * block.error / (double) (block_size *
1231 block_size);
1232 }
1233 }
1234
1235 me->encoder_frame->mc_error = total_error / (240.0 * 240.0) /
1236 (params->x_num_blocks * params->y_num_blocks / 16);
1237
1238 /* magic parameter */
1239 me->encoder_frame->mc_error *= 2.5;
1240 }
1241
1242 int
schro_motion_block_estimate_entropy(SchroMotion * motion,int i,int j)1243 schro_motion_block_estimate_entropy (SchroMotion * motion, int i, int j)
1244 {
1245 SchroMotionVector *mv;
1246 int entropy = 0;
1247
1248 mv = SCHRO_MOTION_GET_BLOCK (motion, i, j);
1249
1250 if (mv->split == 0 && (i & 3 || j & 3))
1251 return 0;
1252 if (mv->split == 1 && (i & 1 || j & 1))
1253 return 0;
1254
1255 if (mv->pred_mode == 0) {
1256 int pred[3];
1257
1258 schro_motion_dc_prediction (motion, i, j, pred);
1259
1260 entropy += schro_pack_estimate_sint (mv->u.dc.dc[0] - pred[0]);
1261 entropy += schro_pack_estimate_sint (mv->u.dc.dc[1] - pred[1]);
1262 entropy += schro_pack_estimate_sint (mv->u.dc.dc[2] - pred[2]);
1263
1264 return entropy;
1265 }
1266 if (mv->using_global)
1267 return 0;
1268 if (mv->pred_mode & 1) {
1269 int pred_x, pred_y;
1270 schro_motion_vector_prediction (motion, i, j, &pred_x, &pred_y, 1);
1271 entropy += schro_pack_estimate_sint (mv->u.vec.dx[0] - pred_x);
1272 entropy += schro_pack_estimate_sint (mv->u.vec.dy[0] - pred_y);
1273 }
1274 if (mv->pred_mode & 2) {
1275 int pred_x, pred_y;
1276 schro_motion_vector_prediction (motion, i, j, &pred_x, &pred_y, 2);
1277 entropy += schro_pack_estimate_sint (mv->u.vec.dx[1] - pred_x);
1278 entropy += schro_pack_estimate_sint (mv->u.vec.dy[1] - pred_y);
1279 }
1280 return entropy;
1281 }
1282
1283 int
schro_motion_estimate_entropy(SchroMotion * motion)1284 schro_motion_estimate_entropy (SchroMotion * motion)
1285 {
1286 SchroParams *params = motion->params;
1287 int i, j;
1288 int entropy = 0;
1289
1290 for (j = 0; j < params->y_num_blocks; j++) {
1291 for (i = 0; i < params->x_num_blocks; i++) {
1292 entropy += schro_motion_block_estimate_entropy (motion, i, j);
1293 }
1294 }
1295
1296 return entropy;
1297 }
1298
1299 #ifdef unused
1300 int
schro_motion_superblock_estimate_entropy(SchroMotion * motion,int i,int j)1301 schro_motion_superblock_estimate_entropy (SchroMotion * motion, int i, int j)
1302 {
1303 int ii, jj;
1304 int entropy = 0;
1305
1306 for (jj = j; jj < j + 4; jj++) {
1307 for (ii = i; ii < i + 4; ii++) {
1308 entropy += schro_motion_block_estimate_entropy (motion, ii, jj);
1309 }
1310 }
1311
1312 return entropy;
1313 }
1314 #endif
1315
1316 int
schro_motion_superblock_try_estimate_entropy(SchroMotion * motion,int i,int j,SchroBlock * block)1317 schro_motion_superblock_try_estimate_entropy (SchroMotion * motion, int i,
1318 int j, SchroBlock * block)
1319 {
1320 int ii, jj;
1321 int entropy = 0;
1322 SchroBlock save_block;
1323
1324 schro_motion_copy_from (motion, i, j, &save_block);
1325 schro_motion_copy_to (motion, i, j, block);
1326 for (jj = 0; jj < 4; jj++) {
1327 for (ii = 0; ii < 4; ii++) {
1328 entropy += schro_motion_block_estimate_entropy (motion, i + ii, j + jj);
1329 }
1330 }
1331 schro_motion_copy_to (motion, i, j, &save_block);
1332
1333 return entropy;
1334 }
1335
1336 int
schro_motionest_superblock_get_metric(SchroMotionEst * me,SchroBlock * block,int i,int j)1337 schro_motionest_superblock_get_metric (SchroMotionEst * me,
1338 SchroBlock * block, int i, int j)
1339 {
1340 SchroMotionVector *mv;
1341 SchroFrameData orig;
1342 int width, height;
1343 int xmin, ymin;
1344 int xmax, ymax;
1345
1346 xmin = MAX (i * me->params->xbsep_luma, 0);
1347 ymin = MAX (j * me->params->ybsep_luma, 0);
1348 xmax =
1349 MIN ((i + 4) * me->params->xbsep_luma,
1350 me->encoder_frame->filtered_frame->width);
1351 ymax =
1352 MIN ((j + 4) * me->params->ybsep_luma,
1353 me->encoder_frame->filtered_frame->height);
1354
1355 schro_frame_get_subdata (get_downsampled (me->encoder_frame, 0), &orig,
1356 0, xmin, ymin);
1357
1358 width = xmax - xmin;
1359 height = ymax - ymin;
1360
1361 mv = &block->mv[0][0];
1362
1363 if (mv->pred_mode == 0) {
1364 return schro_metric_get_dc (&orig, mv->u.dc.dc[0], width, height);
1365 }
1366 if (mv->pred_mode == 1 || mv->pred_mode == 2) {
1367 SchroFrame *ref_frame;
1368 SchroFrameData ref_data;
1369 int ref;
1370
1371 ref = mv->pred_mode - 1;
1372
1373 ref_frame = get_downsampled (me->encoder_frame->ref_frame[ref], 0);
1374
1375 if (xmin + mv->u.vec.dx[ref] < -ref_frame->extension ||
1376 ymin + mv->u.vec.dy[ref] < -ref_frame->extension ||
1377 xmax + mv->u.vec.dx[ref] >
1378 me->encoder_frame->filtered_frame->width + ref_frame->extension
1379 || ymax + mv->u.vec.dy[ref] >
1380 me->encoder_frame->filtered_frame->height + ref_frame->extension) {
1381 /* bailing because it's "hard" */
1382 return SCHRO_METRIC_INVALID_2;
1383 }
1384
1385 schro_frame_get_subdata (ref_frame, &ref_data,
1386 0, xmin + mv->u.vec.dx[ref], ymin + mv->u.vec.dy[ref]);
1387
1388 return schro_metric_get (&orig, &ref_data, width, height);
1389 }
1390
1391 if (mv->pred_mode == 3) {
1392 SchroFrame *ref0_frame;
1393 SchroFrame *ref1_frame;
1394 SchroFrameData ref0_data;
1395 SchroFrameData ref1_data;
1396
1397 ref0_frame = get_downsampled (me->encoder_frame->ref_frame[0], 0);
1398 ref1_frame = get_downsampled (me->encoder_frame->ref_frame[1], 0);
1399
1400 if (xmin + mv->u.vec.dx[0] < -ref0_frame->extension ||
1401 ymin + mv->u.vec.dy[0] < -ref0_frame->extension ||
1402 xmax + mv->u.vec.dx[0] >
1403 me->encoder_frame->filtered_frame->width + ref0_frame->extension
1404 || ymax + mv->u.vec.dy[0] >
1405 me->encoder_frame->filtered_frame->height + ref0_frame->extension
1406 || xmin + mv->u.vec.dx[1] < -ref1_frame->extension
1407 || ymin + mv->u.vec.dy[1] < -ref1_frame->extension
1408 || xmax + mv->u.vec.dx[1] >
1409 me->encoder_frame->filtered_frame->width + ref1_frame->extension
1410 || ymax + mv->u.vec.dy[1] >
1411 me->encoder_frame->filtered_frame->height + ref1_frame->extension) {
1412 /* bailing because it's "hard" */
1413 return SCHRO_METRIC_INVALID_2;
1414 }
1415
1416 schro_frame_get_subdata (ref0_frame,
1417 &ref0_data, 0, xmin + mv->u.vec.dx[0], ymin + mv->u.vec.dy[0]);
1418 schro_frame_get_subdata (ref1_frame,
1419 &ref1_data, 0, xmin + mv->u.vec.dx[1], ymin + mv->u.vec.dy[1]);
1420
1421 return schro_metric_get_biref (&orig, &ref0_data, 1, &ref1_data, 1, 1,
1422 width, height);
1423 }
1424
1425 SCHRO_ASSERT (0);
1426
1427 return SCHRO_METRIC_INVALID_2;
1428 }
1429
1430 #ifdef unused
1431 int
schro_block_check(SchroBlock * block)1432 schro_block_check (SchroBlock * block)
1433 {
1434 SchroMotionVector *sbmv;
1435 SchroMotionVector *bmv;
1436 SchroMotionVector *mv;
1437 int i, j;
1438
1439 sbmv = &block->mv[0][0];
1440 for (j = 0; j < 4; j++) {
1441 for (i = 0; i < 4; i++) {
1442 mv = &block->mv[j][i];
1443
1444 switch (sbmv->split) {
1445 case 0:
1446 if (!schro_motion_vector_is_equal (mv, sbmv)) {
1447 SCHRO_ERROR ("mv(%d,%d) not equal to superblock mv", i, j);
1448 return 0;
1449 }
1450 break;
1451 case 1:
1452 bmv = &block->mv[(j & ~1)][(i & ~1)];
1453 if (!schro_motion_vector_is_equal (mv, bmv)) {
1454 SCHRO_ERROR ("mv(%d,%d) not equal to 2-block mv", i, j);
1455 return 0;
1456 }
1457 break;
1458 case 2:
1459 break;
1460 default:
1461 SCHRO_ERROR ("mv(%d,%d) has bad split", i, j);
1462 return 0;
1463 break;
1464 }
1465 }
1466 }
1467
1468 return 1;
1469 }
1470 #endif
1471
1472 void
schro_block_fixup(SchroBlock * block)1473 schro_block_fixup (SchroBlock * block)
1474 {
1475 SchroMotionVector *mv;
1476
1477 mv = &block->mv[0][0];
1478 if (mv->split == 0) {
1479 mv[1] = mv[0];
1480 mv[2] = mv[0];
1481 mv[3] = mv[0];
1482 memcpy (mv + 4, mv, 4 * sizeof (*mv));
1483 memcpy (mv + 8, mv, 4 * sizeof (*mv));
1484 memcpy (mv + 12, mv, 4 * sizeof (*mv));
1485 }
1486 if (mv->split == 1) {
1487 mv[1] = mv[0];
1488 mv[3] = mv[2];
1489 memcpy (mv + 4, mv, 4 * sizeof (*mv));
1490 mv[9] = mv[8];
1491 mv[11] = mv[10];
1492 memcpy (mv + 12, mv + 8, 4 * sizeof (*mv));
1493 }
1494 }
1495
1496 void
schro_motion_copy_from(SchroMotion * motion,int i,int j,SchroBlock * block)1497 schro_motion_copy_from (SchroMotion * motion, int i, int j, SchroBlock * block)
1498 {
1499 SchroMotionVector *mv;
1500 int ii, jj;
1501
1502 for (jj = 0; jj < 4; jj++) {
1503 for (ii = 0; ii < 4; ii++) {
1504 mv = SCHRO_MOTION_GET_BLOCK (motion, i + ii, j + jj);
1505 block->mv[jj][ii] = *mv;
1506 }
1507 }
1508 }
1509
1510 void
schro_motion_copy_to(SchroMotion * motion,int i,int j,SchroBlock * block)1511 schro_motion_copy_to (SchroMotion * motion, int i, int j, SchroBlock * block)
1512 {
1513 SchroMotionVector *mv;
1514 int ii, jj;
1515
1516 for (jj = 0; jj < 4; jj++) {
1517 for (ii = 0; ii < 4; ii++) {
1518 mv = SCHRO_MOTION_GET_BLOCK (motion, i + ii, j + jj);
1519 *mv = block->mv[jj][ii];
1520 }
1521 }
1522 }
1523
1524 /* performs single position block matching for split2
1525 * to calculate SAD */
1526 static void
schro_get_split2_metric(SchroMe * me,int ref,int i,int j,SchroMotionVector * mv,int * metric,SchroFrameData * fd)1527 schro_get_split2_metric (SchroMe * me, int ref, int i, int j,
1528 SchroMotionVector * mv, int *metric, SchroFrameData * fd)
1529 {
1530 SchroParams *params = schro_me_params (me);
1531 SchroFrameData orig[2], ref_data[2];
1532 SchroFrame *frame = schro_me_src (me);
1533 SchroUpsampledFrame *upframe;
1534 int mv_prec = params->mv_precision;
1535 int fd_width, fd_height;
1536 int width[3], height[3], dx, dy;
1537 int k;
1538 int tmp_x, tmp_y;
1539 int block_x[3], block_y[3];
1540
1541 /* calculates split2 block sizes for all components */
1542 block_x[0] = params->xbsep_luma;
1543 block_y[0] = params->ybsep_luma;
1544 block_x[1] = block_x[2] =
1545 block_x[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
1546 video_format->chroma_format);
1547 block_y[1] = block_y[2] =
1548 block_y[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
1549 video_format->chroma_format);
1550
1551 /* get source data if possible */
1552 for (k = 1; 3 > k; ++k) {
1553 if (!schro_frame_get_data (frame, &orig[k - 1], k, i * block_x[k],
1554 j * block_y[k])) {
1555 *metric = INT_MAX;
1556 return;
1557 }
1558 width[k] = MIN (block_x[k], orig[k - 1].width);
1559 height[k] = MIN (block_y[k], orig[k - 1].height);
1560 }
1561 upframe = schro_me_ref (me, ref);
1562 *metric = 0;
1563 for (k = 1; 3 > k; ++k) {
1564 /* get ref data, if possible */
1565 tmp_x = (i * block_x[k]) << mv_prec;
1566 tmp_y = (j * block_y[k]) << mv_prec;
1567 dx = mv->u.vec.dx[ref];
1568 dx >>= SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
1569 dx += tmp_x;
1570 dy = mv->u.vec.dy[ref];
1571 dy >>= SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
1572 dy += tmp_y;
1573 if (INT_MAX == mv->metric) {
1574 *metric = INT_MAX;
1575 return;
1576 }
1577 /* I need to save the original value of fd width and height */
1578 fd_width = fd->width;
1579 fd_height = fd->height;
1580 fd->width = width[k];
1581 fd->height = height[k];
1582
1583 schro_upsampled_frame_get_block_fast_precN (upframe, k, dx, dy, mv_prec,
1584 &ref_data[k - 1], fd);
1585 fd->width = fd_width;
1586 fd->height = fd_height;
1587 *metric +=
1588 schro_metric_absdiff_u8 (orig[k - 1].data, orig[k - 1].stride,
1589 ref_data[k - 1].data, ref_data[k - 1].stride, width[k], height[k]);
1590 }
1591 mv->chroma_metric = *metric;
1592 *metric += mv->metric;
1593 return;
1594 }
1595
1596
1597 /* performs mode decision for a superblock, split level 2
1598 * Note that a SchroMotion object is required to estimate
1599 * the cost of the different prediction modes. */
1600 static void
schro_do_split2(SchroMe * me,int i,int j,SchroBlock * block,SchroFrameData * fd)1601 schro_do_split2 (SchroMe * me, int i, int j, SchroBlock * block,
1602 SchroFrameData * fd)
1603 {
1604 int total_entropy = 0, total_error = 0, ii, jj, ref;
1605 double lambda = schro_me_lambda (me); /* frame->frame_me_lambda; */
1606 int comp_w[3], comp_h[3];
1607 SchroParams *params = schro_me_params (me);
1608 SchroMotion *motion = schro_me_motion (me);
1609 int mvprec = params->mv_precision;
1610 int xnum_blocks = params->x_num_blocks;
1611 int fd_width, fd_height, biref;
1612 int xblen = params->xbsep_luma, yblen = params->ybsep_luma;
1613 SchroFrame *orig_frame = schro_me_src (me);
1614 SchroFrameData ref_data[3][2], orig[3];
1615 SchroUpsampledFrame *upframe[2];
1616 SchroMotionField *mf;
1617 int xmin, ymin, xmax, ymax;
1618
1619 xmin = ymin = -orig_frame->extension;
1620 xmax = (orig_frame->width << mvprec) + orig_frame->extension;
1621 ymax = (orig_frame->height << mvprec) + orig_frame->extension;
1622
1623 comp_w[0] = xblen;
1624 comp_h[0] = yblen;
1625 comp_w[1] = comp_w[2] = xblen
1626 >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
1627 comp_h[1] = comp_h[2] = yblen
1628 >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
1629
1630
1631 for (jj = 0; 4 > jj; ++jj) {
1632 for (ii = 0; 4 > ii; ++ii) {
1633 double score, min_score = HUGE_VAL;
1634 int entropy[2], error;
1635 int width[3], height[3];
1636 int dx[2], dy[2];
1637 int k;
1638 int best_entropy = INT_MAX, best_error = INT_MAX;
1639 SchroMotionVector *mv, *mv_ref[2], best_mv = { 0 };
1640 best_mv.split = 2;
1641 best_mv.pred_mode = 1;
1642
1643 mv_ref[0] = mv_ref[1] = NULL;
1644 memset (entropy, 0, sizeof (entropy));
1645 memset (width, 0, sizeof (width));
1646 memset (height, 0, sizeof (height));
1647 mv = motion->motion_vectors + (j + jj) * xnum_blocks + i + ii;
1648 /* check that the block lies whitin the frame */
1649 if (!(orig_frame->width > (i + ii) * xblen)
1650 || !(orig_frame->height > (j + jj) * yblen)) {
1651 /* Note: blocks outside frame are encoded pred_mode 1, zero MVs */
1652 int pred_x, pred_y;
1653 *mv = best_mv;
1654 mv->pred_mode =
1655 schro_motion_get_mode_prediction (motion, i + ii, j + jj);
1656 if (mv->pred_mode != 1 && mv->pred_mode != 2)
1657 mv->pred_mode = 1;
1658 schro_motion_vector_prediction (motion, i + ii, j + jj, &pred_x,
1659 &pred_y, 1);
1660 mv->u.vec.dx[mv->pred_mode - 1] = pred_x;
1661 mv->u.vec.dy[mv->pred_mode - 1] = pred_y;
1662 block->mv[jj][ii] = best_mv;
1663 total_entropy += 2;
1664 continue;
1665 }
1666 mv->metric = INT_MAX;
1667
1668 /* do the 2 references, if available */
1669 for (ref = 0; params->num_refs > ref; ++ref) {
1670 mf = schro_me_split2_mf (me, ref);
1671 SCHRO_ASSERT (mf);
1672 mv_ref[ref] = mf->motion_vectors + (j + jj) * xnum_blocks + i + ii;
1673 *mv = *mv_ref[ref];
1674 mv->split = 2;
1675 mv->pred_mode = ref + 1;
1676 mv->using_global = 0;
1677 entropy[ref] =
1678 schro_motion_block_estimate_entropy (motion, i + ii, j + jj);
1679 schro_get_split2_metric (me, ref, i + ii, j + jj, mv, &error, fd);
1680 score = entropy[ref] + error * lambda;
1681 if (min_score > score) {
1682 min_score = score;
1683 best_mv = *mv;
1684 best_entropy = entropy[ref];
1685 best_error = mv->metric;
1686 }
1687 }
1688 /* do biref, if available */
1689 if (1 < params->num_refs) {
1690 /* Note: I need to calculate the cost of biref prediction */
1691 biref = TRUE; /* flag - either or both MVs could be outside frame+ext */
1692 mv->u.vec.dx[0] = mv_ref[0]->u.vec.dx[0];
1693 mv->u.vec.dy[0] = mv_ref[0]->u.vec.dy[0];
1694 mv->u.vec.dx[1] = mv_ref[1]->u.vec.dx[1];
1695 mv->u.vec.dy[1] = mv_ref[1]->u.vec.dy[1];
1696 mv->pred_mode = 3;
1697 mv->using_global = 0;
1698 for (k = 0; 3 > k; ++k) {
1699 int tmp_x;
1700 int tmp_y;
1701
1702 /* fetch dource data for all components */
1703 schro_frame_get_data (orig_frame, &orig[k], k, (i + ii) * comp_w[k],
1704 (j + jj) * comp_h[k]);
1705 width[k] = MIN (comp_w[k], orig[k].width);
1706 height[k] = MIN (comp_h[k], orig[k].height);
1707 tmp_x = (i + ii) * (comp_w[k] << mvprec);
1708 tmp_y = (j + jj) * (comp_h[k] << mvprec);
1709 for (ref = 0; params->num_refs > ref; ++ref) {
1710 dx[ref] = mv->u.vec.dx[ref];
1711 dx[ref] >>= 0 == k ? 0
1712 : SCHRO_CHROMA_FORMAT_H_SHIFT (params->
1713 video_format->chroma_format);
1714 dx[ref] += tmp_x;
1715 dy[ref] = mv->u.vec.dy[ref];
1716 dy[ref] >>= 0 == k ? 0
1717 : SCHRO_CHROMA_FORMAT_V_SHIFT (params->
1718 video_format->chroma_format);
1719 dy[ref] += tmp_y;
1720 if (0 == k && biref && (xmin > dx[ref] || ymin > dy[ref]
1721 || !(xmax > dx[ref] + width[k] - 1)
1722 || !(ymax > dy[ref] + height[k] - 1))) {
1723 biref = FALSE;
1724 break;
1725 }
1726 /* I need to save the original value of fd width and height */
1727 fd_width = fd[ref].width;
1728 fd_height = fd[ref].height;
1729 fd[ref].width = width[k];
1730 fd[ref].height = height[k];
1731 upframe[ref] = schro_me_ref (me, ref);
1732 schro_upsampled_frame_get_block_fast_precN (upframe[ref], k, dx[ref]
1733 , dy[ref], mvprec, &ref_data[k][ref], &fd[ref]);
1734 fd[ref].width = fd_width;
1735 fd[ref].height = fd_height;
1736 }
1737 }
1738 if (biref) {
1739 mv->metric =
1740 schro_metric_get_biref (&orig[0], &ref_data[0][0], 1,
1741 &ref_data[0][1], 1, 1, width[0], height[0]);
1742 mv->chroma_metric = 0;
1743 for (k = 1; 3 > k; ++k) {
1744 mv->chroma_metric +=
1745 schro_metric_get_biref (&orig[k], &ref_data[k][0], 1,
1746 &ref_data[k][1], 1, 1, width[k], height[k]);
1747 }
1748 score =
1749 entropy[0] + entropy[1] + (mv->metric +
1750 mv->chroma_metric) * lambda;
1751 if (min_score > score) {
1752 best_error = mv->metric + mv->chroma_metric;
1753 best_entropy = entropy[0] + entropy[1];
1754 best_mv = *mv;
1755 min_score = score;
1756 }
1757 }
1758 }
1759
1760 /* FIXME: magic used for considering DC prediction */
1761 if (4 * (width[0] * height[0] + 2 * width[1] * height[1]) < best_error) {
1762 /* let's consider DC prediction */
1763 SchroMotionVector *mvdc;
1764 int k;
1765 int ok = TRUE;
1766
1767 mvdc = (SchroMotionVector *) mv;
1768 mvdc->pred_mode = 0;
1769 mvdc->split = 2;
1770 mvdc->using_global = 0;
1771 error = 0;
1772 for (k = 0; 3 > k; ++k) {
1773 int tmp = schro_block_average (&mvdc->u.dc.dc[k],
1774 orig_frame->components + k, (i + ii) * comp_w[k],
1775 (j + jj) * comp_h[k], comp_w[k], comp_h[k]);
1776 if (SCHRO_METRIC_INVALID_2 == tmp) {
1777 SCHRO_DEBUG ("Invalid DC metric");
1778 mvdc->metric = INT_MAX;
1779 ok = FALSE;
1780 } else {
1781 error += tmp;
1782 }
1783 }
1784 if (ok) {
1785 mvdc->metric = error;
1786 /* FIXME: we're assuming that the block doesn't have any predictor */
1787 entropy[0] = schro_pack_estimate_sint (mvdc->u.dc.dc[0]);
1788 entropy[0] += schro_pack_estimate_sint (mvdc->u.dc.dc[1]);
1789 entropy[0] += schro_pack_estimate_sint (mvdc->u.dc.dc[2]);
1790 if (error < best_error) {
1791 best_mv = *(SchroMotionVector *) mvdc;
1792 best_error = mvdc->metric;
1793 best_entropy = entropy[0];
1794 }
1795 }
1796 }
1797 *mv = best_mv;
1798 total_error += best_error;
1799 total_entropy += best_entropy;
1800 block->mv[jj][ii] = best_mv;
1801 }
1802 }
1803 block->valid = TRUE;
1804 block->error = total_error;
1805 block->entropy = total_entropy;
1806 block->score = total_entropy + lambda * total_error;
1807 }
1808
1809 static void
set_split1_motion(SchroMotion * motion,int i,int j)1810 set_split1_motion (SchroMotion * motion, int i, int j)
1811 {
1812 SchroParams *params = motion->params;
1813 int xnum_blocks = params->x_num_blocks;
1814 SchroMotionVector *mv = motion->motion_vectors + j * xnum_blocks + i;
1815
1816 *(mv + 1) = *mv;
1817 *(mv + xnum_blocks) = *mv;
1818 *(mv + xnum_blocks + 1) = *mv;
1819 }
1820
1821 static int
mv_already_in_list(SchroMotionVector * hint_list[],int len,SchroMotionVector * candidate_mv,int ref,int shift)1822 mv_already_in_list (SchroMotionVector * hint_list[], int len,
1823 SchroMotionVector * candidate_mv, int ref, int shift)
1824 {
1825 int i;
1826
1827 for (i = 0; len > i; ++i) {
1828 if ((candidate_mv->u.vec.dx[ref] << shift) == hint_list[i]->u.vec.dx[ref]
1829 && (candidate_mv->u.vec.dy[ref] << shift) ==
1830 hint_list[i]->u.vec.dy[ref]) {
1831 return TRUE;
1832 }
1833 }
1834 return FALSE;
1835 }
1836
1837 /* select a MV for a split1 block based on 5 seeds
1838 the four split 2 MVs and the MV from rough ME, level 1.
1839 The selection of the MV is based on actual cost, not just SAD */
1840 static void
schro_get_best_mv_split1(SchroMe * me,int ref,int i,int j,SchroMotionVector * mv_ref,int * error,int * entropy,SchroFrameData * fd)1841 schro_get_best_mv_split1 (SchroMe * me, int ref, int i, int j,
1842 SchroMotionVector * mv_ref, int *error, int *entropy, SchroFrameData * fd)
1843 {
1844 SchroMotionVector *hint_mv[6], *mv_motion;
1845 SchroMotionVector *mv, temp_mv = { 0 };
1846 SchroMotionField *mf;
1847 SchroParams *params = schro_me_params (me);
1848 SchroFrameData orig[3], ref_data[3];
1849 SchroFrame *frame = schro_me_src (me);
1850 SchroUpsampledFrame *upframe;
1851 SchroMotion *motion = schro_me_motion (me);
1852 int n = 0, ii, jj, m = 0, min_m, metric, ent;
1853 int mv_prec = params->mv_precision;
1854 int fd_width, fd_height;
1855 double score, min_score, lambda = schro_me_lambda (me);
1856 int xblen, yblen, width[3], height[3], dx, dy;
1857 int comp_w[3], comp_h[3];
1858 int k;
1859 int xmin, xmax, ymin, ymax, tmp_x, tmp_y;
1860 int best_error = INT_MAX, best_entropy = INT_MAX;
1861 int best_chroma_error = INT_MAX;
1862 int block_x[3], block_y[3];
1863 SchroHierBm *hbm;
1864
1865 xblen = params->xbsep_luma << 1;
1866 yblen = params->ybsep_luma << 1;
1867 xmin = ymin = -frame->extension;
1868 xmax = (frame->width << mv_prec) + frame->extension;
1869 ymax = (frame->height << mv_prec) + frame->extension;
1870 /* calculate split1 block sizes for all components */
1871 comp_w[0] = xblen;
1872 comp_h[0] = yblen;
1873 comp_w[1] = comp_w[2] = xblen
1874 >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
1875 comp_h[1] = comp_h[2] = yblen
1876 >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
1877 /* calculates split2 block sizes for all components */
1878 block_x[0] = params->xbsep_luma;
1879 block_y[0] = params->ybsep_luma;
1880 block_x[1] = block_x[2] =
1881 block_x[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
1882 video_format->chroma_format);
1883 block_y[1] = block_y[2] =
1884 block_y[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
1885 video_format->chroma_format);
1886
1887 SCHRO_ASSERT (motion);
1888 mv_motion = motion->motion_vectors + j * params->x_num_blocks + i;
1889
1890 for (k = 0; 3 > k; ++k) {
1891 /* get source data if possible */
1892 if (!schro_frame_get_data (frame, &orig[k], k, i * block_x[k],
1893 j * block_y[k])) {
1894 *mv_ref = temp_mv;
1895 mv_ref->metric = INT_MAX;
1896 mv_ref->pred_mode = ref + 1;
1897 *error = INT_MAX;
1898 *mv_motion = *mv_ref;
1899 *entropy = schro_motion_block_estimate_entropy (motion, i, j);
1900 return;
1901 }
1902 width[k] = MIN (comp_w[k], orig[k].width);
1903 height[k] = MIN (comp_h[k], orig[k].height);
1904 }
1905 /* inherit from split 2 level MV */
1906 mf = schro_me_subpel_mf (me, ref);
1907 SCHRO_ASSERT (mf);
1908 for (jj = 0; 2 > jj; ++jj) {
1909 for (ii = 0; 2 > ii; ++ii) {
1910 mv = mf->motion_vectors + (j + jj) * mf->x_num_blocks + i + ii;
1911 if (SCHRO_METRIC_INVALID != mv->metric) {
1912 if ((0 < n && !mv_already_in_list (hint_mv, n, mv, ref, mv_prec))
1913 || 0 == n) {
1914 hint_mv[n++] = mv;
1915 }
1916 }
1917 }
1918 }
1919 /* inherit from stage 1 of hier. BM */
1920 hbm = schro_me_hbm (me, ref);
1921 SCHRO_ASSERT (hbm);
1922 mf = schro_hbm_motion_field (hbm, 1);
1923 SCHRO_ASSERT (mf);
1924 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
1925 if (INT_MAX != mv->metric) {
1926 if ((0 < n && !mv_already_in_list (hint_mv, n, mv, ref, mv_prec)) || 0 == n) {
1927 temp_mv = *mv;
1928 temp_mv.u.vec.dx[ref] <<= mv_prec;
1929 temp_mv.u.vec.dy[ref] <<= mv_prec;
1930 hint_mv[n++] = &temp_mv;
1931 }
1932 }
1933
1934 /* now pick the best candidate */
1935 min_m = -1;
1936 min_score = HUGE_VAL;
1937 upframe = schro_me_ref (me, ref);
1938 for (m = 0; n > m; ++m) {
1939 int chroma_metric = 0;
1940 int ok = TRUE;
1941
1942 metric = 0;
1943 for (k = 0; 3 > k; ++k) {
1944 tmp_x = (i * block_x[k]) << mv_prec;
1945 tmp_y = (j * block_y[k]) << mv_prec;
1946 dx = hint_mv[m]->u.vec.dx[ref];
1947 dx >>= 0 == k ? 0
1948 : SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
1949 dx += tmp_x;
1950 dy = hint_mv[m]->u.vec.dy[ref];
1951 dy >>= 0 == k ? 0
1952 : SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
1953 dy += tmp_y;
1954 if (0 == k && (xmin > dx || ymin > dy
1955 || !(xmax > dx + width[k] - 1) || !(ymax > dy + height[k] - 1))) {
1956 k = 3;
1957 ok = FALSE;
1958 continue;
1959 }
1960 /* I need to save the original value of fd width and height */
1961 fd_width = fd->width;
1962 fd_height = fd->height;
1963 fd->width = width[k];
1964 fd->height = height[k];
1965
1966 schro_upsampled_frame_get_block_fast_precN (upframe, k, dx, dy, mv_prec,
1967 &ref_data[k], fd);
1968 fd->width = fd_width;
1969 fd->height = fd_height;
1970 if (0 == k) {
1971 metric =
1972 schro_metric_absdiff_u8 (orig[0].data, orig[0].stride,
1973 ref_data[0].data, ref_data[0].stride, width[0], height[0]);
1974 } else {
1975 chroma_metric +=
1976 schro_metric_absdiff_u8 (orig[k].data, orig[k].stride,
1977 ref_data[k].data, ref_data[k].stride, width[k], height[k]);
1978 }
1979 }
1980 if (ok) {
1981 *mv_motion = *hint_mv[m];
1982 mv_motion->split = 1;
1983 mv_motion->pred_mode = ref + 1;
1984 ent = schro_motion_block_estimate_entropy (motion, i, j);
1985 score = ent + (metric + chroma_metric) * lambda;
1986 if (min_score > score) {
1987 min_score = score;
1988 min_m = m;
1989 best_entropy = ent;
1990 best_error = metric;
1991 best_chroma_error = chroma_metric;
1992 }
1993 }
1994 }
1995 if (-1 < min_m) {
1996 *error = best_error + best_chroma_error;
1997 *entropy = best_entropy;
1998 *mv_ref = *hint_mv[min_m];
1999 mv_ref->metric = best_error >> 2;
2000 mv_ref->chroma_metric = best_chroma_error >> 2;
2001 mv_ref->split = 1;
2002 mv_ref->pred_mode = ref + 1;
2003 } else
2004 mv_ref->metric = INT_MAX;
2005 }
2006
2007 /* performs mode decision for a superblock, split level 1 */
2008 static void
schro_do_split1(SchroMe * me,int i,int j,SchroBlock * block,SchroFrameData * fd)2009 schro_do_split1 (SchroMe * me, int i, int j, SchroBlock * block,
2010 SchroFrameData * fd)
2011 {
2012 SchroParams *params = schro_me_params (me);
2013 SchroMotion *motion = schro_me_motion (me);
2014 SchroFrame *orig_frame = schro_me_src (me);
2015 SchroFrameData ref_data[3][2], orig[3];
2016 SchroUpsampledFrame *upframe[2];
2017 SchroMotionField *mf;
2018 double lambda = schro_me_lambda (me);
2019 int ii, jj, ref, biref, k;
2020 int total_entropy = 0, total_error = 0;
2021 int mvprec = params->mv_precision;
2022 int xblen = params->xbsep_luma * 2, yblen = params->ybsep_luma * 2;
2023 int width[3], height[3], dx[2], dy[2], tmp_x, tmp_y;
2024 int fd_width, fd_height;
2025 int xmin, xmax, ymin, ymax;
2026 int comp_h[3], comp_w[3];
2027 int block_x[3], block_y[3];
2028
2029 xmin = ymin = -orig_frame->extension;
2030 xmax = (orig_frame->width << mvprec) + orig_frame->extension;
2031 ymax = (orig_frame->height << mvprec) + orig_frame->extension;
2032
2033 comp_w[0] = xblen;
2034 comp_h[0] = yblen;
2035 comp_w[1] = comp_w[2] = xblen
2036 >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
2037 comp_h[1] = comp_h[2] = yblen
2038 >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
2039 block_x[0] = params->xbsep_luma;
2040 block_y[0] = params->ybsep_luma;
2041 block_x[1] = block_x[2] =
2042 block_x[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
2043 video_format->chroma_format);
2044 block_y[1] = block_y[2] =
2045 block_y[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
2046 video_format->chroma_format);
2047
2048 block->valid = TRUE;
2049
2050 for (jj = 0; 4 > jj; jj += 2) {
2051 for (ii = 0; 4 > ii; ii += 2) {
2052 double score, min_score = HUGE_VAL;
2053 int entropy[2], error = INT_MAX;
2054 int best_entropy = INT_MAX, best_chroma_error = INT_MAX, best_error =
2055 INT_MAX;
2056 /* Note that the metric for the split 1 block will be stored in best_mv
2057 * but divided by 4 */
2058 SchroMotionVector *mv, best_mv = { 0 }, mv_ref[2], *mv_split1;
2059 best_mv.split = 1;
2060 best_mv.pred_mode = 1;
2061
2062 mv = motion->motion_vectors + (j + jj) * params->x_num_blocks + i + ii;
2063 /* check that the block lies within the frame */
2064 if (!(orig_frame->width > (i + ii) * params->xbsep_luma)
2065 || !(orig_frame->height > (j + jj) * params->ybsep_luma)) {
2066 /* the block lies outside the frame, set both block and motion
2067 * to a zero mv, split 1, forward predicted */
2068 int pred_x, pred_y;
2069 *mv = best_mv;
2070 mv->pred_mode =
2071 schro_motion_get_mode_prediction (motion, i + ii, j + jj);
2072 if (mv->pred_mode != 1 && mv->pred_mode != 2)
2073 mv->pred_mode = 1;
2074 schro_motion_vector_prediction (motion, i + ii, j + jj, &pred_x,
2075 &pred_y, 1);
2076 mv->u.vec.dx[mv->pred_mode - 1] = pred_x;
2077 mv->u.vec.dy[mv->pred_mode - 1] = pred_y;
2078 block->mv[jj][ii] = *mv;
2079 set_split1_motion (motion, i + ii, j + jj);
2080 total_entropy += 2;
2081 mf = schro_me_split1_mf (me, 0);
2082 SCHRO_ASSERT (mf);
2083 mv_split1 =
2084 mf->motion_vectors + (j + jj) * params->x_num_blocks + i + ii;
2085 *mv_split1 = best_mv;
2086 if (1 < params->num_refs) {
2087 mf = schro_me_split1_mf (me, 1);
2088 SCHRO_ASSERT (mf);
2089 mv_split1 =
2090 mf->motion_vectors + (j + jj) * params->x_num_blocks + i + ii;
2091 *mv_split1 = best_mv;
2092 mv_split1->pred_mode = 2;
2093 }
2094 continue;
2095 }
2096 mv->metric = INT_MAX;
2097 mv->chroma_metric = INT_MAX;
2098 best_mv.metric = INT_MAX;
2099 best_mv.chroma_metric = INT_MAX;
2100
2101 /* do the 2 references, if available */
2102 for (ref = 0; params->num_refs > ref; ++ref) {
2103 mf = schro_me_split1_mf (me, ref);
2104 SCHRO_ASSERT (mf);
2105 mv_split1 =
2106 mf->motion_vectors + (j + jj) * params->x_num_blocks + i + ii;
2107 schro_get_best_mv_split1 (me, ref, i + ii, j + jj, &mv_ref[ref]
2108 , &error, &entropy[ref], fd);
2109 *mv_split1 = mv_ref[ref];
2110 if (INT_MAX != mv_ref[ref].metric) {
2111 score = entropy[ref] + lambda * error;
2112 if (min_score > score) {
2113 min_score = score;
2114 best_mv = mv_ref[ref];
2115 best_entropy = entropy[ref];
2116 best_error = error;
2117 }
2118 }
2119 }
2120 /* do biref if available */
2121 if (1 < params->num_refs
2122 && SCHRO_METRIC_INVALID != mv_ref[0].metric
2123 && SCHRO_METRIC_INVALID != mv_ref[1].metric) {
2124 /* I'm going to use the two best MVs from previous steps
2125 * Note: I need to calculate the cost and entropy of biref */
2126 mv_ref[0].u.vec.dx[1] = mv_ref[1].u.vec.dx[1];
2127 mv_ref[0].u.vec.dy[1] = mv_ref[1].u.vec.dy[1];
2128 mv_ref[0].pred_mode = 3;
2129 biref = TRUE;
2130 for (k = 0; 3 > k; ++k) {
2131 schro_frame_get_data (orig_frame, &orig[k], k, (i + ii) * block_x[k],
2132 (j + jj) * block_y[k]);
2133 width[k] = MIN (comp_w[k], orig[k].width);
2134 height[k] = MIN (comp_h[k], orig[k].height);
2135 tmp_x = (i + ii) * (block_x[k] << mvprec);
2136 tmp_y = (j + jj) * (block_y[k] << mvprec);
2137 for (ref = 0; params->num_refs > ref; ++ref) {
2138 dx[ref] = mv_ref[0].u.vec.dx[ref];
2139 dx[ref] >>= 0 == k ? 0
2140 : SCHRO_CHROMA_FORMAT_H_SHIFT (params->
2141 video_format->chroma_format);
2142 dx[ref] += tmp_x;
2143 dy[ref] = mv_ref[0].u.vec.dy[ref];
2144 dy[ref] >>= 0 == k ? 0
2145 : SCHRO_CHROMA_FORMAT_V_SHIFT (params->
2146 video_format->chroma_format);
2147 dy[ref] += tmp_y;
2148 /* check whether we can extract reference blocks */
2149 if (0 == k && biref && (xmin > dx[ref] || ymin > dy[ref]
2150 || !(xmax > dx[ref] + width[k] - 1)
2151 || !(ymax > dy[ref] + height[k] - 1))) {
2152 biref = FALSE;
2153 k = 3;
2154 break;
2155 }
2156 /* I need to save the original value of fd width and height */
2157 fd_width = fd[ref].width;
2158 fd_height = fd[ref].height;
2159 fd[ref].width = width[k];
2160 fd[ref].height = height[k];
2161 upframe[ref] = schro_me_ref (me, ref);
2162 schro_upsampled_frame_get_block_fast_precN (upframe[ref], k,
2163 dx[ref], dy[ref], mvprec, &ref_data[k][ref], &fd[ref]);
2164 fd[ref].width = fd_width;
2165 fd[ref].height = fd_height;
2166 }
2167 }
2168 if (biref) {
2169 int chroma_error = 0;
2170
2171 error = 0;
2172 error =
2173 schro_metric_get_biref (&orig[0], &ref_data[0][0], 1,
2174 &ref_data[0][1], 1, 1, width[0], height[0]);
2175 for (k = 1; 3 > k; ++k) {
2176 chroma_error +=
2177 schro_metric_get_biref (&orig[k], &ref_data[k][0], 1,
2178 &ref_data[k][1], 1, 1, width[k], height[k]);
2179 }
2180 score = entropy[0] + entropy[1] + lambda * (error + chroma_error);
2181 mv_ref[0].metric = error >> 2;
2182 mv_ref[0].chroma_metric = chroma_error >> 2;
2183 if (min_score > score) {
2184 best_error = error;
2185 best_chroma_error = chroma_error;
2186 best_entropy = entropy[0] + entropy[1];
2187 best_mv = mv_ref[0];
2188 min_score = score;
2189 }
2190 }
2191 }
2192 if (SCHRO_METRIC_INVALID == best_mv.metric) {
2193 block->valid = FALSE;
2194 } else {
2195 *mv = best_mv;
2196 total_error += best_error + best_chroma_error;
2197 total_entropy += best_entropy;
2198 block->mv[jj][ii] = best_mv;
2199 set_split1_motion (motion, i + ii, j + jj);
2200 }
2201 }
2202 }
2203 block->error = total_error;
2204 block->entropy = total_entropy;
2205 block->score = total_entropy + lambda * total_error;
2206 }
2207
2208 static void
schro_get_best_split0_mv(SchroMe * me,int ref,int i,int j,SchroMotionVector * mv_ref,int * error,int * entropy,SchroFrameData * fd)2209 schro_get_best_split0_mv (SchroMe * me, int ref, int i, int j,
2210 SchroMotionVector * mv_ref, int *error, int *entropy, SchroFrameData * fd)
2211 {
2212 SchroMotionVector *hint_mv[6], *mv_motion;
2213 SchroMotionVector *mv, temp_mv = { 0 };
2214 SchroMotionField *mf;
2215 SchroParams *params = schro_me_params (me);
2216 SchroFrameData orig[3], ref_data[3];
2217 SchroFrame *frame = schro_me_src (me);
2218 SchroUpsampledFrame *upframe;
2219 SchroHierBm *hbm;
2220 SchroMotion *motion = schro_me_motion (me);
2221 int n = 0, m = 0, min_m = -1, metric = 0, ent;
2222 int mv_prec = params->mv_precision;
2223 int fd_width, fd_height, jj, ii;
2224 int k;
2225 double score, min_score = HUGE_VAL, lambda = schro_me_lambda (me);
2226 int width[3], height[3], dx, dy, xmin, xmax, ymin, ymax, tmp_x, tmp_y;
2227 int best_error = INT_MAX, best_chroma_error = INT_MAX, best_entropy = INT_MAX;
2228 int comp_w[3], comp_h[3];
2229 /* split2 block sizes for all components */
2230 int block_x[3], block_y[3];
2231
2232 block_x[0] = params->xbsep_luma;
2233 block_y[0] = params->ybsep_luma;
2234 block_x[1] = block_x[2] =
2235 block_x[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
2236 video_format->chroma_format);
2237 block_y[1] = block_y[2] =
2238 block_y[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
2239 video_format->chroma_format);
2240 /* split0 block sizes for all components */
2241 comp_w[0] = block_x[0] << 2;
2242 comp_h[0] = block_y[0] << 2;
2243 comp_w[1] = comp_w[2] =
2244 comp_w[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
2245 video_format->chroma_format);
2246 comp_h[1] = comp_h[2] =
2247 comp_h[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
2248 video_format->chroma_format);
2249
2250 xmin = -frame->extension;
2251 ymin = -frame->extension;
2252 xmax = (frame->width << mv_prec) + frame->extension;
2253 ymax = (frame->height << mv_prec) + frame->extension;
2254
2255 /* get source data if possible */
2256 for (k = 0; 3 > k; ++k) {
2257 if (!schro_frame_get_data (frame, &orig[k], k, i * block_x[k],
2258 j * block_y[k])) {
2259 /* this should never happen */
2260 SCHRO_ASSERT (0);
2261 }
2262 width[k] = MIN (comp_w[k], orig[k].width);
2263 height[k] = MIN (comp_h[k], orig[k].height);
2264 }
2265 mv_motion = motion->motion_vectors + j * params->x_num_blocks + i;
2266
2267 /* inherit from split 1 level MV */
2268 mf = schro_me_split1_mf (me, ref);
2269 SCHRO_ASSERT (mf);
2270 for (jj = 0; 4 > jj; jj += 2) {
2271 for (ii = 0; 4 > ii; ii += 2) {
2272 mv = mf->motion_vectors + (j + jj) * mf->x_num_blocks + i + ii;
2273 if (INT_MAX != mv->metric) {
2274 if ((0 < n && !mv_already_in_list (hint_mv, n, mv, ref, 0)) || 0 == n) {
2275 hint_mv[n++] = mv;
2276 }
2277 }
2278 }
2279 }
2280 /* inherit from stage 2 of hier. BM */
2281 hbm = schro_me_hbm (me, ref);
2282 SCHRO_ASSERT (hbm);
2283 mf = schro_hbm_motion_field (hbm, 2);
2284 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
2285 if (INT_MAX != mv->metric) {
2286 if ((0 < n && !mv_already_in_list (hint_mv, n, mv, ref, mv_prec)) || 0 == n) {
2287 temp_mv = *mv;
2288 temp_mv.u.vec.dx[ref] <<= mv_prec;
2289 temp_mv.u.vec.dy[ref] <<= mv_prec;
2290 hint_mv[n++] = &temp_mv;
2291 }
2292 }
2293 /* now pick the best candidate */
2294 tmp_x = (i * params->xbsep_luma) << mv_prec;
2295 tmp_y = (j * params->ybsep_luma) << mv_prec;
2296 upframe = schro_me_ref (me, ref);
2297 for (m = 0; n > m; ++m) {
2298 int ok = TRUE;
2299 int chroma_metric = 0;
2300 for (k = 0; 3 > k; ++k) {
2301 tmp_x = (i * block_x[k]) << mv_prec;
2302 tmp_y = (j * block_y[k]) << mv_prec;
2303 dx = hint_mv[m]->u.vec.dx[ref];
2304 dx >>= 0 == k ? 0
2305 : SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
2306 dx += tmp_x;
2307 dy = hint_mv[m]->u.vec.dy[ref];
2308 dy >>= 0 == k ? 0
2309 : SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
2310 dy += tmp_y;
2311 if (0 == k && (xmin > dx || ymin > dy
2312 || !(xmax > dx + width[k] - 1) || !(ymax > dy + height[k] - 1))) {
2313 ok = FALSE;
2314 k = 3;
2315 continue;
2316 }
2317 if (ok) {
2318 /* I need to save the original values of fd width and height */
2319 fd_width = fd->width;
2320 fd_height = fd->height;
2321 fd->width = width[k];
2322 fd->height = height[k];
2323 schro_upsampled_frame_get_block_fast_precN (upframe, k, dx, dy, mv_prec,
2324 &ref_data[k], fd);
2325 fd->width = fd_width;
2326 fd->height = fd_height;
2327 if (0 == k) {
2328 metric =
2329 schro_metric_absdiff_u8 (orig[0].data, orig[0].stride,
2330 ref_data[0].data, ref_data[0].stride, width[0], height[0]);
2331 } else {
2332 chroma_metric +=
2333 schro_metric_absdiff_u8 (orig[k].data, orig[k].stride,
2334 ref_data[k].data, ref_data[k].stride, width[k], height[k]);
2335 }
2336 }
2337 }
2338 if (ok) {
2339 *mv_motion = *hint_mv[m];
2340 mv_motion->split = 0;
2341 mv_motion->pred_mode = ref + 1;
2342 ent = schro_motion_block_estimate_entropy (motion, i, j);
2343 score = ent + lambda * (metric + chroma_metric);
2344 if (min_score > score) {
2345 min_score = score;
2346 min_m = m;
2347 best_entropy = ent;
2348 best_error = metric;
2349 best_chroma_error = chroma_metric;
2350 }
2351 }
2352 }
2353 if (-1 < min_m) {
2354 *error = best_error + best_chroma_error;
2355 *entropy = best_entropy;
2356 *mv_ref = *hint_mv[min_m];
2357 mv_ref->metric = best_error >> 4;
2358 mv_ref->chroma_metric = best_chroma_error >> 4;
2359 mv_ref->split = 0;
2360 mv_ref->pred_mode = ref + 1;
2361 } else
2362 mv_ref->metric = INT_MAX;
2363 }
2364
2365 static void
schro_do_split0_biref(SchroMe * me,int i,int j,SchroBlock * block,SchroFrameData * fd)2366 schro_do_split0_biref (SchroMe * me, int i, int j, SchroBlock * block,
2367 SchroFrameData * fd)
2368 {
2369 SchroParams *params = schro_me_params (me);
2370 int entropy = 0;
2371 SchroMotion *motion = schro_me_motion (me);
2372 SchroMotionVector *mv_motion;
2373 SchroFrame *orig_frame = schro_me_src (me);
2374 SchroFrameData ref_data[3][2], orig[3];
2375 SchroUpsampledFrame *upframe[2];
2376 double lambda = schro_me_lambda (me);
2377 int mv_prec = params->mv_precision;
2378 int width[3], height[3], dx[2], dy[2], tmp_x, tmp_y;
2379 int ref, error = INT_MAX;
2380 int xmin = -orig_frame->extension;
2381 int ymin = -orig_frame->extension;
2382 int xmax = (orig_frame->width << mv_prec) + orig_frame->extension;
2383 int ymax = (orig_frame->height << mv_prec) + orig_frame->extension;
2384 int biref, fd_width, fd_height;
2385 int k;
2386 /* split2 block sizes for all components */
2387 int block_x[3], block_y[3];
2388 int comp_w[3], comp_h[3];
2389 SchroMotionVector *mv;
2390
2391
2392 block->valid = FALSE;
2393
2394 mv_motion = motion->motion_vectors + j * params->x_num_blocks + i;
2395
2396 mv = &block->mv[0][0];
2397 mv->split = 0;
2398 mv->pred_mode = 3;
2399 mv->using_global = 0;
2400
2401 *mv_motion = *mv;
2402 entropy = schro_motion_block_estimate_entropy (motion, i, j);
2403
2404 block_x[0] = params->xbsep_luma;
2405 block_y[0] = params->ybsep_luma;
2406 block_x[1] = block_x[2] =
2407 block_x[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
2408 video_format->chroma_format);
2409 block_y[1] = block_y[2] =
2410 block_y[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
2411 video_format->chroma_format);
2412 /* split0 block sizes for all components */
2413 comp_w[0] = block_x[0] << 2;
2414 comp_h[0] = block_y[0] << 2;
2415 comp_w[1] = comp_w[2] =
2416 comp_w[0] >> SCHRO_CHROMA_FORMAT_H_SHIFT (params->
2417 video_format->chroma_format);
2418 comp_h[1] = comp_h[2] =
2419 comp_h[0] >> SCHRO_CHROMA_FORMAT_V_SHIFT (params->
2420 video_format->chroma_format);
2421
2422 /* do biref, if available */
2423 biref = TRUE;
2424 /* fetch source data */
2425 for (k = 0; 3 > k; ++k) {
2426 if (schro_frame_get_data (orig_frame, &orig[k], k, i * block_x[k],
2427 j * block_y[k])) {
2428 width[k] = MIN (orig[k].width, comp_w[k]);
2429 height[k] = MIN (orig[k].height, comp_h[k]);
2430 } else {
2431 biref = FALSE;
2432 break;
2433 }
2434 }
2435 if (biref) {
2436 /* fetch reference data, if possible */
2437 for (ref = 0; params->num_refs > ref; ++ref) {
2438 for (k = 0; 3 > k && biref; ++k) {
2439 tmp_x = (i * block_x[k]) << mv_prec;
2440 tmp_y = (j * block_y[k]) << mv_prec;
2441 dx[ref] = mv->u.vec.dx[ref];
2442 dx[ref] >>= 0 == k ? 0
2443 : SCHRO_CHROMA_FORMAT_H_SHIFT (params->video_format->chroma_format);
2444 dx[ref] += tmp_x;
2445 dy[ref] = mv->u.vec.dy[ref];
2446 dy[ref] >>= 0 == k ? 0
2447 : SCHRO_CHROMA_FORMAT_V_SHIFT (params->video_format->chroma_format);
2448 dy[ref] += tmp_y;
2449 /* check whether we can extract reference blocks */
2450 if (0 == k && (xmin > dx[ref] || ymin > dy[ref]
2451 || !(xmax > dx[ref] + width[k] - 1)
2452 || !(ymax > dy[ref] + height[k] - 1))) {
2453 biref = FALSE;
2454 break;
2455 } else {
2456 fd_width = fd[ref].width;
2457 fd_height = fd[ref].height;
2458 fd[ref].width = width[k];
2459 fd[ref].height = height[k];
2460 upframe[ref] = schro_me_ref (me, ref);
2461 schro_upsampled_frame_get_block_fast_precN (upframe[ref], k, dx[ref],
2462 dy[ref], mv_prec, &ref_data[k][ref], &fd[ref]);
2463 fd[ref].width = fd_width;
2464 fd[ref].height = fd_height;
2465 }
2466 }
2467 }
2468 if (biref) {
2469 int chroma_error = 0;
2470 error =
2471 schro_metric_get_biref (&orig[0], &ref_data[0][0], 1, &ref_data[0][1],
2472 1, 1, width[0], height[0]);
2473 for (k = 1; 3 > k; ++k) {
2474 chroma_error +=
2475 schro_metric_get_biref (&orig[k], &ref_data[k][0], 1,
2476 &ref_data[k][1], 1, 1, width[k], height[k]);
2477 }
2478 mv->metric = error >> 4;
2479 mv->chroma_metric = chroma_error >> 4;
2480 block->entropy = entropy;
2481 block->error = error + chroma_error;
2482 block->score = block->entropy + lambda * block->error;
2483 block->valid = TRUE;
2484 }
2485 }
2486 }
2487
2488 static void
schro_do_split0_biref_zero(SchroMe * me,int i,int j,SchroBlock * block,SchroFrameData * fd)2489 schro_do_split0_biref_zero (SchroMe * me, int i, int j, SchroBlock * block,
2490 SchroFrameData * fd)
2491 {
2492 SchroParams *params = schro_me_params (me);
2493 SchroMotionVector *mv;
2494
2495 SCHRO_ASSERT (1 < params->num_refs);
2496
2497 mv = &block->mv[0][0];
2498 mv->split = 0;
2499 mv->pred_mode = 3;
2500 mv->using_global = 0;
2501 mv->u.vec.dx[0] = 0;
2502 mv->u.vec.dy[0] = 0;
2503 mv->u.vec.dx[1] = 0;
2504 mv->u.vec.dy[1] = 0;
2505
2506 schro_do_split0_biref (me, i, j, block, fd);
2507 }
2508
2509 /* performs mode decision for a superblock, split level 0 */
2510 static void
schro_do_split0(SchroMe * me,int i,int j,SchroBlock * block,SchroFrameData * fd)2511 schro_do_split0 (SchroMe * me, int i, int j, SchroBlock * block,
2512 SchroFrameData * fd)
2513 {
2514 SchroParams *params = schro_me_params (me);
2515 SchroMotionField *mf;
2516 SchroMotionVector mv_ref[2], best_mv = { 0 }, *mv_split0;
2517 double lambda = schro_me_lambda (me);
2518 int ref;
2519 int error = INT_MAX;
2520 int entropy[2];
2521 int best_error = INT_MAX;
2522 int best_entropy = INT_MAX;
2523 double score, min_score = HUGE_VAL;
2524
2525 best_mv.metric = INT_MAX;
2526
2527 block->valid = FALSE;
2528
2529 /* do the 2 references, if available */
2530 for (ref = 0; params->num_refs > ref; ++ref) {
2531 mf = schro_me_split0_mf (me, ref);
2532 SCHRO_ASSERT (mf);
2533 mv_split0 = mf->motion_vectors + j * params->x_num_blocks + i;
2534 schro_get_best_split0_mv (me, ref, i, j, &mv_ref[ref], &error,
2535 &entropy[ref], fd);
2536 *mv_split0 = mv_ref[ref];
2537 if (INT_MAX != mv_ref[ref].metric) {
2538 score = entropy[ref] + lambda * error;
2539 if (min_score > score) {
2540 min_score = score;
2541 best_mv = mv_ref[ref];
2542 best_entropy = entropy[ref];
2543 best_error = error;
2544 }
2545 }
2546 }
2547 /* do biref, if available */
2548 if (1 < params->num_refs
2549 && INT_MAX != mv_ref[0].metric && INT_MAX != mv_ref[1].metric) {
2550 SchroBlock biref_block = { 0 };
2551
2552 SchroMotionVector *mv;
2553 mv = &biref_block.mv[0][0];
2554 mv->split = 0;
2555 mv->pred_mode = 3;
2556 mv->using_global = 0;
2557 mv->u.vec.dx[0] = mv_ref[0].u.vec.dx[0];
2558 mv->u.vec.dy[0] = mv_ref[0].u.vec.dy[0];
2559 mv->u.vec.dx[1] = mv_ref[1].u.vec.dx[1];
2560 mv->u.vec.dy[1] = mv_ref[1].u.vec.dy[1];
2561 mv->metric = INT_MAX;
2562
2563 schro_do_split0_biref (me, i, j, &biref_block, fd);
2564
2565 if (biref_block.valid && min_score > biref_block.score) {
2566 min_score = biref_block.score;
2567 best_mv = biref_block.mv[0][0];
2568 best_error = biref_block.error;
2569 best_entropy = biref_block.entropy;
2570 }
2571 }
2572
2573 if (INT_MAX == best_mv.metric) {
2574 block->valid = FALSE;
2575 } else {
2576 block->valid = TRUE;
2577 block->error = best_error;
2578 block->entropy = best_entropy;
2579 block->score = best_entropy + lambda * best_error;
2580 block->mv[0][0] = best_mv;
2581 }
2582 }
2583
2584
2585 /* performs mode decision and block/superblock splitting */
2586 void
schro_mode_decision(SchroMe * me)2587 schro_mode_decision (SchroMe * me)
2588 {
2589 SchroParams *params = schro_me_params (me);
2590 SchroFrameData fd[2];
2591 SchroMotion *motion = schro_me_motion (me);
2592 int i, j, ref;
2593 double total_error = 0.0;
2594 int block_size;
2595 int badblocks = 0, dcblocks = 0;
2596 double min_score;
2597 int k, l;
2598
2599 block_size = 16 * params->xbsep_luma * params->ybsep_luma;
2600 fd[0].data = fd[1].data = NULL;
2601 if (1 < params->mv_precision) {
2602 for (ref = 0; params->num_refs > ref; ++ref) {
2603 fd[ref].data = schro_malloc (block_size * sizeof (uint8_t));
2604 fd[ref].stride = fd[ref].width = params->xbsep_luma << 2;
2605 fd[ref].height = params->ybsep_luma << 2;
2606 fd[ref].length = block_size * sizeof (uint8_t);
2607 fd[ref].h_shift = fd[ref].v_shift = 0;
2608 fd[ref].format = SCHRO_FRAME_FORMAT_U8_420;
2609 }
2610 }
2611 /* we're now using chroma info for MS, increase block size accordingly */
2612 block_size = block_size * 2 / 3;
2613 /* loop over all superblocks. The indices are set to the value of the
2614 * top-left block in the SB, just like in Dave's bigblock estimation.
2615 * We'll start considering split 2 first, then split 1 and finally split 0 */
2616 for (j = 0; params->y_num_blocks > j; j += 4) {
2617 for (i = 0; params->x_num_blocks > i; i += 4) {
2618 SchroBlock block = { 0 }
2619 , tryblock = {
2620 0};
2621
2622 schro_do_split2 (me, i, j, &block, fd);
2623 min_score = block.score;
2624
2625 /* note: do_split1 writes to motion */
2626 schro_do_split1 (me, i, j, &tryblock, fd);
2627 if (tryblock.valid) {
2628 if (min_score > tryblock.score) {
2629 memcpy (&block, &tryblock, sizeof (block));
2630 schro_block_fixup (&block);
2631 /* I need to overwrite motion because it's needed to estimate
2632 * entropy at split 0 */
2633 schro_motion_copy_to (motion, i, j, &block);
2634 min_score = block.score;
2635 /* Note: only do split0 if split1 better than split2 */
2636 schro_do_split0 (me, i, j, &tryblock, fd);
2637 if (tryblock.valid) {
2638 if (min_score > tryblock.score) {
2639 memcpy (&block, &tryblock, sizeof (block));
2640 schro_block_fixup (&block);
2641 }
2642 }
2643 }
2644 }
2645 if (1 < params->num_refs) {
2646 schro_do_split0_biref_zero (me, i, j, &tryblock, fd);
2647 if (tryblock.valid) {
2648 if (min_score > tryblock.score) {
2649 memcpy (&block, &tryblock, sizeof (block));
2650 schro_block_fixup (&block);
2651 }
2652 }
2653 }
2654 schro_motion_copy_to (motion, i, j, &block);
2655 if (block.error > 10 * block_size) {
2656 ++badblocks;
2657 }
2658
2659 for (k = 0; 4 > k; ++k) {
2660 for (l = 0; 4 > l; ++l) {
2661 if (0 == block.mv[k][l].pred_mode) {
2662 ++dcblocks;
2663 }
2664 }
2665 }
2666
2667 total_error += (double) block.error * block.error /
2668 (double) (block_size * block_size);
2669 }
2670 }
2671
2672 schro_me_set_mc_error (me,
2673 total_error / (240.0 * 240.0) /
2674 params->x_num_blocks * params->y_num_blocks / 16);
2675
2676 schro_me_set_badblock_ratio (me,
2677 ((double) badblocks) / (params->x_num_blocks * params->y_num_blocks /
2678 16));
2679
2680 schro_me_set_dcblock_ratio (me,
2681 ((double) dcblocks) / (params->x_num_blocks * params->y_num_blocks));
2682
2683 if (1 < params->mv_precision) {
2684 for (ref = 0; params->num_refs > ref; ++ref) {
2685 schro_free (fd[ref].data);
2686 }
2687 }
2688 }
2689
2690 struct SchroMeElement
2691 {
2692 SchroUpsampledFrame *ref;
2693
2694 SchroMotionField *subpel_mf;
2695 SchroMotionField *split2_mf;
2696 SchroMotionField *split1_mf;
2697 SchroMotionField *split0_mf;
2698
2699 SchroHierBm *hbm;
2700 };
2701
2702
2703 typedef struct SchroMeElement *SchroMeElement;
2704
2705 /* supports motion estimation */
2706 struct _SchroMe
2707 {
2708 SchroFrame *src;
2709
2710 SchroParams *params;
2711 double lambda;
2712 SchroMotion *motion;
2713
2714 double mc_error;
2715 double badblocks_ratio;
2716 double dcblock_ratio;
2717
2718 SchroMeElement meElement[2];
2719 };
2720
2721 static SchroMeElement
schro_me_element_new(SchroEncoderFrame * frame,int ref_number)2722 schro_me_element_new (SchroEncoderFrame * frame, int ref_number)
2723 {
2724 SchroMeElement me;
2725
2726 me = schro_malloc0 (sizeof (struct SchroMeElement));
2727
2728 SCHRO_ASSERT (frame && (0 == ref_number || 1 == ref_number));
2729 SCHRO_ASSERT (me);
2730
2731 me->ref = frame->ref_frame[ref_number]->upsampled_original_frame;
2732 me->hbm = schro_hbm_ref (frame->hier_bm[ref_number]);
2733 return me;
2734 }
2735
2736 static void
schro_me_element_free(SchroMeElement * pme)2737 schro_me_element_free (SchroMeElement * pme)
2738 {
2739 SchroMeElement me = *pme;
2740
2741 if (me) {
2742 if (me->hbm)
2743 schro_hbm_unref (me->hbm);
2744 if (me->subpel_mf)
2745 schro_motion_field_free (me->subpel_mf);
2746 if (me->split2_mf)
2747 schro_motion_field_free (me->split2_mf);
2748 if (me->split1_mf)
2749 schro_motion_field_free (me->split1_mf);
2750 if (me->split0_mf)
2751 schro_motion_field_free (me->split0_mf);
2752 schro_free (me);
2753 *pme = NULL;
2754 }
2755 }
2756
2757
2758 SchroMe *
schro_me_new(SchroEncoderFrame * frame)2759 schro_me_new (SchroEncoderFrame * frame)
2760 {
2761 int ref;
2762 SchroMe *me = schro_malloc0 (sizeof (struct _SchroMe));
2763
2764 SCHRO_ASSERT (me);
2765
2766 me->src = frame->filtered_frame;
2767 me->params = &frame->params;
2768 me->motion = frame->motion;
2769 me->lambda = frame->frame_me_lambda;
2770 for (ref = 0; me->params->num_refs > ref; ++ref) {
2771 me->meElement[ref] = schro_me_element_new (frame, ref);
2772 }
2773 return me;
2774 }
2775
2776 void
schro_me_free(SchroMe * me)2777 schro_me_free (SchroMe * me)
2778 {
2779 int ref;
2780
2781 if (me) {
2782 for (ref = 0; me->params->num_refs > ref; ++ref) {
2783 schro_me_element_free (&me->meElement[ref]);
2784 }
2785 }
2786 schro_free (me);
2787 }
2788
2789 SchroFrame *
schro_me_src(SchroMe * me)2790 schro_me_src (SchroMe * me)
2791 {
2792 SCHRO_ASSERT (me);
2793 return me->src;
2794 }
2795
2796 SchroUpsampledFrame *
schro_me_ref(SchroMe * me,int ref_number)2797 schro_me_ref (SchroMe * me, int ref_number)
2798 {
2799 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2800 return me->meElement[ref_number]->ref;
2801 }
2802
2803 SchroMotionField *
schro_me_subpel_mf(SchroMe * me,int ref_number)2804 schro_me_subpel_mf (SchroMe * me, int ref_number)
2805 {
2806 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2807 return me->meElement[ref_number]->subpel_mf;
2808 }
2809
2810 void
schro_me_set_subpel_mf(SchroMe * me,SchroMotionField * mf,int ref_number)2811 schro_me_set_subpel_mf (SchroMe * me, SchroMotionField * mf, int ref_number)
2812 {
2813 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2814 me->meElement[ref_number]->subpel_mf = mf;
2815 }
2816
2817 SchroMotionField *
schro_me_split2_mf(SchroMe * me,int ref_number)2818 schro_me_split2_mf (SchroMe * me, int ref_number)
2819 {
2820 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2821 return me->meElement[ref_number]->split2_mf;
2822 }
2823
2824 void
schro_me_set_split2_mf(SchroMe * me,SchroMotionField * mf,int ref_number)2825 schro_me_set_split2_mf (SchroMe * me, SchroMotionField * mf, int ref_number)
2826 {
2827 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2828 me->meElement[ref_number]->split2_mf = mf;
2829 }
2830
2831 SchroMotionField *
schro_me_split1_mf(SchroMe * me,int ref_number)2832 schro_me_split1_mf (SchroMe * me, int ref_number)
2833 {
2834 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2835 return me->meElement[ref_number]->split1_mf;
2836 }
2837
2838 void
schro_me_set_split1_mf(SchroMe * me,SchroMotionField * mf,int ref_number)2839 schro_me_set_split1_mf (SchroMe * me, SchroMotionField * mf, int ref_number)
2840 {
2841 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2842 me->meElement[ref_number]->split1_mf = mf;
2843 }
2844
2845 SchroMotionField *
schro_me_split0_mf(SchroMe * me,int ref_number)2846 schro_me_split0_mf (SchroMe * me, int ref_number)
2847 {
2848 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2849 return me->meElement[ref_number]->split0_mf;
2850 }
2851
2852 void
schro_me_set_split0_mf(SchroMe * me,SchroMotionField * mf,int ref_number)2853 schro_me_set_split0_mf (SchroMe * me, SchroMotionField * mf, int ref_number)
2854 {
2855 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2856 me->meElement[ref_number]->split0_mf = mf;
2857 }
2858
2859 SchroHierBm *
schro_me_hbm(SchroMe * me,int ref_number)2860 schro_me_hbm (SchroMe * me, int ref_number)
2861 {
2862 SCHRO_ASSERT (me && (0 == ref_number || 1 == ref_number));
2863 return me->meElement[ref_number]->hbm;
2864 }
2865
2866 void
schro_me_set_lambda(SchroMe * me,double lambda)2867 schro_me_set_lambda (SchroMe * me, double lambda)
2868 {
2869 SCHRO_ASSERT (me);
2870 me->lambda = lambda;
2871 }
2872
2873 double
schro_me_lambda(SchroMe * me)2874 schro_me_lambda (SchroMe * me)
2875 {
2876 SCHRO_ASSERT (me);
2877 return me->lambda;
2878 }
2879
2880 SchroParams *
schro_me_params(SchroMe * me)2881 schro_me_params (SchroMe * me)
2882 {
2883 SCHRO_ASSERT (me);
2884 return me->params;
2885 }
2886
2887 SchroMotion *
schro_me_motion(SchroMe * me)2888 schro_me_motion (SchroMe * me)
2889 {
2890 SCHRO_ASSERT (me);
2891 return me->motion;
2892 }
2893
2894 void
schro_me_set_motion(SchroMe * me,SchroMotion * motion)2895 schro_me_set_motion (SchroMe * me, SchroMotion * motion)
2896 {
2897 SCHRO_ASSERT (me);
2898 me->motion = motion;
2899 }
2900
2901 void
schro_me_set_mc_error(SchroMe * me,double mc_error)2902 schro_me_set_mc_error (SchroMe * me, double mc_error)
2903 {
2904 SCHRO_ASSERT (me);
2905 me->mc_error = mc_error;
2906 }
2907
2908 double
schro_me_mc_error(SchroMe * me)2909 schro_me_mc_error (SchroMe * me)
2910 {
2911 SCHRO_ASSERT (me);
2912 return me->mc_error;
2913 }
2914
2915 void
schro_me_set_badblock_ratio(SchroMe * me,double badblocks_ratio)2916 schro_me_set_badblock_ratio (SchroMe * me, double badblocks_ratio)
2917 {
2918 SCHRO_ASSERT (me);
2919 me->badblocks_ratio = badblocks_ratio;
2920 }
2921
2922 double
schro_me_badblocks_ratio(SchroMe * me)2923 schro_me_badblocks_ratio (SchroMe * me)
2924 {
2925 SCHRO_ASSERT (me);
2926 return me->badblocks_ratio;
2927 }
2928
2929 void
schro_me_set_dcblock_ratio(SchroMe * me,double dcblock_ratio)2930 schro_me_set_dcblock_ratio (SchroMe * me, double dcblock_ratio)
2931 {
2932 SCHRO_ASSERT (me);
2933 me->dcblock_ratio = dcblock_ratio;
2934 }
2935
2936 double
schro_me_dcblock_ratio(SchroMe * me)2937 schro_me_dcblock_ratio (SchroMe * me)
2938 {
2939 SCHRO_ASSERT (me);
2940 return me->dcblock_ratio;
2941 }
2942