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 GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <sys/types.h> /* on BSD, uio.h needs types.h */
28 #include <sys/uio.h> /* for input.h */
38 #include "decoder_fifo.h"
40 #include "video_output.h"
42 #include "vdec_idct.h"
43 #include "video_decoder.h"
44 #include "vdec_motion.h"
46 #include "vpar_blocks.h"
47 #include "vpar_headers.h"
48 #include "vpar_synchro.h"
49 #include "video_parser.h"
50 #include "video_fifo.h"
52 #define __MotionComponents(width,height) \
53 void MotionComponent_x_y_copy_##width##_##height (); \
54 void MotionComponent_X_y_copy_##width##_##height (); \
55 void MotionComponent_x_Y_copy_##width##_##height (); \
56 void MotionComponent_X_Y_copy_##width##_##height (); \
57 void MotionComponent_x_y_avg_##width##_##height (); \
58 void MotionComponent_X_y_avg_##width##_##height (); \
59 void MotionComponent_x_Y_avg_##width##_##height (); \
60 void MotionComponent_X_Y_avg_##width##_##height ();
62 __MotionComponents (16,16) /* 444, 422, 420 */
63 __MotionComponents (16,8) /* 444, 422, 420 */
64 __MotionComponents (8,8) /* 422, 420 */
65 __MotionComponents (8,4) /* 420 */
67 __MotionComponents (8,16) /* 422 */
70 #define ___callTheRightOne(width,height) \
71 if ((i_width == width) && (i_height == height)) \
78 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
82 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
86 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
91 MotionComponent_X_Y_copy_##width##_##height (p_src, p_dest, \
102 MotionComponent_x_y_avg_##width##_##height (p_src, p_dest, \
106 MotionComponent_X_y_avg_##width##_##height (p_src, p_dest, \
110 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_step, /* number of coeffs to jump to
133 * go to the next line of the
135 int i_select, /* half-pel vectors */
136 boolean_t b_average /* (explicit) averaging of several
139 ___callTheRightOne (16,16)
140 ___callTheRightOne (16,8)
141 ___callTheRightOne (8,8)
142 ___callTheRightOne (8,4)
144 ___callTheRightOne (8,16)
148 /*****************************************************************************
149 * Motion420 : motion compensation for a 4:2:0 macroblock
150 *****************************************************************************/
151 static __inline__ void Motion420(
152 macroblock_t * p_mb, /* destination macroblock */
153 picture_t * p_source, /* source picture */
154 boolean_t b_source_field, /* source field */
155 boolean_t b_dest_field, /* destination field */
156 int i_mv_x, int i_mv_y, /* motion vector coordinates,
158 int i_l_stride, /* number of coeffs to jump to
159 * go to the next predicted
162 int i_height, /* height of the block to
163 * predict, in luminance
165 int i_offset, /* position of the first
166 * predicted line (explicit) */
167 boolean_t b_average /* (explicit) averaging of
168 * several predictions */ )
170 /* Temporary variables to avoid recalculating things twice */
171 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
173 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
174 + (p_mb->i_motion_l_y + i_offset
177 * p_mb->p_picture->i_width;
178 if( i_source_offset >= p_source->i_width * p_source->i_height )
180 intf_ErrMsg( "vdec error: bad motion vector\n" );
185 MotionComponent( /* source */
186 p_source->p_y + i_source_offset,
190 + (p_mb->i_motion_l_y + b_dest_field)
191 * p_mb->p_picture->i_width,
192 /* prediction width and height */
195 i_l_stride, p_mb->i_l_stride,
197 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
200 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
201 + ((p_mb->i_motion_c_y + (i_offset >> 1)
204 * p_mb->p_picture->i_chroma_width;
205 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
207 intf_ErrMsg( "vdec error: bad motion vector\n" );
211 i_dest_offset = (p_mb->i_c_x)
212 + (p_mb->i_motion_c_y + b_dest_field)
213 * p_mb->p_picture->i_chroma_width;
214 i_c_height = i_height >> 1;
215 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
218 MotionComponent( p_source->p_u
222 8, i_c_height, i_c_stride, p_mb->i_c_stride,
223 i_c_select, b_average );
226 MotionComponent( p_source->p_v
230 8, i_c_height, i_c_stride, p_mb->i_c_stride,
231 i_c_select, b_average );
234 /*****************************************************************************
235 * Motion422 : motion compensation for a 4:2:2 macroblock
236 *****************************************************************************/
237 static __inline__ void Motion422(
238 macroblock_t * p_mb, /* destination macroblock */
239 picture_t * p_source, /* source picture */
240 boolean_t b_source_field, /* source field */
241 boolean_t b_dest_field, /* destination field */
242 int i_mv_x, int i_mv_y, /* motion vector coordinates,
244 int i_l_stride, /* number of coeffs to jump to
245 * go to the next predicted
248 int i_height, /* height of the block to
249 * predict, in luminance
251 int i_offset, /* position of the first
252 * predicted line (explicit) */
253 boolean_t b_average /* (explicit) averaging of
254 * several predictions */ )
257 int i_source_offset, i_dest_offset, i_c_select;
260 MotionComponent( /* source */
262 + (p_mb->i_l_x + (i_mv_x >> 1))
263 + (p_mb->i_motion_l_y + i_offset
266 * p_mb->p_picture->i_width,
270 + (p_mb->i_motion_l_y + b_dest_field)
271 * p_mb->p_picture->i_width,
272 /* prediction width and height */
275 i_l_stride, p_mb->i_l_stride,
277 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
280 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
281 + ((p_mb->i_motion_c_y + (i_offset)
284 * p_mb->p_picture->i_chroma_width;
285 i_dest_offset = (p_mb->i_c_x)
286 + (p_mb->i_motion_c_y + b_dest_field)
287 * p_mb->p_picture->i_chroma_width;
288 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
291 MotionComponent( p_source->p_u
295 8, i_height, i_c_stride, p_mb->i_c_stride,
296 i_c_select, b_average );
299 MotionComponent( p_source->p_v
303 8, i_height, i_c_stride, p_mb->i_c_stride,
304 i_c_select, b_average );
308 /*****************************************************************************
309 * Motion444 : motion compensation for a 4:4:4 macroblock
310 *****************************************************************************/
311 static __inline__ void Motion444(
312 macroblock_t * p_mb, /* destination macroblock */
313 picture_t * p_source, /* source picture */
314 boolean_t b_source_field, /* source field */
315 boolean_t b_dest_field, /* destination field */
316 int i_mv_x, int i_mv_y, /* motion vector coordinates,
318 int i_l_stride, /* number of coeffs to jump to
319 * go to the next predicted
322 int i_height, /* height of the block to
323 * predict, in luminance
325 int i_offset, /* position of the first
326 * predicted line (explicit) */
327 boolean_t b_average /* (explicit) averaging of
328 * several predictions */ )
331 int i_source_offset, i_dest_offset, i_select;
333 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
334 + (p_mb->i_motion_l_y + i_offset
337 * p_mb->p_picture->i_width;
338 i_dest_offset = (p_mb->i_l_x)
339 + (p_mb->i_motion_l_y + b_dest_field)
340 * p_mb->p_picture->i_width;
341 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
345 MotionComponent( p_source->p_y
349 16, i_height, i_l_stride, p_mb->i_l_stride,
350 i_select, b_average );
353 MotionComponent( p_source->p_u
357 16, i_height, i_l_stride, p_mb->i_l_stride,
358 i_select, b_average );
361 MotionComponent( p_source->p_v
365 16, i_height, i_l_stride, p_mb->i_l_stride,
366 i_select, b_average );
370 /*****************************************************************************
371 * vdec_MotionFieldField : motion compensation for field motion type (field)
372 *****************************************************************************/
373 #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 ); \
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], \
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], \
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], \
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], \
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], \
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], \
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 )