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, \
124 /*****************************************************************************
125 * vdec_MotionComponent : last stage of motion compensation
126 *****************************************************************************/
127 static __inline__ void MotionComponent(
128 yuv_data_t * p_src, /* source block */
129 yuv_data_t * p_dest, /* dest block */
130 int i_width, /* (explicit) width of block */
131 int i_height, /* (explicit) height of block */
132 int i_stride, /* number of coeffs to jump
133 * between each predicted line */
134 int i_step, /* number of coeffs to jump to
135 * go to the next line of the
137 int i_select, /* half-pel vectors */
138 boolean_t b_average /* (explicit) averaging of several
141 ___callTheRightOne (16,16)
142 ___callTheRightOne (16,8)
143 ___callTheRightOne (8,8)
144 ___callTheRightOne (8,4)
146 ___callTheRightOne (8,16)
150 /*****************************************************************************
151 * Motion420 : motion compensation for a 4:2:0 macroblock
152 *****************************************************************************/
153 static __inline__ void Motion420(
154 macroblock_t * p_mb, /* destination macroblock */
155 picture_t * p_source, /* source picture */
156 boolean_t b_source_field, /* source field */
157 boolean_t b_dest_field, /* destination field */
158 int i_mv_x, int i_mv_y, /* motion vector coordinates,
160 int i_l_stride, /* number of coeffs to jump to
161 * go to the next predicted
164 int i_height, /* height of the block to
165 * predict, in luminance
167 int i_offset, /* position of the first
168 * predicted line (explicit) */
169 boolean_t b_average /* (explicit) averaging of
170 * several predictions */ )
172 /* Temporary variables to avoid recalculating things twice */
173 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
175 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
176 + (p_mb->i_motion_l_y + i_offset
179 * p_mb->p_picture->i_width;
180 if( i_source_offset >= p_source->i_width * p_source->i_height )
182 intf_ErrMsg( "vdec error: bad motion vector\n" );
187 MotionComponent( /* source */
188 p_source->p_y + i_source_offset,
192 + (p_mb->i_motion_l_y + b_dest_field)
193 * p_mb->p_picture->i_width,
194 /* prediction width and height */
197 i_l_stride, p_mb->i_l_stride,
199 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
202 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
203 + ((p_mb->i_motion_c_y + (i_offset >> 1)
206 * p_mb->p_picture->i_chroma_width;
207 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
209 intf_ErrMsg( "vdec error: bad motion vector\n" );
213 i_dest_offset = (p_mb->i_c_x)
214 + (p_mb->i_motion_c_y + b_dest_field)
215 * p_mb->p_picture->i_chroma_width;
216 i_c_height = i_height >> 1;
217 i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
220 MotionComponent( p_source->p_u
224 8, i_c_height, i_c_stride, p_mb->i_c_stride,
225 i_c_select, b_average );
228 MotionComponent( p_source->p_v
232 8, i_c_height, i_c_stride, p_mb->i_c_stride,
233 i_c_select, b_average );
236 /*****************************************************************************
237 * Motion422 : motion compensation for a 4:2:2 macroblock
238 *****************************************************************************/
239 static __inline__ void Motion422(
240 macroblock_t * p_mb, /* destination macroblock */
241 picture_t * p_source, /* source picture */
242 boolean_t b_source_field, /* source field */
243 boolean_t b_dest_field, /* destination field */
244 int i_mv_x, int i_mv_y, /* motion vector coordinates,
246 int i_l_stride, /* number of coeffs to jump to
247 * go to the next predicted
250 int i_height, /* height of the block to
251 * predict, in luminance
253 int i_offset, /* position of the first
254 * predicted line (explicit) */
255 boolean_t b_average /* (explicit) averaging of
256 * several predictions */ )
259 int i_source_offset, i_dest_offset, i_c_select;
262 MotionComponent( /* source */
264 + (p_mb->i_l_x + (i_mv_x >> 1))
265 + (p_mb->i_motion_l_y + i_offset
268 * p_mb->p_picture->i_width,
272 + (p_mb->i_motion_l_y + b_dest_field)
273 * p_mb->p_picture->i_width,
274 /* prediction width and height */
277 i_l_stride, p_mb->i_l_stride,
279 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
282 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
283 + ((p_mb->i_motion_c_y + (i_offset)
286 * p_mb->p_picture->i_chroma_width;
287 i_dest_offset = (p_mb->i_c_x)
288 + (p_mb->i_motion_c_y + b_dest_field)
289 * p_mb->p_picture->i_chroma_width;
290 i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
293 MotionComponent( p_source->p_u
297 8, i_height, i_c_stride, p_mb->i_c_stride,
298 i_c_select, b_average );
301 MotionComponent( p_source->p_v
305 8, i_height, i_c_stride, p_mb->i_c_stride,
306 i_c_select, b_average );
310 /*****************************************************************************
311 * Motion444 : motion compensation for a 4:4:4 macroblock
312 *****************************************************************************/
313 static __inline__ void Motion444(
314 macroblock_t * p_mb, /* destination macroblock */
315 picture_t * p_source, /* source picture */
316 boolean_t b_source_field, /* source field */
317 boolean_t b_dest_field, /* destination field */
318 int i_mv_x, int i_mv_y, /* motion vector coordinates,
320 int i_l_stride, /* number of coeffs to jump to
321 * go to the next predicted
324 int i_height, /* height of the block to
325 * predict, in luminance
327 int i_offset, /* position of the first
328 * predicted line (explicit) */
329 boolean_t b_average /* (explicit) averaging of
330 * several predictions */ )
333 int i_source_offset, i_dest_offset, i_select;
335 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
336 + (p_mb->i_motion_l_y + i_offset
339 * p_mb->p_picture->i_width;
340 i_dest_offset = (p_mb->i_l_x)
341 + (p_mb->i_motion_l_y + b_dest_field)
342 * p_mb->p_picture->i_width;
343 i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
347 MotionComponent( p_source->p_y
351 16, i_height, i_l_stride, p_mb->i_l_stride,
352 i_select, b_average );
355 MotionComponent( p_source->p_u
359 16, i_height, i_l_stride, p_mb->i_l_stride,
360 i_select, b_average );
363 MotionComponent( p_source->p_v
367 16, i_height, i_l_stride, p_mb->i_l_stride,
368 i_select, b_average );
372 /*****************************************************************************
373 * vdec_MotionFieldField : motion compensation for field motion type (field)
374 *****************************************************************************/
375 #define FIELDFIELD( MOTION ) \
376 picture_t * p_pred; \
378 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
380 if( p_mb->b_P_second \
381 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
382 p_pred = p_mb->p_picture; \
384 p_pred = p_mb->p_forward; \
386 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
387 p_mb->b_motion_field, \
388 p_mb->pppi_motion_vectors[0][0][0], \
389 p_mb->pppi_motion_vectors[0][0][1], \
390 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
392 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
394 MOTION( p_mb, p_mb->p_backward, \
395 p_mb->ppi_field_select[0][1], \
396 p_mb->b_motion_field, \
397 p_mb->pppi_motion_vectors[0][1][0], \
398 p_mb->pppi_motion_vectors[0][1][1], \
399 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
402 else /* MB_MOTION_BACKWARD */ \
404 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
405 p_mb->b_motion_field, \
406 p_mb->pppi_motion_vectors[0][1][0], \
407 p_mb->pppi_motion_vectors[0][1][1], \
408 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
412 void vdec_MotionFieldField420( macroblock_t * p_mb )
414 FIELDFIELD( Motion420 )
417 void vdec_MotionFieldField422( macroblock_t * p_mb )
419 //FIELDFIELD( Motion422 )
422 void vdec_MotionFieldField444( macroblock_t * p_mb )
424 //FIELDFIELD( Motion444 )
427 /*****************************************************************************
428 * vdec_MotionField16x8XXX?? : motion compensation for 16x8 motion type (field)
429 *****************************************************************************/
430 #define FIELD16X8( MOTION ) \
432 picture_t * p_pred; \
434 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
436 if( p_mb->b_P_second \
437 && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
438 p_pred = p_mb->p_picture; \
440 p_pred = p_mb->p_forward; \
442 MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0], \
443 p_mb->b_motion_field, \
444 p_mb->pppi_motion_vectors[0][0][0], \
445 p_mb->pppi_motion_vectors[0][0][1], \
446 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
448 if( p_mb->b_P_second \
449 && (p_mb->b_motion_field != p_mb->ppi_field_select[1][0]) )\
450 p_pred = p_mb->p_picture; \
452 p_pred = p_mb->p_forward; \
454 MOTION( p_mb, p_pred, p_mb->ppi_field_select[1][0], \
455 p_mb->b_motion_field, \
456 p_mb->pppi_motion_vectors[1][0][0], \
457 p_mb->pppi_motion_vectors[1][0][1], \
458 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
460 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
462 MOTION( p_mb, p_mb->p_backward, \
463 p_mb->ppi_field_select[0][1], \
464 p_mb->b_motion_field, \
465 p_mb->pppi_motion_vectors[0][1][0], \
466 p_mb->pppi_motion_vectors[0][1][1], \
467 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 1 ); \
469 MOTION( p_mb, p_mb->p_backward, \
470 p_mb->ppi_field_select[1][1], \
471 p_mb->b_motion_field, \
472 p_mb->pppi_motion_vectors[1][1][0], \
473 p_mb->pppi_motion_vectors[1][1][1], \
474 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 1 ); \
478 else /* MB_MOTION_BACKWARD */ \
480 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], \
481 p_mb->b_motion_field, \
482 p_mb->pppi_motion_vectors[0][1][0], \
483 p_mb->pppi_motion_vectors[0][1][1], \
484 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 ); \
486 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], \
487 p_mb->b_motion_field, \
488 p_mb->pppi_motion_vectors[1][1][0], \
489 p_mb->pppi_motion_vectors[1][1][1], \
490 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 ); \
494 void vdec_MotionField16x8420( macroblock_t * p_mb )
496 FIELD16X8( Motion420 )
499 void vdec_MotionField16x8422( macroblock_t * p_mb )
501 //FIELD16X8( Motion422 )
504 void vdec_MotionField16x8444( macroblock_t * p_mb )
506 //FIELD16X8( Motion444 )
509 /*****************************************************************************
510 * vdec_MotionFieldDMVXXX?? : motion compensation for dmv motion type (field)
511 *****************************************************************************/
512 #define FIELDDMV( MOTION ) \
514 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
516 picture_t * p_pred; \
518 /* predict from field of same parity */ \
519 MOTION( p_mb, p_mb->p_forward, \
520 p_mb->b_motion_field, p_mb->b_motion_field, \
521 p_mb->pppi_motion_vectors[0][0][0], \
522 p_mb->pppi_motion_vectors[0][0][1], \
523 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
525 if( p_mb->b_P_second ) \
526 p_pred = p_mb->p_picture; \
528 p_pred = p_mb->p_forward; \
530 /* predict from field of opposite parity */ \
531 MOTION( p_mb, p_pred, !p_mb->b_motion_field, p_mb->b_motion_field, \
532 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
533 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
536 void vdec_MotionFieldDMV420( macroblock_t * p_mb )
538 FIELDDMV( Motion420 )
541 void vdec_MotionFieldDMV422( macroblock_t * p_mb )
543 //FIELDDMV( Motion422 )
546 void vdec_MotionFieldDMV444( macroblock_t * p_mb )
548 //FIELDDMV( Motion444 )
551 /*****************************************************************************
552 * vdec_MotionFrameFrameXXX?? : motion compensation for frame motion type (frame)
553 *****************************************************************************/
554 #define FRAMEFRAME( MOTION ) \
556 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
558 MOTION( p_mb, p_mb->p_forward, 0, 0, \
559 p_mb->pppi_motion_vectors[0][0][0], \
560 p_mb->pppi_motion_vectors[0][0][1], \
561 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
563 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
565 MOTION( p_mb, p_mb->p_backward, 0, 0, \
566 p_mb->pppi_motion_vectors[0][1][0], \
567 p_mb->pppi_motion_vectors[0][1][1], \
568 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 ); \
572 else /* MB_MOTION_BACKWARD */ \
574 MOTION( p_mb, p_mb->p_backward, 0, 0, \
575 p_mb->pppi_motion_vectors[0][1][0], \
576 p_mb->pppi_motion_vectors[0][1][1], \
577 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 ); \
581 void vdec_MotionFrameFrame420( macroblock_t * p_mb )
583 FRAMEFRAME( Motion420 )
586 void vdec_MotionFrameFrame422( macroblock_t * p_mb )
588 //FRAMEFRAME( Motion422 )
591 void vdec_MotionFrameFrame444( macroblock_t * p_mb )
593 //FRAMEFRAME( Motion444 )
596 /*****************************************************************************
597 * vdec_MotionFrameFieldXXX?? : motion compensation for field motion type (frame)
598 *****************************************************************************/
599 #define FRAMEFIELD( MOTION ) \
601 int i_l_stride = p_mb->i_l_stride << 1; \
602 int i_c_stride = p_mb->i_c_stride << 1; \
604 if( p_mb->i_mb_type & MB_MOTION_FORWARD ) \
606 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[0][0], 0, \
607 p_mb->pppi_motion_vectors[0][0][0], \
608 p_mb->pppi_motion_vectors[0][0][1], \
609 i_l_stride, i_c_stride, 8, 0, 0 ); \
611 MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[1][0], 1, \
612 p_mb->pppi_motion_vectors[1][0][0], \
613 p_mb->pppi_motion_vectors[1][0][1], \
614 i_l_stride, i_c_stride, 8, 0, 0 ); \
616 if( p_mb->i_mb_type & MB_MOTION_BACKWARD ) \
618 MOTION( p_mb, p_mb->p_backward, \
619 p_mb->ppi_field_select[0][1], 0, \
620 p_mb->pppi_motion_vectors[0][1][0], \
621 p_mb->pppi_motion_vectors[0][1][1], \
622 i_l_stride, i_c_stride, 8, 0, 1 ); \
624 MOTION( p_mb, p_mb->p_backward, \
625 p_mb->ppi_field_select[1][1], 1, \
626 p_mb->pppi_motion_vectors[1][1][0], \
627 p_mb->pppi_motion_vectors[1][1][1], \
628 i_l_stride, i_c_stride, 8, 0, 1 ); \
632 else /* MB_MOTION_BACKWARD only */ \
634 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], 0,\
635 p_mb->pppi_motion_vectors[0][1][0], \
636 p_mb->pppi_motion_vectors[0][1][1], \
637 i_l_stride, i_c_stride, 8, 0, 0 ); \
639 MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1], 1,\
640 p_mb->pppi_motion_vectors[1][1][0], \
641 p_mb->pppi_motion_vectors[1][1][1], \
642 i_l_stride, i_c_stride, 8, 0, 0 ); \
646 void vdec_MotionFrameField420( macroblock_t * p_mb )
648 FRAMEFIELD( Motion420 )
651 void vdec_MotionFrameField422( macroblock_t * p_mb )
653 //FRAMEFIELD( Motion422 )
656 void vdec_MotionFrameField444( macroblock_t * p_mb )
658 //FRAMEFIELD( Motion444 )
661 /*****************************************************************************
662 * vdec_MotionFrameDMVXXX?? : motion compensation for dmv motion type (frame)
663 *****************************************************************************/
664 #define FRAMEDMV( MOTION ) \
666 /* This is necessarily a MOTION_FORWARD only macroblock, in a P \
669 /* predict top field from top field */ \
670 MOTION( p_mb, p_mb->p_forward, 0, 0, \
671 p_mb->pppi_motion_vectors[0][0][0], \
672 p_mb->pppi_motion_vectors[0][0][1], \
673 /* XXX?? XXX?? >> 1 ? */ \
674 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
676 /* predict and add to top field from bottom field */ \
677 MOTION( p_mb, p_mb->p_forward, 1, 0, \
678 p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1], \
679 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
681 /* predict bottom field from bottom field */ \
682 MOTION( p_mb, p_mb->p_forward, 1, 1, \
683 p_mb->pppi_motion_vectors[0][0][0], \
684 p_mb->pppi_motion_vectors[0][0][1], \
685 /* XXX?? XXX?? >> 1 ? */ \
686 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 ); \
688 /* predict and add to bottom field from top field */ \
689 MOTION( p_mb, p_mb->p_forward, 1, 0, \
690 p_mb->ppi_dmv[1][0], p_mb->ppi_dmv[1][1], \
691 p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 ); \
694 void vdec_MotionFrameDMV420( macroblock_t * p_mb )
696 FRAMEDMV( Motion420 )
699 void vdec_MotionFrameDMV422( macroblock_t * p_mb )
701 //FRAMEDMV( Motion422 )
704 void vdec_MotionFrameDMV444( macroblock_t * p_mb )
706 //FRAMEDMV( Motion444 )