1 /*****************************************************************************
2 * vdec_motion.c : motion compensation routines
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
28 #include <sys/types.h> /* on BSD, uio.h needs types.h */
29 #include <sys/uio.h> /* for input.h */
40 #include "decoder_fifo.h"
42 #include "video_output.h"
44 #include "vdec_idct.h"
45 #include "video_decoder.h"
46 #include "vdec_motion.h"
48 #include "vpar_blocks.h"
49 #include "vpar_headers.h"
50 #include "vpar_synchro.h"
51 #include "video_parser.h"
52 #include "video_fifo.h"
54 #define __MotionComponents(width,height) \
55 void MotionComponent_x_y_copy_##width##_##height (); \
56 void MotionComponent_X_y_copy_##width##_##height (); \
57 void MotionComponent_x_Y_copy_##width##_##height (); \
58 void MotionComponent_X_Y_copy_##width##_##height (); \
59 void MotionComponent_x_y_avg_##width##_##height (); \
60 void MotionComponent_X_y_avg_##width##_##height (); \
61 void MotionComponent_x_Y_avg_##width##_##height (); \
62 void MotionComponent_X_Y_avg_##width##_##height ();
64 __MotionComponents (16,16) /* 444, 422, 420 */
65 __MotionComponents (16,8) /* 444, 422, 420 */
66 __MotionComponents (8,8) /* 422, 420 */
67 __MotionComponents (8,4) /* 420 */
69 __MotionComponents (8,16) /* 422 */
72 #define ___callTheRightOne(width,height) \
73 if ((i_width == width) && (i_height == height)) \
80 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
84 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
88 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
93 MotionComponent_X_Y_copy_##width##_##height (p_src, p_dest, \
104 MotionComponent_x_y_avg_##width##_##height (p_src, p_dest, \
108 MotionComponent_X_y_avg_##width##_##height (p_src, p_dest, \
112 MotionComponent_x_Y_avg_##width##_##height (p_src, p_dest, \
117 MotionComponent_X_Y_avg_##width##_##height (p_src, p_dest, \
125 /*****************************************************************************
126 * vdec_MotionComponent : last stage of motion compensation
127 *****************************************************************************/
128 static __inline__ void MotionComponent(
129 yuv_data_t * p_src, /* source block */
130 yuv_data_t * p_dest, /* dest block */
131 int i_width, /* (explicit) width of block */
132 int i_height, /* (explicit) height of block */
133 int i_stride, /* number of coeffs to jump
134 * between each predicted line */
135 int i_step, /* number of coeffs to jump to
136 * go to the next line of the
138 int i_select, /* half-pel vectors */
139 boolean_t b_average /* (explicit) averaging of several
142 ___callTheRightOne (16,16)
143 ___callTheRightOne (16,8)
144 ___callTheRightOne (8,8)
145 ___callTheRightOne (8,4)
147 ___callTheRightOne (8,16)
151 /*****************************************************************************
152 * Motion420 : motion compensation for a 4:2:0 macroblock
153 *****************************************************************************/
154 static __inline__ void Motion420(
155 macroblock_t * p_mb, /* destination macroblock */
156 picture_t * p_source, /* source picture */
157 boolean_t b_source_field, /* source field */
158 boolean_t b_dest_field, /* destination field */
159 int i_mv_x, int i_mv_y, /* motion vector coordinates,
161 int i_l_stride, /* number of coeffs to jump to
162 * go to the next predicted
165 int i_height, /* height of the block to
166 * predict, in luminance
168 int i_offset, /* position of the first
169 * predicted line (explicit) */
170 boolean_t b_average /* (explicit) averaging of
171 * several predictions */ )
173 /* Temporary variables to avoid recalculating things twice */
174 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
176 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
177 + (p_mb->i_motion_l_y + i_offset
180 * p_mb->p_picture->i_width;
181 if( i_source_offset >= p_source->i_width * p_source->i_height )
183 intf_ErrMsg( "vdec error: bad motion vector\n" );
188 MotionComponent( /* source */
189 p_source->p_y + i_source_offset,
193 + (p_mb->i_motion_l_y + b_dest_field)
194 * p_mb->p_picture->i_width,
195 /* prediction width and height */
198 i_l_stride, p_mb->i_l_stride,
200 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
203 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
204 + ((p_mb->i_motion_c_y + (i_offset >> 1)
207 * p_mb->p_picture->i_chroma_width;
208 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
210 intf_ErrMsg( "vdec error: bad motion vector\n" );
214 i_dest_offset = (p_mb->i_c_x)
215 + (p_mb->i_motion_c_y + b_dest_field)
216 * p_mb->p_picture->i_chroma_width;
217 i_c_height = i_height >> 1;
218 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
221 MotionComponent( p_source->p_u
225 8, i_c_height, i_c_stride, p_mb->i_c_stride,
226 i_c_select, b_average );
229 MotionComponent( p_source->p_v
233 8, i_c_height, i_c_stride, p_mb->i_c_stride,
234 i_c_select, b_average );
237 /*****************************************************************************
238 * Motion422 : motion compensation for a 4:2:2 macroblock
239 *****************************************************************************/
240 static __inline__ void Motion422(
241 macroblock_t * p_mb, /* destination macroblock */
242 picture_t * p_source, /* source picture */
243 boolean_t b_source_field, /* source field */
244 boolean_t b_dest_field, /* destination field */
245 int i_mv_x, int i_mv_y, /* motion vector coordinates,
247 int i_l_stride, /* number of coeffs to jump to
248 * go to the next predicted
251 int i_height, /* height of the block to
252 * predict, in luminance
254 int i_offset, /* position of the first
255 * predicted line (explicit) */
256 boolean_t b_average /* (explicit) averaging of
257 * several predictions */ )
260 int i_source_offset, i_dest_offset, i_c_select;
263 MotionComponent( /* source */
265 + (p_mb->i_l_x + (i_mv_x >> 1))
266 + (p_mb->i_motion_l_y + i_offset
269 * p_mb->p_picture->i_width,
273 + (p_mb->i_motion_l_y + b_dest_field)
274 * p_mb->p_picture->i_width,
275 /* prediction width and height */
278 i_l_stride, p_mb->i_l_stride,
280 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
283 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
284 + ((p_mb->i_motion_c_y + (i_offset)
287 * p_mb->p_picture->i_chroma_width;
288 i_dest_offset = (p_mb->i_c_x)
289 + (p_mb->i_motion_c_y + b_dest_field)
290 * p_mb->p_picture->i_chroma_width;
291 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
294 MotionComponent( p_source->p_u
298 8, i_height, i_c_stride, p_mb->i_c_stride,
299 i_c_select, b_average );
302 MotionComponent( p_source->p_v
306 8, i_height, i_c_stride, p_mb->i_c_stride,
307 i_c_select, b_average );
311 /*****************************************************************************
312 * Motion444 : motion compensation for a 4:4:4 macroblock
313 *****************************************************************************/
314 static __inline__ void Motion444(
315 macroblock_t * p_mb, /* destination macroblock */
316 picture_t * p_source, /* source picture */
317 boolean_t b_source_field, /* source field */
318 boolean_t b_dest_field, /* destination field */
319 int i_mv_x, int i_mv_y, /* motion vector coordinates,
321 int i_l_stride, /* number of coeffs to jump to
322 * go to the next predicted
325 int i_height, /* height of the block to
326 * predict, in luminance
328 int i_offset, /* position of the first
329 * predicted line (explicit) */
330 boolean_t b_average /* (explicit) averaging of
331 * several predictions */ )
334 int i_source_offset, i_dest_offset, i_select;
336 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
337 + (p_mb->i_motion_l_y + i_offset
340 * p_mb->p_picture->i_width;
341 i_dest_offset = (p_mb->i_l_x)
342 + (p_mb->i_motion_l_y + b_dest_field)
343 * p_mb->p_picture->i_width;
344 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
348 MotionComponent( p_source->p_y
352 16, i_height, i_l_stride, p_mb->i_l_stride,
353 i_select, b_average );
356 MotionComponent( p_source->p_u
360 16, i_height, i_l_stride, p_mb->i_l_stride,
361 i_select, b_average );
364 MotionComponent( p_source->p_v
368 16, i_height, i_l_stride, p_mb->i_l_stride,
369 i_select, b_average );
373 /*****************************************************************************
374 * vdec_MotionFieldField : motion compensation for field motion type (field)
375 *****************************************************************************/
376 #define FIELDFIELD( MOTION ) \
377 picture_t * p_pred; \
379 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
381 if( p_mb->b_P_second \
382 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
383 p_pred = p_mb->p_picture; \
385 p_pred = p_mb->p_forward; \
387 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
388 p_mb->b_motion_field, \
389 p_mb->pppi_motion_vectors[0][0][0], \
390 p_mb->pppi_motion_vectors[0][0][1], \
391 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
393 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
395 MOTION( p_mb, p_mb->p_backward, \
396 p_mb->ppi_field_select[0][1], \
397 p_mb->b_motion_field, \
398 p_mb->pppi_motion_vectors[0][1][0], \
399 p_mb->pppi_motion_vectors[0][1][1], \
400 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
403 else /* MB_MOTION_BACKWARD */ \
405 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
406 p_mb->b_motion_field, \
407 p_mb->pppi_motion_vectors[0][1][0], \
408 p_mb->pppi_motion_vectors[0][1][1], \
409 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
413 void vdec_MotionFieldField420( macroblock_t * p_mb )
415 FIELDFIELD( Motion420 )
418 void vdec_MotionFieldField422( macroblock_t * p_mb )
420 //FIELDFIELD( Motion422 )
423 void vdec_MotionFieldField444( macroblock_t * p_mb )
425 //FIELDFIELD( Motion444 )
428 /*****************************************************************************
429 * vdec_MotionField16x8XXX: motion compensation for 16x8 motion type (field)
430 *****************************************************************************/
431 #define FIELD16X8( MOTION ) \
433 picture_t * p_pred; \
435 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
437 if( p_mb->b_P_second \
438 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
439 p_pred = p_mb->p_picture; \
441 p_pred = p_mb->p_forward; \
443 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
444 p_mb->b_motion_field, \
445 p_mb->pppi_motion_vectors[0][0][0], \
446 p_mb->pppi_motion_vectors[0][0][1], \
447 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
449 if( p_mb->b_P_second \
450 && (p_mb->b_motion_field != p_mb->ppi_field_select[1][0]) )\
451 p_pred = p_mb->p_picture; \
453 p_pred = p_mb->p_forward; \
455 MOTION( p_mb, p_pred, p_mb->ppi_field_select[1][0], \
456 p_mb->b_motion_field, \
457 p_mb->pppi_motion_vectors[1][0][0], \
458 p_mb->pppi_motion_vectors[1][0][1], \
459 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
461 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
463 MOTION( p_mb, p_mb->p_backward, \
464 p_mb->ppi_field_select[0][1], \
465 p_mb->b_motion_field, \
466 p_mb->pppi_motion_vectors[0][1][0], \
467 p_mb->pppi_motion_vectors[0][1][1], \
468 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 1 ); \
470 MOTION( p_mb, p_mb->p_backward, \
471 p_mb->ppi_field_select[1][1], \
472 p_mb->b_motion_field, \
473 p_mb->pppi_motion_vectors[1][1][0], \
474 p_mb->pppi_motion_vectors[1][1][1], \
475 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 1 ); \
479 else /* MB_MOTION_BACKWARD */ \
481 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
482 p_mb->b_motion_field, \
483 p_mb->pppi_motion_vectors[0][1][0], \
484 p_mb->pppi_motion_vectors[0][1][1], \
485 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
487 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], \
488 p_mb->b_motion_field, \
489 p_mb->pppi_motion_vectors[1][1][0], \
490 p_mb->pppi_motion_vectors[1][1][1], \
491 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
495 void vdec_MotionField16x8420( macroblock_t * p_mb )
497 FIELD16X8( Motion420 )
500 void vdec_MotionField16x8422( macroblock_t * p_mb )
502 //FIELD16X8( Motion422 )
505 void vdec_MotionField16x8444( macroblock_t * p_mb )
507 //FIELD16X8( Motion444 )
510 /*****************************************************************************
511 * vdec_MotionFieldDMVXXX?? : motion compensation for dmv motion type (field)
512 *****************************************************************************/
513 #define FIELDDMV( MOTION ) \
515 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
517 picture_t * p_pred; \
519 /* predict from field of same parity */ \
520 MOTION( p_mb, p_mb->p_forward, \
521 p_mb->b_motion_field, p_mb->b_motion_field, \
522 p_mb->pppi_motion_vectors[0][0][0], \
523 p_mb->pppi_motion_vectors[0][0][1], \
524 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
526 if( p_mb->b_P_second ) \
527 p_pred = p_mb->p_picture; \
529 p_pred = p_mb->p_forward; \
531 /* predict from field of opposite parity */ \
532 MOTION( p_mb, p_pred, !p_mb->b_motion_field, p_mb->b_motion_field, \
533 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
534 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
537 void vdec_MotionFieldDMV420( macroblock_t * p_mb )
539 FIELDDMV( Motion420 )
542 void vdec_MotionFieldDMV422( macroblock_t * p_mb )
544 //FIELDDMV( Motion422 )
547 void vdec_MotionFieldDMV444( macroblock_t * p_mb )
549 //FIELDDMV( Motion444 )
552 /*****************************************************************************
553 * vdec_MotionFrameFrameXXX?? : motion compensation for frame motion type (frame)
554 *****************************************************************************/
555 #define FRAMEFRAME( MOTION ) \
557 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
559 MOTION( p_mb, p_mb->p_forward, 0, 0, \
560 p_mb->pppi_motion_vectors[0][0][0], \
561 p_mb->pppi_motion_vectors[0][0][1], \
562 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
564 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
566 MOTION( p_mb, p_mb->p_backward, 0, 0, \
567 p_mb->pppi_motion_vectors[0][1][0], \
568 p_mb->pppi_motion_vectors[0][1][1], \
569 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
573 else /* MB_MOTION_BACKWARD */ \
575 MOTION( p_mb, p_mb->p_backward, 0, 0, \
576 p_mb->pppi_motion_vectors[0][1][0], \
577 p_mb->pppi_motion_vectors[0][1][1], \
578 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
582 void vdec_MotionFrameFrame420( macroblock_t * p_mb )
584 FRAMEFRAME( Motion420 )
587 void vdec_MotionFrameFrame422( macroblock_t * p_mb )
589 //FRAMEFRAME( Motion422 )
592 void vdec_MotionFrameFrame444( macroblock_t * p_mb )
594 //FRAMEFRAME( Motion444 )
597 /*****************************************************************************
598 * vdec_MotionFrameFieldXXX?? : motion compensation for field motion type (frame)
599 *****************************************************************************/
600 #define FRAMEFIELD( MOTION ) \
602 int i_l_stride = p_mb->i_l_stride << 1; \
603 int i_c_stride = p_mb->i_c_stride << 1; \
605 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
607 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[0][0], 0, \
608 p_mb->pppi_motion_vectors[0][0][0], \
609 p_mb->pppi_motion_vectors[0][0][1], \
610 i_l_stride, i_c_stride, 8, 0, 0 ); \
612 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[1][0], 1, \
613 p_mb->pppi_motion_vectors[1][0][0], \
614 p_mb->pppi_motion_vectors[1][0][1], \
615 i_l_stride, i_c_stride, 8, 0, 0 ); \
617 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
619 MOTION( p_mb, p_mb->p_backward, \
620 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, 1 ); \
625 MOTION( p_mb, p_mb->p_backward, \
626 p_mb->ppi_field_select[1][1], 1, \
627 p_mb->pppi_motion_vectors[1][1][0], \
628 p_mb->pppi_motion_vectors[1][1][1], \
629 i_l_stride, i_c_stride, 8, 0, 1 ); \
633 else /* MB_MOTION_BACKWARD only */ \
635 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], 0,\
636 p_mb->pppi_motion_vectors[0][1][0], \
637 p_mb->pppi_motion_vectors[0][1][1], \
638 i_l_stride, i_c_stride, 8, 0, 0 ); \
640 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], 1,\
641 p_mb->pppi_motion_vectors[1][1][0], \
642 p_mb->pppi_motion_vectors[1][1][1], \
643 i_l_stride, i_c_stride, 8, 0, 0 ); \
647 void vdec_MotionFrameField420( macroblock_t * p_mb )
649 FRAMEFIELD( Motion420 )
652 void vdec_MotionFrameField422( macroblock_t * p_mb )
654 //FRAMEFIELD( Motion422 )
657 void vdec_MotionFrameField444( macroblock_t * p_mb )
659 //FRAMEFIELD( Motion444 )
662 /*****************************************************************************
663 * vdec_MotionFrameDMVXXX?? : motion compensation for dmv motion type (frame)
664 *****************************************************************************/
665 #define FRAMEDMV( MOTION ) \
667 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
670 /* predict top field from top field */ \
671 MOTION( p_mb, p_mb->p_forward, 0, 0, \
672 p_mb->pppi_motion_vectors[0][0][0], \
673 p_mb->pppi_motion_vectors[0][0][1], \
674 /* XXX?? XXX?? >> 1 ? */ \
675 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
677 /* predict and add to top field from bottom field */ \
678 MOTION( p_mb, p_mb->p_forward, 1, 0, \
679 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
680 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
682 /* predict bottom field from bottom field */ \
683 MOTION( p_mb, p_mb->p_forward, 1, 1, \
684 p_mb->pppi_motion_vectors[0][0][0], \
685 p_mb->pppi_motion_vectors[0][0][1], \
686 /* XXX?? XXX?? >> 1 ? */ \
687 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
689 /* predict and add to bottom field from top field */ \
690 MOTION( p_mb, p_mb->p_forward, 1, 0, \
691 p_mb->ppi_dmv[1][0], p_mb->ppi_dmv[1][1], \
692 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
695 void vdec_MotionFrameDMV420( macroblock_t * p_mb )
697 FRAMEDMV( Motion420 )
700 void vdec_MotionFrameDMV422( macroblock_t * p_mb )
702 //FRAMEDMV( Motion422 )
705 void vdec_MotionFrameDMV444( macroblock_t * p_mb )
707 //FRAMEDMV( Motion444 )