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 */
39 #include "decoder_fifo.h"
41 #include "video_output.h"
43 #include "vdec_idct.h"
44 #include "video_decoder.h"
45 #include "vdec_motion.h"
47 #include "vpar_blocks.h"
48 #include "vpar_headers.h"
49 #include "vpar_synchro.h"
50 #include "video_parser.h"
51 #include "video_fifo.h"
53 #define __MotionComponents(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_copy_##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 (); \
61 void MotionComponent_X_Y_avg_##width##_##height ();
63 __MotionComponents (16,16) /* 444, 422, 420 */
64 __MotionComponents (16,8) /* 444, 422, 420 */
65 __MotionComponents (8,8) /* 422, 420 */
66 __MotionComponents (8,4) /* 420 */
68 __MotionComponents (8,16) /* 422 */
71 #define ___callTheRightOne(width,height) \
72 if ((i_width == width) && (i_height == height)) \
79 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
83 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
87 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
92 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, \
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_step, /* number of coeffs to jump to
134 * go to the next line of the
136 int i_select, /* half-pel vectors */
137 boolean_t b_average /* (explicit) averaging of several
140 ___callTheRightOne (16,16)
141 ___callTheRightOne (16,8)
142 ___callTheRightOne (8,8)
143 ___callTheRightOne (8,4)
145 ___callTheRightOne (8,16)
149 /*****************************************************************************
150 * Motion420 : motion compensation for a 4:2:0 macroblock
151 *****************************************************************************/
152 static __inline__ void Motion420(
153 macroblock_t * p_mb, /* destination macroblock */
154 picture_t * p_source, /* source picture */
155 boolean_t b_source_field, /* source field */
156 boolean_t b_dest_field, /* destination field */
157 int i_mv_x, int i_mv_y, /* motion vector coordinates,
159 int i_l_stride, /* number of coeffs to jump to
160 * go to the next predicted
163 int i_height, /* height of the block to
164 * predict, in luminance
166 int i_offset, /* position of the first
167 * predicted line (explicit) */
168 boolean_t b_average /* (explicit) averaging of
169 * several predictions */ )
171 /* Temporary variables to avoid recalculating things twice */
172 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
174 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
175 + (p_mb->i_motion_l_y + i_offset
178 * p_mb->p_picture->i_width;
179 if( i_source_offset >= p_source->i_width * p_source->i_height )
181 intf_ErrMsg( "vdec error: bad motion vector\n" );
186 MotionComponent( /* source */
187 p_source->p_y + i_source_offset,
191 + (p_mb->i_motion_l_y + b_dest_field)
192 * p_mb->p_picture->i_width,
193 /* prediction width and height */
196 i_l_stride, p_mb->i_l_stride,
198 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
201 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
202 + ((p_mb->i_motion_c_y + (i_offset >> 1)
205 * p_mb->p_picture->i_chroma_width;
206 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
208 intf_ErrMsg( "vdec error: bad motion vector\n" );
212 i_dest_offset = (p_mb->i_c_x)
213 + (p_mb->i_motion_c_y + b_dest_field)
214 * p_mb->p_picture->i_chroma_width;
215 i_c_height = i_height >> 1;
216 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
219 MotionComponent( p_source->p_u
223 8, i_c_height, i_c_stride, p_mb->i_c_stride,
224 i_c_select, b_average );
227 MotionComponent( p_source->p_v
231 8, i_c_height, i_c_stride, p_mb->i_c_stride,
232 i_c_select, b_average );
235 /*****************************************************************************
236 * Motion422 : motion compensation for a 4:2:2 macroblock
237 *****************************************************************************/
238 static __inline__ void Motion422(
239 macroblock_t * p_mb, /* destination macroblock */
240 picture_t * p_source, /* source picture */
241 boolean_t b_source_field, /* source field */
242 boolean_t b_dest_field, /* destination field */
243 int i_mv_x, int i_mv_y, /* motion vector coordinates,
245 int i_l_stride, /* number of coeffs to jump to
246 * go to the next predicted
249 int i_height, /* height of the block to
250 * predict, in luminance
252 int i_offset, /* position of the first
253 * predicted line (explicit) */
254 boolean_t b_average /* (explicit) averaging of
255 * several predictions */ )
258 int i_source_offset, i_dest_offset, i_c_select;
261 MotionComponent( /* source */
263 + (p_mb->i_l_x + (i_mv_x >> 1))
264 + (p_mb->i_motion_l_y + i_offset
267 * p_mb->p_picture->i_width,
271 + (p_mb->i_motion_l_y + b_dest_field)
272 * p_mb->p_picture->i_width,
273 /* prediction width and height */
276 i_l_stride, p_mb->i_l_stride,
278 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
281 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
282 + ((p_mb->i_motion_c_y + (i_offset)
285 * p_mb->p_picture->i_chroma_width;
286 i_dest_offset = (p_mb->i_c_x)
287 + (p_mb->i_motion_c_y + b_dest_field)
288 * p_mb->p_picture->i_chroma_width;
289 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
292 MotionComponent( p_source->p_u
296 8, i_height, i_c_stride, p_mb->i_c_stride,
297 i_c_select, b_average );
300 MotionComponent( p_source->p_v
304 8, i_height, i_c_stride, p_mb->i_c_stride,
305 i_c_select, b_average );
309 /*****************************************************************************
310 * Motion444 : motion compensation for a 4:4:4 macroblock
311 *****************************************************************************/
312 static __inline__ void Motion444(
313 macroblock_t * p_mb, /* destination macroblock */
314 picture_t * p_source, /* source picture */
315 boolean_t b_source_field, /* source field */
316 boolean_t b_dest_field, /* destination field */
317 int i_mv_x, int i_mv_y, /* motion vector coordinates,
319 int i_l_stride, /* number of coeffs to jump to
320 * go to the next predicted
323 int i_height, /* height of the block to
324 * predict, in luminance
326 int i_offset, /* position of the first
327 * predicted line (explicit) */
328 boolean_t b_average /* (explicit) averaging of
329 * several predictions */ )
332 int i_source_offset, i_dest_offset, i_select;
334 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
335 + (p_mb->i_motion_l_y + i_offset
338 * p_mb->p_picture->i_width;
339 i_dest_offset = (p_mb->i_l_x)
340 + (p_mb->i_motion_l_y + b_dest_field)
341 * p_mb->p_picture->i_width;
342 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
346 MotionComponent( p_source->p_y
350 16, i_height, i_l_stride, p_mb->i_l_stride,
351 i_select, b_average );
354 MotionComponent( p_source->p_u
358 16, i_height, i_l_stride, p_mb->i_l_stride,
359 i_select, b_average );
362 MotionComponent( p_source->p_v
366 16, i_height, i_l_stride, p_mb->i_l_stride,
367 i_select, b_average );
371 /*****************************************************************************
372 * vdec_MotionFieldField : motion compensation for field motion type (field)
373 *****************************************************************************/
374 #define FIELDFIELD( MOTION ) \
375 picture_t * p_pred; \
377 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
379 if( p_mb->b_P_second \
380 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
381 p_pred = p_mb->p_picture; \
383 p_pred = p_mb->p_forward; \
385 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
386 p_mb->b_motion_field, \
387 p_mb->pppi_motion_vectors[0][0][0], \
388 p_mb->pppi_motion_vectors[0][0][1], \
389 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
391 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
393 MOTION( p_mb, p_mb->p_backward, \
394 p_mb->ppi_field_select[0][1], \
395 p_mb->b_motion_field, \
396 p_mb->pppi_motion_vectors[0][1][0], \
397 p_mb->pppi_motion_vectors[0][1][1], \
398 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], \
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], \
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], \
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], \
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], \
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], \
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 )