1 /*****************************************************************************
2 * vdec_motion.c : motion compensation routines
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7 * Jean-Marc Dressler <polux@via.ecp.fr>
8 * Michel Lespinasse <walken@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
30 #include <sys/types.h> /* on BSD, uio.h needs types.h */
31 #include <sys/uio.h> /* for input.h */
42 #include "decoder_fifo.h"
44 #include "video_output.h"
46 #include "vdec_idct.h"
47 #include "video_decoder.h"
48 #include "vdec_motion.h"
50 #include "vpar_blocks.h"
51 #include "vpar_headers.h"
52 #include "vpar_synchro.h"
53 #include "video_parser.h"
54 #include "video_fifo.h"
56 #define __MotionComponents(width,height) \
57 void MotionComponent_x_y_copy_##width##_##height (); \
58 void MotionComponent_X_y_copy_##width##_##height (); \
59 void MotionComponent_x_Y_copy_##width##_##height (); \
60 void MotionComponent_X_Y_copy_##width##_##height (); \
61 void MotionComponent_x_y_avg_##width##_##height (); \
62 void MotionComponent_X_y_avg_##width##_##height (); \
63 void MotionComponent_x_Y_avg_##width##_##height (); \
64 void MotionComponent_X_Y_avg_##width##_##height ();
66 __MotionComponents (16,16) /* 444, 422, 420 */
67 __MotionComponents (16,8) /* 444, 422, 420 */
68 __MotionComponents (8,8) /* 422, 420 */
69 __MotionComponents (8,4) /* 420 */
71 __MotionComponents (8,16) /* 422 */
74 #define ___callTheRightOne(width,height) \
75 if ((i_width == width) && (i_height == height)) \
82 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
86 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
90 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
94 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, \
116 MotionComponent_X_Y_avg_##width##_##height (p_src, p_dest, \
123 /*****************************************************************************
124 * vdec_MotionComponent : last stage of motion compensation
125 *****************************************************************************/
126 static __inline__ void MotionComponent(
127 yuv_data_t * p_src, /* source block */
128 yuv_data_t * p_dest, /* dest block */
129 int i_width, /* (explicit) width of block */
130 int i_height, /* (explicit) height of block */
131 int i_stride, /* number of coeffs to jump
132 * between each predicted line */
133 int i_select, /* half-pel vectors */
134 boolean_t b_average /* (explicit) averaging of several
137 ___callTheRightOne (16,16)
138 ___callTheRightOne (16,8)
139 ___callTheRightOne (8,8)
140 ___callTheRightOne (8,4)
142 ___callTheRightOne (8,16)
146 /*****************************************************************************
147 * Motion420 : motion compensation for a 4:2:0 macroblock
148 *****************************************************************************/
149 static __inline__ void Motion420(
150 macroblock_t * p_mb, /* destination macroblock */
151 picture_t * p_source, /* source picture */
152 boolean_t b_source_field, /* source field */
153 boolean_t b_dest_field, /* destination field */
154 int i_mv_x, int i_mv_y, /* motion vector coordinates,
156 int i_l_stride, /* number of coeffs to jump to
157 * go to the next predicted
160 int i_height, /* height of the block to
161 * predict, in luminance
163 int i_offset, /* position of the first
164 * predicted line (explicit) */
165 boolean_t b_average /* (explicit) averaging of
166 * several predictions */ )
168 /* Temporary variables to avoid recalculating things twice */
169 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
171 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
172 + (p_mb->i_motion_l_y + i_offset
174 * p_mb->p_picture->i_width
175 + (i_mv_y >> 1) * i_l_stride;
176 if( i_source_offset >= p_source->i_width * p_source->i_height )
178 intf_ErrMsg( "vdec error: bad motion vector (lum)\n" );
183 MotionComponent( /* source */
184 p_source->p_y + i_source_offset,
188 + (p_mb->i_motion_l_y + b_dest_field + i_offset)
189 * p_mb->p_picture->i_width,
190 /* prediction width and height */
195 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
198 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
199 + (p_mb->i_motion_c_y + (i_offset >> 1)
201 * p_mb->p_picture->i_chroma_width
202 + ((i_mv_y/2) >> 1) * i_c_stride;
203 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
205 intf_ErrMsg( "vdec error: bad motion vector (chroma)\n" );
209 i_dest_offset = (p_mb->i_c_x)
210 + (p_mb->i_motion_c_y + b_dest_field
212 * p_mb->p_picture->i_chroma_width;
213 i_c_height = i_height >> 1;
214 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
217 MotionComponent( p_source->p_u
221 8, i_c_height, i_c_stride,
222 i_c_select, b_average );
225 MotionComponent( p_source->p_v
229 8, i_c_height, i_c_stride,
230 i_c_select, b_average );
233 /*****************************************************************************
234 * Motion422 : motion compensation for a 4:2:2 macroblock
235 *****************************************************************************/
236 static __inline__ void Motion422(
237 macroblock_t * p_mb, /* destination macroblock */
238 picture_t * p_source, /* source picture */
239 boolean_t b_source_field, /* source field */
240 boolean_t b_dest_field, /* destination field */
241 int i_mv_x, int i_mv_y, /* motion vector coordinates,
243 int i_l_stride, /* number of coeffs to jump to
244 * go to the next predicted
247 int i_height, /* height of the block to
248 * predict, in luminance
250 int i_offset, /* position of the first
251 * predicted line (explicit) */
252 boolean_t b_average /* (explicit) averaging of
253 * several predictions */ )
256 int i_source_offset, i_dest_offset, i_c_select;
259 MotionComponent( /* source */
261 + (p_mb->i_l_x + (i_mv_x >> 1))
262 + (p_mb->i_motion_l_y + i_offset
264 * p_mb->p_picture->i_width
265 + (i_mv_y >> 1) * p_mb->i_l_stride,
269 + (p_mb->i_motion_l_y + b_dest_field)
270 * p_mb->p_picture->i_width,
271 /* prediction width and height */
276 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
279 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
280 + (p_mb->i_motion_c_y + i_offset
282 * p_mb->p_picture->i_chroma_width
283 + (i_mv_y) >> 1) * p_mb->i_c_stride;
284 i_dest_offset = (p_mb->i_c_x)
285 + (p_mb->i_motion_c_y + b_dest_field)
286 * p_mb->p_picture->i_chroma_width;
287 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
290 MotionComponent( p_source->p_u
294 8, i_height, i_c_stride,
295 i_c_select, b_average );
298 MotionComponent( p_source->p_v
302 8, i_height, i_c_stride,
303 i_c_select, b_average );
307 /*****************************************************************************
308 * Motion444 : motion compensation for a 4:4:4 macroblock
309 *****************************************************************************/
310 static __inline__ void Motion444(
311 macroblock_t * p_mb, /* destination macroblock */
312 picture_t * p_source, /* source picture */
313 boolean_t b_source_field, /* source field */
314 boolean_t b_dest_field, /* destination field */
315 int i_mv_x, int i_mv_y, /* motion vector coordinates,
317 int i_l_stride, /* number of coeffs to jump to
318 * go to the next predicted
321 int i_height, /* height of the block to
322 * predict, in luminance
324 int i_offset, /* position of the first
325 * predicted line (explicit) */
326 boolean_t b_average /* (explicit) averaging of
327 * several predictions */ )
330 int i_source_offset, i_dest_offset, i_select;
332 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
333 + (p_mb->i_motion_l_y + i_offset
335 * p_mb->p_picture->i_width
336 + (i_mv_y >> 1) * p_mb->i_l_stride;
337 i_dest_offset = (p_mb->i_l_x)
338 + (p_mb->i_motion_l_y + b_dest_field)
339 * p_mb->p_picture->i_width;
340 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
344 MotionComponent( p_source->p_y
348 16, i_height, i_l_stride,
349 i_select, b_average );
352 MotionComponent( p_source->p_u
356 16, i_height, i_l_stride,
357 i_select, b_average );
360 MotionComponent( p_source->p_v
364 16, i_height, i_l_stride,
365 i_select, b_average );
369 /*****************************************************************************
370 * vdec_MotionFieldField : motion compensation for field motion type (field)
371 *****************************************************************************/
372 #define FIELDFIELD( MOTION ) \
374 picture_t * p_pred; \
376 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
378 if( p_mb->b_P_second \
379 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
380 p_pred = p_mb->p_picture; \
382 p_pred = p_mb->p_forward; \
384 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
385 p_mb->b_motion_field, \
386 p_mb->pppi_motion_vectors[0][0][0], \
387 p_mb->pppi_motion_vectors[0][0][1], \
388 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
390 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
392 MOTION( p_mb, p_mb->p_backward, \
393 p_mb->ppi_field_select[0][1], \
394 p_mb->b_motion_field, \
395 p_mb->pppi_motion_vectors[0][1][0], \
396 p_mb->pppi_motion_vectors[0][1][1], \
397 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
401 else /* MB_MOTION_BACKWARD */ \
403 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
404 p_mb->b_motion_field, \
405 p_mb->pppi_motion_vectors[0][1][0], \
406 p_mb->pppi_motion_vectors[0][1][1], \
407 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
411 void vdec_MotionFieldField420( macroblock_t * p_mb )
413 FIELDFIELD( Motion420 )
416 void vdec_MotionFieldField422( macroblock_t * p_mb )
418 //FIELDFIELD( Motion422 )
421 void vdec_MotionFieldField444( macroblock_t * p_mb )
423 //FIELDFIELD( Motion444 )
426 /*****************************************************************************
427 * vdec_MotionField16x8XXX: motion compensation for 16x8 motion type (field)
428 *****************************************************************************/
429 #define FIELD16X8( MOTION ) \
431 picture_t * p_pred; \
433 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
435 if( p_mb->b_P_second \
436 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
437 p_pred = p_mb->p_picture; \
439 p_pred = p_mb->p_forward; \
441 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
442 p_mb->b_motion_field, \
443 p_mb->pppi_motion_vectors[0][0][0], \
444 p_mb->pppi_motion_vectors[0][0][1], \
445 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
447 if( p_mb->b_P_second \
448 && (p_mb->b_motion_field != p_mb->ppi_field_select[1][0]) )\
449 p_pred = p_mb->p_picture; \
451 p_pred = p_mb->p_forward; \
453 MOTION( p_mb, p_pred, p_mb->ppi_field_select[1][0], \
454 p_mb->b_motion_field, \
455 p_mb->pppi_motion_vectors[1][0][0], \
456 p_mb->pppi_motion_vectors[1][0][1], \
457 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
459 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
461 MOTION( p_mb, p_mb->p_backward, \
462 p_mb->ppi_field_select[0][1], \
463 p_mb->b_motion_field, \
464 p_mb->pppi_motion_vectors[0][1][0], \
465 p_mb->pppi_motion_vectors[0][1][1], \
466 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 1 ); \
468 MOTION( p_mb, p_mb->p_backward, \
469 p_mb->ppi_field_select[1][1], \
470 p_mb->b_motion_field, \
471 p_mb->pppi_motion_vectors[1][1][0], \
472 p_mb->pppi_motion_vectors[1][1][1], \
473 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 1 ); \
477 else /* MB_MOTION_BACKWARD */ \
479 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
480 p_mb->b_motion_field, \
481 p_mb->pppi_motion_vectors[0][1][0], \
482 p_mb->pppi_motion_vectors[0][1][1], \
483 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
485 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], \
486 p_mb->b_motion_field, \
487 p_mb->pppi_motion_vectors[1][1][0], \
488 p_mb->pppi_motion_vectors[1][1][1], \
489 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
493 void vdec_MotionField16x8420( macroblock_t * p_mb )
495 FIELD16X8( Motion420 )
498 void vdec_MotionField16x8422( macroblock_t * p_mb )
500 //FIELD16X8( Motion422 )
503 void vdec_MotionField16x8444( macroblock_t * p_mb )
505 //FIELD16X8( Motion444 )
508 /*****************************************************************************
509 * vdec_MotionFieldDMVXXX : motion compensation for dmv motion type (field)
510 *****************************************************************************/
511 #define FIELDDMV( MOTION ) \
513 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
515 picture_t * p_pred; \
517 /* predict from field of same parity */ \
518 MOTION( p_mb, p_mb->p_forward, \
519 p_mb->b_motion_field, p_mb->b_motion_field, \
520 p_mb->pppi_motion_vectors[0][0][0], \
521 p_mb->pppi_motion_vectors[0][0][1], \
522 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
524 if( p_mb->b_P_second ) \
525 p_pred = p_mb->p_picture; \
527 p_pred = p_mb->p_forward; \
529 /* predict from field of opposite parity */ \
530 MOTION( p_mb, p_pred, !p_mb->b_motion_field, p_mb->b_motion_field, \
531 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
532 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
535 void vdec_MotionFieldDMV420( macroblock_t * p_mb )
537 FIELDDMV( Motion420 )
540 void vdec_MotionFieldDMV422( macroblock_t * p_mb )
542 //FIELDDMV( Motion422 )
545 void vdec_MotionFieldDMV444( macroblock_t * p_mb )
547 //FIELDDMV( Motion444 )
550 /*****************************************************************************
551 * vdec_MotionFrameFrameXXX?? : motion compensation for frame motion type (frame)
552 *****************************************************************************/
553 #define FRAMEFRAME( MOTION ) \
555 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
557 MOTION( p_mb, p_mb->p_forward, 0, 0, \
558 p_mb->pppi_motion_vectors[0][0][0], \
559 p_mb->pppi_motion_vectors[0][0][1], \
560 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
562 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
564 MOTION( p_mb, p_mb->p_backward, 0, 0, \
565 p_mb->pppi_motion_vectors[0][1][0], \
566 p_mb->pppi_motion_vectors[0][1][1], \
567 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
571 else /* MB_MOTION_BACKWARD */ \
573 MOTION( p_mb, p_mb->p_backward, 0, 0, \
574 p_mb->pppi_motion_vectors[0][1][0], \
575 p_mb->pppi_motion_vectors[0][1][1], \
576 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
580 void vdec_MotionFrameFrame420( macroblock_t * p_mb )
582 FRAMEFRAME( Motion420 )
585 void vdec_MotionFrameFrame422( macroblock_t * p_mb )
587 //FRAMEFRAME( Motion422 )
590 void vdec_MotionFrameFrame444( macroblock_t * p_mb )
592 //FRAMEFRAME( Motion444 )
595 /*****************************************************************************
596 * vdec_MotionFrameFieldXXX?? : motion compensation for field motion type (frame)
597 *****************************************************************************/
598 #define FRAMEFIELD( MOTION ) \
600 int i_l_stride = p_mb->i_l_stride << 1; \
601 int i_c_stride = p_mb->i_c_stride << 1; \
603 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
605 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[0][0], 0, \
606 p_mb->pppi_motion_vectors[0][0][0], \
607 p_mb->pppi_motion_vectors[0][0][1] >> 1, \
608 i_l_stride, i_c_stride, 8, 0, 0 ); \
610 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[1][0], 1, \
611 p_mb->pppi_motion_vectors[1][0][0], \
612 p_mb->pppi_motion_vectors[1][0][1] >> 1, \
613 i_l_stride, i_c_stride, 8, 0, 0 ); \
615 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
617 MOTION( p_mb, p_mb->p_backward, \
618 p_mb->ppi_field_select[0][1], 0, \
619 p_mb->pppi_motion_vectors[0][1][0], \
620 p_mb->pppi_motion_vectors[0][1][1] >> 1, \
621 i_l_stride, i_c_stride, 8, 0, 1 ); \
623 MOTION( p_mb, p_mb->p_backward, \
624 p_mb->ppi_field_select[1][1], 1, \
625 p_mb->pppi_motion_vectors[1][1][0], \
626 p_mb->pppi_motion_vectors[1][1][1] >> 1, \
627 i_l_stride, i_c_stride, 8, 0, 1 ); \
631 else /* MB_MOTION_BACKWARD only */ \
633 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], 0,\
634 p_mb->pppi_motion_vectors[0][1][0], \
635 p_mb->pppi_motion_vectors[0][1][1] >> 1, \
636 i_l_stride, i_c_stride, 8, 0, 0 ); \
638 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], 1,\
639 p_mb->pppi_motion_vectors[1][1][0], \
640 p_mb->pppi_motion_vectors[1][1][1] >> 1, \
641 i_l_stride, i_c_stride, 8, 0, 0 ); \
645 void vdec_MotionFrameField420( macroblock_t * p_mb )
647 FRAMEFIELD( Motion420 )
650 void vdec_MotionFrameField422( macroblock_t * p_mb )
652 //FRAMEFIELD( Motion422 )
655 void vdec_MotionFrameField444( macroblock_t * p_mb )
657 //FRAMEFIELD( Motion444 )
660 /*****************************************************************************
661 * vdec_MotionFrameDMVXXX?? : motion compensation for dmv motion type (frame)
662 *****************************************************************************/
663 #define FRAMEDMV( MOTION ) \
665 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
668 /* predict top field from top field */ \
669 MOTION( p_mb, p_mb->p_forward, 0, 0, \
670 p_mb->pppi_motion_vectors[0][0][0], \
671 p_mb->pppi_motion_vectors[0][0][1], \
672 /* XXX?? XXX?? >> 1 ? */ \
673 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
675 /* predict and add to top field from bottom field */ \
676 MOTION( p_mb, p_mb->p_forward, 1, 0, \
677 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
678 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
680 /* predict bottom field from bottom field */ \
681 MOTION( p_mb, p_mb->p_forward, 1, 1, \
682 p_mb->pppi_motion_vectors[0][0][0], \
683 p_mb->pppi_motion_vectors[0][0][1], \
684 /* XXX?? XXX?? >> 1 ? */ \
685 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
687 /* predict and add to bottom field from top field */ \
688 MOTION( p_mb, p_mb->p_forward, 1, 0, \
689 p_mb->ppi_dmv[1][0], p_mb->ppi_dmv[1][1], \
690 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
693 void vdec_MotionFrameDMV420( macroblock_t * p_mb )
695 FRAMEDMV( Motion420 )
698 void vdec_MotionFrameDMV422( macroblock_t * p_mb )
700 //FRAMEDMV( Motion422 )
703 void vdec_MotionFrameDMV444( macroblock_t * p_mb )
705 //FRAMEDMV( Motion444 )