1 /*****************************************************************************
2 * vdec_motion.c : motion compensation routines
4 *****************************************************************************/
6 /*****************************************************************************
8 *****************************************************************************/
19 #include "vlc_thread.h"
22 #include "debug.h" /* XXX?? temporaire, requis par netlist.h */
25 #include "input_netlist.h"
26 #include "decoder_fifo.h"
28 #include "video_output.h"
30 #include "vdec_idct.h"
31 #include "video_decoder.h"
32 #include "vdec_motion.h"
34 #include "vpar_blocks.h"
35 #include "vpar_headers.h"
36 #include "vpar_synchro.h"
37 #include "video_parser.h"
38 #include "video_fifo.h"
40 #define __MotionComponents(width,height) \
41 void MotionComponent_x_y_copy_##width##_##height (); \
42 void MotionComponent_X_y_copy_##width##_##height (); \
43 void MotionComponent_x_Y_copy_##width##_##height (); \
44 void MotionComponent_X_Y_copy_##width##_##height (); \
45 void MotionComponent_x_y_avg_##width##_##height (); \
46 void MotionComponent_X_y_avg_##width##_##height (); \
47 void MotionComponent_x_Y_avg_##width##_##height (); \
48 void MotionComponent_X_Y_avg_##width##_##height ();
50 __MotionComponents (16,16) /* 444, 422, 420 */
51 __MotionComponents (16,8) /* 444, 422, 420 */
52 __MotionComponents (8,8) /* 422, 420 */
53 __MotionComponents (8,4) /* 420 */
55 __MotionComponents (8,16) /* 422 */
58 #define ___callTheRightOne(width,height) \
59 if ((i_width == width) && (i_height == height)) \
66 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
70 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
74 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
79 MotionComponent_X_Y_copy_##width##_##height (p_src, p_dest, \
90 MotionComponent_x_y_avg_##width##_##height (p_src, p_dest, \
94 MotionComponent_X_y_avg_##width##_##height (p_src, p_dest, \
98 MotionComponent_x_Y_avg_##width##_##height (p_src, p_dest, \
103 MotionComponent_X_Y_avg_##width##_##height (p_src, p_dest, \
110 /*****************************************************************************
111 * vdec_MotionComponent : last stage of motion compensation
112 *****************************************************************************/
113 static __inline__ void MotionComponent(
114 yuv_data_t * p_src, /* source block */
115 yuv_data_t * p_dest, /* dest block */
116 int i_width, /* (explicit) width of block */
117 int i_height, /* (explicit) height of block */
118 int i_stride, /* number of coeffs to jump
119 * between each predicted line */
120 int i_step, /* number of coeffs to jump to
121 * go to the next line of the
123 int i_select, /* half-pel vectors */
124 boolean_t b_average /* (explicit) averaging of several
127 ___callTheRightOne (16,16)
128 ___callTheRightOne (16,8)
129 ___callTheRightOne (8,8)
130 ___callTheRightOne (8,4)
132 ___callTheRightOne (8,16)
136 /*****************************************************************************
137 * Motion420 : motion compensation for a 4:2:0 macroblock
138 *****************************************************************************/
139 static __inline__ void Motion420(
140 macroblock_t * p_mb, /* destination macroblock */
141 picture_t * p_source, /* source picture */
142 boolean_t b_source_field, /* source field */
143 boolean_t b_dest_field, /* destination field */
144 int i_mv_x, int i_mv_y, /* motion vector coordinates,
146 int i_l_stride, /* number of coeffs to jump to
147 * go to the next predicted
150 int i_height, /* height of the block to
151 * predict, in luminance
153 int i_offset, /* position of the first
154 * predicted line (explicit) */
155 boolean_t b_average /* (explicit) averaging of
156 * several predictions */ )
158 /* Temporary variables to avoid recalculating things twice */
159 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
161 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
162 + (p_mb->i_motion_l_y + i_offset
165 * p_mb->p_picture->i_width;
166 if( i_source_offset >= p_source->i_width * p_source->i_height )
168 fprintf( stderr, "vdec error: bad motion vector\n" );
173 MotionComponent( /* source */
174 p_source->p_y + i_source_offset,
178 + (p_mb->i_motion_l_y + b_dest_field)
179 * p_mb->p_picture->i_width,
180 /* prediction width and height */
183 i_l_stride, p_mb->i_l_stride,
185 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
188 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
189 + ((p_mb->i_motion_c_y + (i_offset >> 1)
192 * p_mb->p_picture->i_chroma_width;
193 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
195 fprintf( stderr, "vdec error: bad motion vector\n" );
199 i_dest_offset = (p_mb->i_c_x)
200 + (p_mb->i_motion_c_y + b_dest_field)
201 * p_mb->p_picture->i_chroma_width;
202 i_c_height = i_height >> 1;
203 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
206 MotionComponent( p_source->p_u
210 8, i_c_height, i_c_stride, p_mb->i_c_stride,
211 i_c_select, b_average );
214 MotionComponent( p_source->p_v
218 8, i_c_height, i_c_stride, p_mb->i_c_stride,
219 i_c_select, b_average );
222 /*****************************************************************************
223 * Motion422 : motion compensation for a 4:2:2 macroblock
224 *****************************************************************************/
225 static __inline__ void Motion422(
226 macroblock_t * p_mb, /* destination macroblock */
227 picture_t * p_source, /* source picture */
228 boolean_t b_source_field, /* source field */
229 boolean_t b_dest_field, /* destination field */
230 int i_mv_x, int i_mv_y, /* motion vector coordinates,
232 int i_l_stride, /* number of coeffs to jump to
233 * go to the next predicted
236 int i_height, /* height of the block to
237 * predict, in luminance
239 int i_offset, /* position of the first
240 * predicted line (explicit) */
241 boolean_t b_average /* (explicit) averaging of
242 * several predictions */ )
245 int i_source_offset, i_dest_offset, i_c_select;
248 MotionComponent( /* source */
250 + (p_mb->i_l_x + (i_mv_x >> 1))
251 + (p_mb->i_motion_l_y + i_offset
254 * p_mb->p_picture->i_width,
258 + (p_mb->i_motion_l_y + b_dest_field)
259 * p_mb->p_picture->i_width,
260 /* prediction width and height */
263 i_l_stride, p_mb->i_l_stride,
265 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
268 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
269 + ((p_mb->i_motion_c_y + (i_offset)
272 * p_mb->p_picture->i_chroma_width;
273 i_dest_offset = (p_mb->i_c_x)
274 + (p_mb->i_motion_c_y + b_dest_field)
275 * p_mb->p_picture->i_chroma_width;
276 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
279 MotionComponent( p_source->p_u
283 8, i_height, i_c_stride, p_mb->i_c_stride,
284 i_c_select, b_average );
287 MotionComponent( p_source->p_v
291 8, i_height, i_c_stride, p_mb->i_c_stride,
292 i_c_select, b_average );
296 /*****************************************************************************
297 * Motion444 : motion compensation for a 4:4:4 macroblock
298 *****************************************************************************/
299 static __inline__ void Motion444(
300 macroblock_t * p_mb, /* destination macroblock */
301 picture_t * p_source, /* source picture */
302 boolean_t b_source_field, /* source field */
303 boolean_t b_dest_field, /* destination field */
304 int i_mv_x, int i_mv_y, /* motion vector coordinates,
306 int i_l_stride, /* number of coeffs to jump to
307 * go to the next predicted
310 int i_height, /* height of the block to
311 * predict, in luminance
313 int i_offset, /* position of the first
314 * predicted line (explicit) */
315 boolean_t b_average /* (explicit) averaging of
316 * several predictions */ )
319 int i_source_offset, i_dest_offset, i_select;
321 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
322 + (p_mb->i_motion_l_y + i_offset
325 * p_mb->p_picture->i_width;
326 i_dest_offset = (p_mb->i_l_x)
327 + (p_mb->i_motion_l_y + b_dest_field)
328 * p_mb->p_picture->i_width;
329 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
333 MotionComponent( p_source->p_y
337 16, i_height, i_l_stride, p_mb->i_l_stride,
338 i_select, b_average );
341 MotionComponent( p_source->p_u
345 16, i_height, i_l_stride, p_mb->i_l_stride,
346 i_select, b_average );
349 MotionComponent( p_source->p_v
353 16, i_height, i_l_stride, p_mb->i_l_stride,
354 i_select, b_average );
358 /*****************************************************************************
359 * vdec_MotionFieldField : motion compensation for field motion type (field)
360 *****************************************************************************/
361 #define FIELDFIELD( MOTION ) \
362 picture_t * p_pred; \
364 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
366 if( p_mb->b_P_second \
367 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
368 p_pred = p_mb->p_picture; \
370 p_pred = p_mb->p_forward; \
372 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
373 p_mb->b_motion_field, \
374 p_mb->pppi_motion_vectors[0][0][0], \
375 p_mb->pppi_motion_vectors[0][0][1], \
376 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
378 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
380 MOTION( p_mb, p_mb->p_backward, \
381 p_mb->ppi_field_select[0][1], \
382 p_mb->b_motion_field, \
383 p_mb->pppi_motion_vectors[0][1][0], \
384 p_mb->pppi_motion_vectors[0][1][1], \
385 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
388 else /* MB_MOTION_BACKWARD */ \
390 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
391 p_mb->b_motion_field, \
392 p_mb->pppi_motion_vectors[0][1][0], \
393 p_mb->pppi_motion_vectors[0][1][1], \
394 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
398 void vdec_MotionFieldField420( macroblock_t * p_mb )
400 FIELDFIELD( Motion420 )
403 void vdec_MotionFieldField422( macroblock_t * p_mb )
405 //FIELDFIELD( Motion422 )
408 void vdec_MotionFieldField444( macroblock_t * p_mb )
410 //FIELDFIELD( Motion444 )
413 /*****************************************************************************
414 * vdec_MotionField16x8XXX?? : motion compensation for 16x8 motion type (field)
415 *****************************************************************************/
416 #define FIELD16X8( MOTION ) \
418 picture_t * p_pred; \
420 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
422 if( p_mb->b_P_second \
423 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
424 p_pred = p_mb->p_picture; \
426 p_pred = p_mb->p_forward; \
428 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
429 p_mb->b_motion_field, \
430 p_mb->pppi_motion_vectors[0][0][0], \
431 p_mb->pppi_motion_vectors[0][0][1], \
432 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
434 if( p_mb->b_P_second \
435 && (p_mb->b_motion_field != p_mb->ppi_field_select[1][0]) )\
436 p_pred = p_mb->p_picture; \
438 p_pred = p_mb->p_forward; \
440 MOTION( p_mb, p_pred, p_mb->ppi_field_select[1][0], \
441 p_mb->b_motion_field, \
442 p_mb->pppi_motion_vectors[1][0][0], \
443 p_mb->pppi_motion_vectors[1][0][1], \
444 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
446 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
448 MOTION( p_mb, p_mb->p_backward, \
449 p_mb->ppi_field_select[0][1], \
450 p_mb->b_motion_field, \
451 p_mb->pppi_motion_vectors[0][1][0], \
452 p_mb->pppi_motion_vectors[0][1][1], \
453 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 1 ); \
455 MOTION( p_mb, p_mb->p_backward, \
456 p_mb->ppi_field_select[1][1], \
457 p_mb->b_motion_field, \
458 p_mb->pppi_motion_vectors[1][1][0], \
459 p_mb->pppi_motion_vectors[1][1][1], \
460 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 1 ); \
464 else /* MB_MOTION_BACKWARD */ \
466 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
467 p_mb->b_motion_field, \
468 p_mb->pppi_motion_vectors[0][1][0], \
469 p_mb->pppi_motion_vectors[0][1][1], \
470 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
472 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], \
473 p_mb->b_motion_field, \
474 p_mb->pppi_motion_vectors[1][1][0], \
475 p_mb->pppi_motion_vectors[1][1][1], \
476 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
480 void vdec_MotionField16x8420( macroblock_t * p_mb )
482 FIELD16X8( Motion420 )
485 void vdec_MotionField16x8422( macroblock_t * p_mb )
487 //FIELD16X8( Motion422 )
490 void vdec_MotionField16x8444( macroblock_t * p_mb )
492 //FIELD16X8( Motion444 )
495 /*****************************************************************************
496 * vdec_MotionFieldDMVXXX?? : motion compensation for dmv motion type (field)
497 *****************************************************************************/
498 #define FIELDDMV( MOTION ) \
500 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
502 picture_t * p_pred; \
504 /* predict from field of same parity */ \
505 MOTION( p_mb, p_mb->p_forward, \
506 p_mb->b_motion_field, p_mb->b_motion_field, \
507 p_mb->pppi_motion_vectors[0][0][0], \
508 p_mb->pppi_motion_vectors[0][0][1], \
509 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
511 if( p_mb->b_P_second ) \
512 p_pred = p_mb->p_picture; \
514 p_pred = p_mb->p_forward; \
516 /* predict from field of opposite parity */ \
517 MOTION( p_mb, p_pred, !p_mb->b_motion_field, p_mb->b_motion_field, \
518 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
519 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
522 void vdec_MotionFieldDMV420( macroblock_t * p_mb )
524 FIELDDMV( Motion420 )
527 void vdec_MotionFieldDMV422( macroblock_t * p_mb )
529 //FIELDDMV( Motion422 )
532 void vdec_MotionFieldDMV444( macroblock_t * p_mb )
534 //FIELDDMV( Motion444 )
537 /*****************************************************************************
538 * vdec_MotionFrameFrameXXX?? : motion compensation for frame motion type (frame)
539 *****************************************************************************/
540 #define FRAMEFRAME( MOTION ) \
542 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
544 MOTION( p_mb, p_mb->p_forward, 0, 0, \
545 p_mb->pppi_motion_vectors[0][0][0], \
546 p_mb->pppi_motion_vectors[0][0][1], \
547 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
549 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
551 MOTION( p_mb, p_mb->p_backward, 0, 0, \
552 p_mb->pppi_motion_vectors[0][1][0], \
553 p_mb->pppi_motion_vectors[0][1][1], \
554 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
558 else /* MB_MOTION_BACKWARD */ \
560 MOTION( p_mb, p_mb->p_backward, 0, 0, \
561 p_mb->pppi_motion_vectors[0][1][0], \
562 p_mb->pppi_motion_vectors[0][1][1], \
563 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
567 void vdec_MotionFrameFrame420( macroblock_t * p_mb )
569 FRAMEFRAME( Motion420 )
572 void vdec_MotionFrameFrame422( macroblock_t * p_mb )
574 //FRAMEFRAME( Motion422 )
577 void vdec_MotionFrameFrame444( macroblock_t * p_mb )
579 //FRAMEFRAME( Motion444 )
582 /*****************************************************************************
583 * vdec_MotionFrameFieldXXX?? : motion compensation for field motion type (frame)
584 *****************************************************************************/
585 #define FRAMEFIELD( MOTION ) \
587 int i_l_stride = p_mb->i_l_stride << 1; \
588 int i_c_stride = p_mb->i_c_stride << 1; \
590 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
592 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[0][0], 0, \
593 p_mb->pppi_motion_vectors[0][0][0], \
594 p_mb->pppi_motion_vectors[0][0][1], \
595 i_l_stride, i_c_stride, 8, 0, 0 ); \
597 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[1][0], 1, \
598 p_mb->pppi_motion_vectors[1][0][0], \
599 p_mb->pppi_motion_vectors[1][0][1], \
600 i_l_stride, i_c_stride, 8, 0, 0 ); \
602 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
604 MOTION( p_mb, p_mb->p_backward, \
605 p_mb->ppi_field_select[0][1], 0, \
606 p_mb->pppi_motion_vectors[0][1][0], \
607 p_mb->pppi_motion_vectors[0][1][1], \
608 i_l_stride, i_c_stride, 8, 0, 1 ); \
610 MOTION( p_mb, p_mb->p_backward, \
611 p_mb->ppi_field_select[1][1], 1, \
612 p_mb->pppi_motion_vectors[1][1][0], \
613 p_mb->pppi_motion_vectors[1][1][1], \
614 i_l_stride, i_c_stride, 8, 0, 1 ); \
618 else /* MB_MOTION_BACKWARD only */ \
620 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], 0,\
621 p_mb->pppi_motion_vectors[0][1][0], \
622 p_mb->pppi_motion_vectors[0][1][1], \
623 i_l_stride, i_c_stride, 8, 0, 0 ); \
625 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], 1,\
626 p_mb->pppi_motion_vectors[1][1][0], \
627 p_mb->pppi_motion_vectors[1][1][1], \
628 i_l_stride, i_c_stride, 8, 0, 0 ); \
632 void vdec_MotionFrameField420( macroblock_t * p_mb )
634 FRAMEFIELD( Motion420 )
637 void vdec_MotionFrameField422( macroblock_t * p_mb )
639 //FRAMEFIELD( Motion422 )
642 void vdec_MotionFrameField444( macroblock_t * p_mb )
644 //FRAMEFIELD( Motion444 )
647 /*****************************************************************************
648 * vdec_MotionFrameDMVXXX?? : motion compensation for dmv motion type (frame)
649 *****************************************************************************/
650 #define FRAMEDMV( MOTION ) \
652 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
655 /* predict top field from top field */ \
656 MOTION( p_mb, p_mb->p_forward, 0, 0, \
657 p_mb->pppi_motion_vectors[0][0][0], \
658 p_mb->pppi_motion_vectors[0][0][1], \
659 /* XXX?? XXX?? >> 1 ? */ \
660 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
662 /* predict and add to top field from bottom field */ \
663 MOTION( p_mb, p_mb->p_forward, 1, 0, \
664 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
665 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
667 /* predict bottom field from bottom field */ \
668 MOTION( p_mb, p_mb->p_forward, 1, 1, \
669 p_mb->pppi_motion_vectors[0][0][0], \
670 p_mb->pppi_motion_vectors[0][0][1], \
671 /* XXX?? XXX?? >> 1 ? */ \
672 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
674 /* predict and add to bottom field from top field */ \
675 MOTION( p_mb, p_mb->p_forward, 1, 0, \
676 p_mb->ppi_dmv[1][0], p_mb->ppi_dmv[1][1], \
677 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
680 void vdec_MotionFrameDMV420( macroblock_t * p_mb )
682 FRAMEDMV( Motion420 )
685 void vdec_MotionFrameDMV422( macroblock_t * p_mb )
687 //FRAMEDMV( Motion422 )
690 void vdec_MotionFrameDMV444( macroblock_t * p_mb )
692 //FRAMEDMV( Motion444 )