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