1 /*****************************************************************************
2 * vdec_motion.c : motion compensation routines
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
5 * $Id: vdec_motion.c,v 1.35 2001/01/05 18:46:44 massiot Exp $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Jean-Marc Dressler <polux@via.ecp.fr>
9 * Michel Lespinasse <walken@via.ecp.fr>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
39 #include "stream_control.h"
40 #include "input_ext-dec.h"
43 #include "video_output.h"
45 #include "vdec_idct.h"
46 #include "video_decoder.h"
47 #include "vdec_motion.h"
49 #include "vpar_blocks.h"
50 #include "vpar_headers.h"
51 #include "vpar_synchro.h"
52 #include "video_parser.h"
53 #include "video_fifo.h"
55 #define __MotionComponents(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_copy_##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 (); \
63 void MotionComponent_X_Y_avg_##width##_##height ();
65 __MotionComponents (16,16) /* 444, 422, 420 */
66 __MotionComponents (16,8) /* 444, 422, 420 */
67 __MotionComponents (8,8) /* 422, 420 */
68 __MotionComponents (8,4) /* 420 */
70 __MotionComponents (8,16) /* 422 */
73 #define ___callTheRightOne(width,height) \
74 if ((i_width == width) && (i_height == height)) \
81 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
85 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
89 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
93 MotionComponent_X_Y_copy_##width##_##height (p_src, p_dest, \
103 MotionComponent_x_y_avg_##width##_##height (p_src, p_dest, \
107 MotionComponent_X_y_avg_##width##_##height (p_src, p_dest, \
111 MotionComponent_x_Y_avg_##width##_##height (p_src, p_dest, \
115 MotionComponent_X_Y_avg_##width##_##height (p_src, p_dest, \
122 /*****************************************************************************
123 * vdec_MotionComponent : last stage of motion compensation
124 *****************************************************************************/
125 static __inline__ void MotionComponent(
126 yuv_data_t * p_src, /* source block */
127 yuv_data_t * p_dest, /* dest block */
128 int i_width, /* (explicit) width of block */
129 int i_height, /* (explicit) height of block */
130 int i_stride, /* number of coeffs to jump
131 * between each predicted line */
132 int i_select, /* half-pel vectors */
133 boolean_t b_average /* (explicit) averaging of several
136 ___callTheRightOne (16,16)
137 ___callTheRightOne (16,8)
138 ___callTheRightOne (8,8)
139 ___callTheRightOne (8,4)
141 ___callTheRightOne (8,16)
145 /*****************************************************************************
146 * Motion420 : motion compensation for a 4:2:0 macroblock
147 *****************************************************************************/
148 static __inline__ void Motion420(
149 macroblock_t * p_mb, /* destination macroblock */
150 picture_t * p_source, /* source picture */
151 boolean_t b_source_field, /* source field */
152 boolean_t b_dest_field, /* destination field */
153 int i_mv_x, int i_mv_y, /* motion vector coordinates,
155 int i_l_stride, /* number of coeffs to jump to
156 * go to the next predicted
159 int i_height, /* height of the block to
160 * predict, in luminance
162 int i_offset, /* position of the first
163 * predicted line (explicit) */
164 boolean_t b_average /* (explicit) averaging of
165 * several predictions */ )
167 /* Temporary variables to avoid recalculating things twice */
168 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
170 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
171 + (p_mb->i_motion_l_y + i_offset
173 * p_mb->p_picture->i_width
174 + (i_mv_y >> 1) * i_l_stride;
175 if( i_source_offset >= p_source->i_width * p_source->i_height )
177 intf_ErrMsg( "vdec error: bad motion vector (lum)" );
182 MotionComponent( /* source */
183 p_source->p_y + i_source_offset,
187 + (p_mb->i_motion_l_y + b_dest_field + i_offset)
188 * p_mb->p_picture->i_width,
189 /* prediction width and height */
194 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
197 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
198 + (p_mb->i_motion_c_y + (i_offset >> 1)
200 * p_mb->p_picture->i_chroma_width
201 + ((i_mv_y/2) >> 1) * i_c_stride;
202 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
204 intf_ErrMsg( "vdec error: bad motion vector (chroma)" );
208 i_dest_offset = (p_mb->i_c_x)
209 + (p_mb->i_motion_c_y + b_dest_field
211 * p_mb->p_picture->i_chroma_width;
212 i_c_height = i_height >> 1;
213 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
216 MotionComponent( p_source->p_u
220 8, i_c_height, i_c_stride,
221 i_c_select, b_average );
224 MotionComponent( p_source->p_v
228 8, i_c_height, i_c_stride,
229 i_c_select, b_average );
232 /*****************************************************************************
233 * Motion422 : motion compensation for a 4:2:2 macroblock
234 *****************************************************************************/
235 static __inline__ void Motion422(
236 macroblock_t * p_mb, /* destination macroblock */
237 picture_t * p_source, /* source picture */
238 boolean_t b_source_field, /* source field */
239 boolean_t b_dest_field, /* destination field */
240 int i_mv_x, int i_mv_y, /* motion vector coordinates,
242 int i_l_stride, /* number of coeffs to jump to
243 * go to the next predicted
246 int i_height, /* height of the block to
247 * predict, in luminance
249 int i_offset, /* position of the first
250 * predicted line (explicit) */
251 boolean_t b_average /* (explicit) averaging of
252 * several predictions */ )
255 int i_source_offset, i_dest_offset, i_c_select;
258 MotionComponent( /* source */
260 + (p_mb->i_l_x + (i_mv_x >> 1))
261 + (p_mb->i_motion_l_y + i_offset
263 * p_mb->p_picture->i_width
264 + (i_mv_y >> 1) * p_mb->i_l_stride,
268 + (p_mb->i_motion_l_y + b_dest_field)
269 * p_mb->p_picture->i_width,
270 /* prediction width and height */
275 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
278 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
279 + (p_mb->i_motion_c_y + i_offset
281 * p_mb->p_picture->i_chroma_width
282 + (i_mv_y) >> 1) * p_mb->i_c_stride;
283 i_dest_offset = (p_mb->i_c_x)
284 + (p_mb->i_motion_c_y + b_dest_field)
285 * p_mb->p_picture->i_chroma_width;
286 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
289 MotionComponent( p_source->p_u
293 8, i_height, i_c_stride,
294 i_c_select, b_average );
297 MotionComponent( p_source->p_v
301 8, i_height, i_c_stride,
302 i_c_select, b_average );
306 /*****************************************************************************
307 * Motion444 : motion compensation for a 4:4:4 macroblock
308 *****************************************************************************/
309 static __inline__ void Motion444(
310 macroblock_t * p_mb, /* destination macroblock */
311 picture_t * p_source, /* source picture */
312 boolean_t b_source_field, /* source field */
313 boolean_t b_dest_field, /* destination field */
314 int i_mv_x, int i_mv_y, /* motion vector coordinates,
316 int i_l_stride, /* number of coeffs to jump to
317 * go to the next predicted
320 int i_height, /* height of the block to
321 * predict, in luminance
323 int i_offset, /* position of the first
324 * predicted line (explicit) */
325 boolean_t b_average /* (explicit) averaging of
326 * several predictions */ )
329 int i_source_offset, i_dest_offset, i_select;
331 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
332 + (p_mb->i_motion_l_y + i_offset
334 * p_mb->p_picture->i_width
335 + (i_mv_y >> 1) * p_mb->i_l_stride;
336 i_dest_offset = (p_mb->i_l_x)
337 + (p_mb->i_motion_l_y + b_dest_field)
338 * p_mb->p_picture->i_width;
339 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
343 MotionComponent( p_source->p_y
347 16, i_height, i_l_stride,
348 i_select, b_average );
351 MotionComponent( p_source->p_u
355 16, i_height, i_l_stride,
356 i_select, b_average );
359 MotionComponent( p_source->p_v
363 16, i_height, i_l_stride,
364 i_select, b_average );
368 /*****************************************************************************
369 * vdec_MotionFieldField : motion compensation for field motion type (field)
370 *****************************************************************************/
371 #define FIELDFIELD( MOTION ) \
373 picture_t * p_pred; \
375 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
377 if( p_mb->b_P_second \
378 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
379 p_pred = p_mb->p_picture; \
381 p_pred = p_mb->p_forward; \
383 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
384 p_mb->b_motion_field, \
385 p_mb->pppi_motion_vectors[0][0][0], \
386 p_mb->pppi_motion_vectors[0][0][1], \
387 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
389 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
391 MOTION( p_mb, p_mb->p_backward, \
392 p_mb->ppi_field_select[0][1], \
393 p_mb->b_motion_field, \
394 p_mb->pppi_motion_vectors[0][1][0], \
395 p_mb->pppi_motion_vectors[0][1][1], \
396 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
400 else /* MB_MOTION_BACKWARD */ \
402 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
403 p_mb->b_motion_field, \
404 p_mb->pppi_motion_vectors[0][1][0], \
405 p_mb->pppi_motion_vectors[0][1][1], \
406 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
410 void vdec_MotionFieldField420( macroblock_t * p_mb )
412 FIELDFIELD( Motion420 )
415 void vdec_MotionFieldField422( macroblock_t * p_mb )
417 //FIELDFIELD( Motion422 )
420 void vdec_MotionFieldField444( macroblock_t * p_mb )
422 //FIELDFIELD( Motion444 )
425 /*****************************************************************************
426 * vdec_MotionField16x8XXX: motion compensation for 16x8 motion type (field)
427 *****************************************************************************/
428 #define FIELD16X8( MOTION ) \
430 picture_t * p_pred; \
432 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
434 if( p_mb->b_P_second \
435 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][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[0][0], \
441 p_mb->b_motion_field, \
442 p_mb->pppi_motion_vectors[0][0][0], \
443 p_mb->pppi_motion_vectors[0][0][1], \
444 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
446 if( p_mb->b_P_second \
447 && (p_mb->b_motion_field != p_mb->ppi_field_select[1][0]) )\
448 p_pred = p_mb->p_picture; \
450 p_pred = p_mb->p_forward; \
452 MOTION( p_mb, p_pred, p_mb->ppi_field_select[1][0], \
453 p_mb->b_motion_field, \
454 p_mb->pppi_motion_vectors[1][0][0], \
455 p_mb->pppi_motion_vectors[1][0][1], \
456 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
458 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
460 MOTION( p_mb, p_mb->p_backward, \
461 p_mb->ppi_field_select[0][1], \
462 p_mb->b_motion_field, \
463 p_mb->pppi_motion_vectors[0][1][0], \
464 p_mb->pppi_motion_vectors[0][1][1], \
465 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 1 ); \
467 MOTION( p_mb, p_mb->p_backward, \
468 p_mb->ppi_field_select[1][1], \
469 p_mb->b_motion_field, \
470 p_mb->pppi_motion_vectors[1][1][0], \
471 p_mb->pppi_motion_vectors[1][1][1], \
472 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 1 ); \
476 else /* MB_MOTION_BACKWARD */ \
478 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
479 p_mb->b_motion_field, \
480 p_mb->pppi_motion_vectors[0][1][0], \
481 p_mb->pppi_motion_vectors[0][1][1], \
482 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
484 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], \
485 p_mb->b_motion_field, \
486 p_mb->pppi_motion_vectors[1][1][0], \
487 p_mb->pppi_motion_vectors[1][1][1], \
488 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
492 void vdec_MotionField16x8420( macroblock_t * p_mb )
494 FIELD16X8( Motion420 )
497 void vdec_MotionField16x8422( macroblock_t * p_mb )
499 //FIELD16X8( Motion422 )
502 void vdec_MotionField16x8444( macroblock_t * p_mb )
504 //FIELD16X8( Motion444 )
507 /*****************************************************************************
508 * vdec_MotionFieldDMVXXX : motion compensation for dmv motion type (field)
509 *****************************************************************************/
510 #define FIELDDMV( MOTION ) \
512 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
514 picture_t * p_pred; \
516 /* predict from field of same parity */ \
517 MOTION( p_mb, p_mb->p_forward, \
518 p_mb->b_motion_field, p_mb->b_motion_field, \
519 p_mb->pppi_motion_vectors[0][0][0], \
520 p_mb->pppi_motion_vectors[0][0][1], \
521 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
523 if( p_mb->b_P_second ) \
524 p_pred = p_mb->p_picture; \
526 p_pred = p_mb->p_forward; \
528 /* predict from field of opposite parity */ \
529 MOTION( p_mb, p_pred, !p_mb->b_motion_field, p_mb->b_motion_field, \
530 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
531 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
534 void vdec_MotionFieldDMV420( macroblock_t * p_mb )
536 FIELDDMV( Motion420 )
539 void vdec_MotionFieldDMV422( macroblock_t * p_mb )
541 //FIELDDMV( Motion422 )
544 void vdec_MotionFieldDMV444( macroblock_t * p_mb )
546 //FIELDDMV( Motion444 )
549 /*****************************************************************************
550 * vdec_MotionFrameFrameXXX?? : motion compensation for frame motion type (frame)
551 *****************************************************************************/
552 #define FRAMEFRAME( MOTION ) \
554 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
556 MOTION( p_mb, p_mb->p_forward, 0, 0, \
557 p_mb->pppi_motion_vectors[0][0][0], \
558 p_mb->pppi_motion_vectors[0][0][1], \
559 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
561 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
563 MOTION( p_mb, p_mb->p_backward, 0, 0, \
564 p_mb->pppi_motion_vectors[0][1][0], \
565 p_mb->pppi_motion_vectors[0][1][1], \
566 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
570 else /* MB_MOTION_BACKWARD */ \
572 MOTION( p_mb, p_mb->p_backward, 0, 0, \
573 p_mb->pppi_motion_vectors[0][1][0], \
574 p_mb->pppi_motion_vectors[0][1][1], \
575 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
579 void vdec_MotionFrameFrame420( macroblock_t * p_mb )
581 FRAMEFRAME( Motion420 )
584 void vdec_MotionFrameFrame422( macroblock_t * p_mb )
586 //FRAMEFRAME( Motion422 )
589 void vdec_MotionFrameFrame444( macroblock_t * p_mb )
591 //FRAMEFRAME( Motion444 )
594 /*****************************************************************************
595 * vdec_MotionFrameFieldXXX?? : motion compensation for field motion type (frame)
596 *****************************************************************************/
597 #define FRAMEFIELD( MOTION ) \
599 int i_l_stride = p_mb->i_l_stride << 1; \
600 int i_c_stride = p_mb->i_c_stride << 1; \
602 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
604 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[0][0], 0, \
605 p_mb->pppi_motion_vectors[0][0][0], \
606 p_mb->pppi_motion_vectors[0][0][1] >> 1, \
607 i_l_stride, i_c_stride, 8, 0, 0 ); \
609 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[1][0], 1, \
610 p_mb->pppi_motion_vectors[1][0][0], \
611 p_mb->pppi_motion_vectors[1][0][1] >> 1, \
612 i_l_stride, i_c_stride, 8, 0, 0 ); \
614 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
616 MOTION( p_mb, p_mb->p_backward, \
617 p_mb->ppi_field_select[0][1], 0, \
618 p_mb->pppi_motion_vectors[0][1][0], \
619 p_mb->pppi_motion_vectors[0][1][1] >> 1, \
620 i_l_stride, i_c_stride, 8, 0, 1 ); \
622 MOTION( p_mb, p_mb->p_backward, \
623 p_mb->ppi_field_select[1][1], 1, \
624 p_mb->pppi_motion_vectors[1][1][0], \
625 p_mb->pppi_motion_vectors[1][1][1] >> 1, \
626 i_l_stride, i_c_stride, 8, 0, 1 ); \
630 else /* MB_MOTION_BACKWARD only */ \
632 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], 0,\
633 p_mb->pppi_motion_vectors[0][1][0], \
634 p_mb->pppi_motion_vectors[0][1][1] >> 1, \
635 i_l_stride, i_c_stride, 8, 0, 0 ); \
637 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], 1,\
638 p_mb->pppi_motion_vectors[1][1][0], \
639 p_mb->pppi_motion_vectors[1][1][1] >> 1, \
640 i_l_stride, i_c_stride, 8, 0, 0 ); \
644 void vdec_MotionFrameField420( macroblock_t * p_mb )
646 FRAMEFIELD( Motion420 )
649 void vdec_MotionFrameField422( macroblock_t * p_mb )
651 //FRAMEFIELD( Motion422 )
654 void vdec_MotionFrameField444( macroblock_t * p_mb )
656 //FRAMEFIELD( Motion444 )
659 /*****************************************************************************
660 * vdec_MotionFrameDMVXXX?? : motion compensation for dmv motion type (frame)
661 *****************************************************************************/
662 #define FRAMEDMV( MOTION ) \
664 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
667 /* predict top field from top field */ \
668 MOTION( p_mb, p_mb->p_forward, 0, 0, \
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 top field from bottom field */ \
675 MOTION( p_mb, p_mb->p_forward, 1, 0, \
676 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
677 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
679 /* predict bottom field from bottom field */ \
680 MOTION( p_mb, p_mb->p_forward, 1, 1, \
681 p_mb->pppi_motion_vectors[0][0][0], \
682 p_mb->pppi_motion_vectors[0][0][1], \
683 /* XXX?? XXX?? >> 1 ? */ \
684 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
686 /* predict and add to bottom field from top field */ \
687 MOTION( p_mb, p_mb->p_forward, 1, 0, \
688 p_mb->ppi_dmv[1][0], p_mb->ppi_dmv[1][1], \
689 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
692 void vdec_MotionFrameDMV420( macroblock_t * p_mb )
694 FRAMEDMV( Motion420 )
697 void vdec_MotionFrameDMV422( macroblock_t * p_mb )
699 //FRAMEDMV( Motion422 )
702 void vdec_MotionFrameDMV444( macroblock_t * p_mb )
704 //FRAMEDMV( Motion444 )