1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include <schroedinger/schro.h>
6 #include <string.h>
7 #include <schroedinger/schroorc.h>
8 #include <orc/orc.h>
9
10 extern int _schro_motion_ref;
11
12
13
14 SchroMotion *
schro_motion_new(SchroParams * params,SchroUpsampledFrame * ref1,SchroUpsampledFrame * ref2)15 schro_motion_new (SchroParams * params, SchroUpsampledFrame * ref1,
16 SchroUpsampledFrame * ref2)
17 {
18 SchroMotion *motion;
19
20 motion = schro_malloc0 (sizeof (SchroMotion));
21
22 motion->params = params;
23 motion->src1 = ref1;
24 motion->src2 = ref2;
25
26 motion->motion_vectors =
27 schro_malloc0 (sizeof (SchroMotionVector) * params->x_num_blocks *
28 params->y_num_blocks);
29
30 motion->tmpdata = schro_malloc (64 * 64 * 3);
31
32 return motion;
33 }
34
35 void
schro_motion_free(SchroMotion * motion)36 schro_motion_free (SchroMotion * motion)
37 {
38 schro_free (motion->tmpdata);
39 schro_free (motion->motion_vectors);
40 schro_free (motion);
41 }
42
43 static int
get_ramp(int x,int offset)44 get_ramp (int x, int offset)
45 {
46 if (offset == 1) {
47 if (x == 0)
48 return 3;
49 return 5;
50 }
51 return 1 + (6 * x + offset - 1) / (2 * offset - 1);
52 }
53
54
55 void
schro_motion_init_obmc_weight(SchroMotion * motion)56 schro_motion_init_obmc_weight (SchroMotion * motion)
57 {
58 int i;
59 int j;
60 int wx, wy;
61
62 for (i = 0; i < motion->xblen; i++) {
63 if (motion->xoffset == 0) {
64 wx = 8;
65 } else if (i < 2 * motion->xoffset) {
66 wx = get_ramp (i, motion->xoffset);
67 } else if (motion->xblen - 1 - i < 2 * motion->xoffset) {
68 wx = get_ramp (motion->xblen - 1 - i, motion->xoffset);
69 } else {
70 wx = 8;
71 }
72 motion->weight_x[i] = wx;
73 }
74
75 for (j = 0; j < motion->yblen; j++) {
76 if (motion->yoffset == 0) {
77 wy = 8;
78 } else if (j < 2 * motion->yoffset) {
79 wy = get_ramp (j, motion->yoffset);
80 } else if (motion->yblen - 1 - j < 2 * motion->yoffset) {
81 wy = get_ramp (motion->yblen - 1 - j, motion->yoffset);
82 } else {
83 wy = 8;
84 }
85 motion->weight_y[j] = wy;
86 }
87
88 for (j = 0; j < motion->yblen; j++) {
89 int16_t *w = SCHRO_FRAME_DATA_GET_LINE (&motion->obmc_weight, j);
90
91 for (i = 0; i < motion->xblen; i++) {
92 w[i] = motion->weight_x[i] * motion->weight_y[j];
93 }
94 }
95
96 }
97
98 void
schro_motion_render(SchroMotion * motion,SchroFrame * dest,SchroFrame * addframe,int add,SchroFrame * output_frame)99 schro_motion_render (SchroMotion * motion, SchroFrame * dest,
100 SchroFrame * addframe, int add, SchroFrame * output_frame)
101 {
102 SchroParams *params = motion->params;
103
104 #ifdef ENABLE_MOTION_REF
105 if (_schro_motion_ref) {
106 schro_motion_render_ref (motion, dest, addframe, add, output_frame);
107 return;
108 }
109 #endif
110
111 if (0 && schro_motion_render_fast_allowed (motion)) {
112 schro_motion_render_fast (motion, dest, addframe, add, output_frame);
113 return;
114 }
115
116 if (params->have_global_motion) {
117 #ifdef ENABLE_MOTION_REF
118 SCHRO_WARNING ("global motion enabled, using reference motion renderer");
119 schro_motion_render_ref (motion, dest, addframe, add, output_frame);
120 return;
121 #else
122 SCHRO_ERROR ("global motion enabled, probably will crash");
123 #endif
124 }
125
126 {
127 int min_extension;
128 int i;
129
130 min_extension = motion->src1->frames[0]->extension;
131 for (i = 0; i < 4; i++) {
132 if (motion->src1->frames[i]) {
133 min_extension = MIN (min_extension, motion->src1->frames[i]->extension);
134 }
135 if (motion->src2 && motion->src2->frames[i]) {
136 min_extension = MIN (min_extension, motion->src2->frames[i]->extension);
137 }
138 }
139
140 if (MAX (params->xblen_luma, params->yblen_luma) > min_extension) {
141 #ifdef ENABLE_MOTION_REF
142 SCHRO_WARNING
143 ("block size (%dx%d) larger than minimum frame extension %d, using reference motion renderer",
144 params->xblen_luma, params->yblen_luma, min_extension);
145 schro_motion_render_ref (motion, dest, addframe, add, output_frame);
146 return;
147 #else
148 SCHRO_ERROR
149 ("block size (%dx%d) larger than minimum frame extension %d, probably will crash",
150 params->xblen_luma, params->yblen_luma, min_extension);
151 #endif
152 }
153 }
154
155 schro_motion_render_u8 (motion, dest, addframe, add, output_frame);
156 }
157
158
159
160 /* original */
161
162
163 void
schro_motion_dc_prediction(SchroMotion * motion,int x,int y,int * pred)164 schro_motion_dc_prediction (SchroMotion * motion, int x, int y, int *pred)
165 {
166 SchroMotionVector *mv;
167 int i;
168
169 for (i = 0; i < 3; i++) {
170 int sum = 0;
171 int n = 0;
172
173 if (x > 0) {
174 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y);
175 if (mv->pred_mode == 0) {
176 sum += mv->u.dc.dc[i];
177 n++;
178 }
179 }
180 if (y > 0) {
181 mv = SCHRO_MOTION_GET_BLOCK (motion, x, y - 1);
182 if (mv->pred_mode == 0) {
183 sum += mv->u.dc.dc[i];
184 n++;
185 }
186 }
187 if (x > 0 && y > 0) {
188 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y - 1);
189 if (mv->pred_mode == 0) {
190 sum += mv->u.dc.dc[i];
191 n++;
192 }
193 }
194 switch (n) {
195 case 0:
196 pred[i] = 0;
197 break;
198 case 1:
199 pred[i] = (short) sum;
200 break;
201 case 2:
202 pred[i] = (sum + 1) >> 1;
203 break;
204 case 3:
205 pred[i] = schro_divide3 (sum + 1);
206 break;
207 default:
208 SCHRO_ASSERT (0);
209 }
210 }
211 }
212
213 int
schro_motion_get_global_prediction(SchroMotion * motion,int x,int y)214 schro_motion_get_global_prediction (SchroMotion * motion, int x, int y)
215 {
216 SchroMotionVector *mv;
217 int sum;
218
219 if (x == 0 && y == 0) {
220 return 0;
221 }
222 if (y == 0) {
223 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, 0);
224 return mv->using_global;
225 }
226 if (x == 0) {
227 mv = SCHRO_MOTION_GET_BLOCK (motion, 0, y - 1);
228 return mv->using_global;
229 }
230
231 sum = 0;
232 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y);
233 sum += mv->using_global;
234 mv = SCHRO_MOTION_GET_BLOCK (motion, x, y - 1);
235 sum += mv->using_global;
236 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y - 1);
237 sum += mv->using_global;
238
239 return (sum >= 2);
240 }
241
242 static int
median3(int a,int b,int c)243 median3 (int a, int b, int c)
244 {
245 if (a < b) {
246 if (b < c)
247 return b;
248 if (c < a)
249 return a;
250 return c;
251 } else {
252 if (a < c)
253 return a;
254 if (c < b)
255 return b;
256 return c;
257 }
258 }
259
260 void
schro_mf_vector_prediction(SchroMotionField * mf,int x,int y,int * pred_x,int * pred_y,int mode)261 schro_mf_vector_prediction (SchroMotionField * mf,
262 int x, int y, int *pred_x, int *pred_y, int mode)
263 {
264 int x_num_blocks;
265 SchroMotionVector *mv;
266 int vx[3], vy[3];
267 int n = 0;
268 int ref = mode - 1;
269
270 SCHRO_ASSERT (mf && pred_x && pred_y);
271 SCHRO_ASSERT (1 == mode || 2 == mode);
272
273 x_num_blocks = mf->x_num_blocks;
274
275 if (0 < x) {
276 mv = &mf->motion_vectors[y * x_num_blocks + x - 1];
277 vx[n] = mv->u.vec.dx[ref];
278 vy[n] = mv->u.vec.dy[ref];
279 ++n;
280 }
281 if (0 < y) {
282 mv = &mf->motion_vectors[(y - 1) * x_num_blocks + x];
283 vx[n] = mv->u.vec.dx[ref];
284 vy[n] = mv->u.vec.dy[ref];
285 ++n;
286 }
287 if (0 < x && 0 < y) {
288 mv = &mf->motion_vectors[(y - 1) * x_num_blocks + x - 1];
289 vx[n] = mv->u.vec.dx[ref];
290 vy[n] = mv->u.vec.dy[ref];
291 ++n;
292 }
293 switch (n) {
294 case 0:
295 *pred_x = 0;
296 *pred_y = 0;
297 break;
298 case 1:
299 *pred_x = vx[0];
300 *pred_y = vy[0];
301 break;
302 case 2:
303 *pred_x = (vx[0] + vx[1] + 1) >> 1;
304 *pred_y = (vy[0] + vy[1] + 1) >> 1;
305 break;
306 case 3:
307 *pred_x = median3 (vx[0], vx[1], vx[2]);
308 *pred_y = median3 (vy[0], vy[1], vy[2]);
309 break;
310 default:
311 SCHRO_ASSERT (0);
312 }
313 }
314
315 void
schro_motion_vector_prediction(SchroMotion * motion,int x,int y,int * pred_x,int * pred_y,int mode)316 schro_motion_vector_prediction (SchroMotion * motion,
317 int x, int y, int *pred_x, int *pred_y, int mode)
318 {
319 SchroMotionVector *mv;
320 int vx[3];
321 int vy[3];
322 int n = 0;
323
324 SCHRO_ASSERT (mode == 1 || mode == 2);
325 if (x > 0) {
326 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y);
327 if (mv->using_global == FALSE && (mv->pred_mode & mode)) {
328 vx[n] = mv->u.vec.dx[mode - 1];
329 vy[n] = mv->u.vec.dy[mode - 1];
330 n++;
331 }
332 }
333 if (y > 0) {
334 mv = SCHRO_MOTION_GET_BLOCK (motion, x, y - 1);
335 if (mv->using_global == FALSE && (mv->pred_mode & mode)) {
336 vx[n] = mv->u.vec.dx[mode - 1];
337 vy[n] = mv->u.vec.dy[mode - 1];
338 n++;
339 }
340 }
341 if (x > 0 && y > 0) {
342 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y - 1);
343 if (mv->using_global == FALSE && (mv->pred_mode & mode)) {
344 vx[n] = mv->u.vec.dx[mode - 1];
345 vy[n] = mv->u.vec.dy[mode - 1];
346 n++;
347 }
348 }
349 switch (n) {
350 case 0:
351 *pred_x = 0;
352 *pred_y = 0;
353 break;
354 case 1:
355 *pred_x = vx[0];
356 *pred_y = vy[0];
357 break;
358 case 2:
359 *pred_x = (vx[0] + vx[1] + 1) >> 1;
360 *pred_y = (vy[0] + vy[1] + 1) >> 1;
361 break;
362 case 3:
363 *pred_x = median3 (vx[0], vx[1], vx[2]);
364 *pred_y = median3 (vy[0], vy[1], vy[2]);
365 break;
366 default:
367 SCHRO_ASSERT (0);
368 }
369 }
370
371 int
schro_motion_split_prediction(SchroMotion * motion,int x,int y)372 schro_motion_split_prediction (SchroMotion * motion, int x, int y)
373 {
374 SchroMotionVector *mv;
375
376 if (y == 0) {
377 if (x == 0) {
378 return 0;
379 } else {
380 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 4, 0);
381 return mv->split;
382 }
383 } else {
384 if (x == 0) {
385 mv = SCHRO_MOTION_GET_BLOCK (motion, x, y - 4);
386 return mv->split;
387 } else {
388 int sum;
389
390 mv = SCHRO_MOTION_GET_BLOCK (motion, x, y - 4);
391 sum = mv->split;
392 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 4, y);
393 sum += mv->split;
394 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 4, y - 4);
395 sum += mv->split;
396
397 return (sum + 1) / 3;
398 }
399 }
400 }
401
402 int
schro_motion_get_mode_prediction(SchroMotion * motion,int x,int y)403 schro_motion_get_mode_prediction (SchroMotion * motion, int x, int y)
404 {
405 SchroMotionVector *mv;
406
407 if (y == 0) {
408 if (x == 0) {
409 return 0;
410 } else {
411 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, 0);
412 return mv->pred_mode;
413 }
414 } else {
415 if (x == 0) {
416 mv = SCHRO_MOTION_GET_BLOCK (motion, 0, y - 1);
417 return mv->pred_mode;
418 } else {
419 int a, b, c;
420
421 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y);
422 a = mv->pred_mode;
423 mv = SCHRO_MOTION_GET_BLOCK (motion, x, y - 1);
424 b = mv->pred_mode;
425 mv = SCHRO_MOTION_GET_BLOCK (motion, x - 1, y - 1);
426 c = mv->pred_mode;
427
428 return (a & b) | (b & c) | (c & a);
429 }
430 }
431 }
432
433 int
schro_motion_vector_is_equal(SchroMotionVector * a,SchroMotionVector * b)434 schro_motion_vector_is_equal (SchroMotionVector * a, SchroMotionVector * b)
435 {
436 if (a == b)
437 return 1;
438 return (memcmp (a, b, sizeof (SchroMotionVector)) == 0);
439 }
440
441 int
schro_motion_verify(SchroMotion * motion)442 schro_motion_verify (SchroMotion * motion)
443 {
444 int x, y;
445 SchroMotionVector *mv, *sbmv, *bmv;
446 SchroParams *params = motion->params;
447
448 if (motion->src1 == NULL) {
449 SCHRO_ERROR ("motion->src1 is NULL");
450 return 0;
451 }
452
453 for (y = 0; y < params->y_num_blocks; y++) {
454 for (x = 0; x < params->x_num_blocks; x++) {
455 mv = &motion->motion_vectors[y * params->x_num_blocks + x];
456 sbmv =
457 &motion->motion_vectors[(y & ~3) * params->x_num_blocks + (x & ~3)];
458
459 if (mv->split != sbmv->split) {
460 SCHRO_ERROR ("mv(%d,%d) has the wrong split", x, y);
461 return 0;
462 }
463
464 switch (sbmv->split) {
465 case 0:
466 if (!schro_motion_vector_is_equal (mv, sbmv)) {
467 SCHRO_ERROR ("mv(%d,%d) not equal to superblock mv", x, y);
468 return 0;
469 }
470 break;
471 case 1:
472 bmv =
473 &motion->motion_vectors[(y & ~1) * params->x_num_blocks +
474 (x & ~1)];
475 if (!schro_motion_vector_is_equal (mv, bmv)) {
476 SCHRO_ERROR ("mv(%d,%d) not equal to 2-block mv", x, y);
477 return 0;
478 }
479 break;
480 case 2:
481 break;
482 default:
483 SCHRO_ERROR ("mv(%d,%d) had bad split %d", sbmv->split);
484 break;
485 }
486
487 switch (mv->pred_mode) {
488 case 0:
489 {
490 int i;
491
492 for (i = 0; i < 3; i++) {
493 /* FIXME 8bit */
494 if (mv->u.dc.dc[i] < -128 || mv->u.dc.dc[i] > 127) {
495 SCHRO_ERROR ("mv(%d,%d) has bad DC value [%d] %d", x, y,
496 i, mv->u.dc.dc[i]);
497 return 0;
498 }
499 }
500 }
501 break;
502 case 1:
503 break;
504 case 2:
505 case 3:
506 if (motion->params->num_refs < 2) {
507 SCHRO_ERROR ("mv(%d,%d) uses non-existent src2", x, y);
508 return 0;
509 }
510 break;
511 default:
512 SCHRO_ASSERT (0);
513 break;
514 }
515
516 if (params->have_global_motion == FALSE) {
517 if (mv->using_global) {
518 SCHRO_ERROR ("mv(%d,%d) uses global motion (disabled)", x, y);
519 return 0;
520 }
521 }
522 }
523 }
524
525 return 1;
526 }
527