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 */
41 #include "stream_control.h"
42 #include "input_ext-dec.h"
45 #include "video_output.h"
47 #include "vdec_idct.h"
48 #include "video_decoder.h"
49 #include "vdec_motion.h"
51 #include "vpar_blocks.h"
52 #include "vpar_headers.h"
53 #include "vpar_synchro.h"
54 #include "video_parser.h"
55 #include "video_fifo.h"
57 #define __MotionComponents(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_copy_##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 (); \
65 void MotionComponent_X_Y_avg_##width##_##height ();
67 __MotionComponents (16,16) /* 444, 422, 420 */
68 __MotionComponents (16,8) /* 444, 422, 420 */
69 __MotionComponents (8,8) /* 422, 420 */
70 __MotionComponents (8,4) /* 420 */
72 __MotionComponents (8,16) /* 422 */
75 #define ___callTheRightOne(width,height) \
76 if ((i_width == width) && (i_height == height)) \
83 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest, \
87 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest, \
91 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest, \
95 MotionComponent_X_Y_copy_##width##_##height (p_src, p_dest, \
105 MotionComponent_x_y_avg_##width##_##height (p_src, p_dest, \
109 MotionComponent_X_y_avg_##width##_##height (p_src, p_dest, \
113 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_select, /* half-pel vectors */
135 boolean_t b_average /* (explicit) averaging of several
138 ___callTheRightOne (16,16)
139 ___callTheRightOne (16,8)
140 ___callTheRightOne (8,8)
141 ___callTheRightOne (8,4)
143 ___callTheRightOne (8,16)
147 /*****************************************************************************
148 * Motion420 : motion compensation for a 4:2:0 macroblock
149 *****************************************************************************/
150 static __inline__ void Motion420(
151 macroblock_t * p_mb, /* destination macroblock */
152 picture_t * p_source, /* source picture */
153 boolean_t b_source_field, /* source field */
154 boolean_t b_dest_field, /* destination field */
155 int i_mv_x, int i_mv_y, /* motion vector coordinates,
157 int i_l_stride, /* number of coeffs to jump to
158 * go to the next predicted
161 int i_height, /* height of the block to
162 * predict, in luminance
164 int i_offset, /* position of the first
165 * predicted line (explicit) */
166 boolean_t b_average /* (explicit) averaging of
167 * several predictions */ )
169 /* Temporary variables to avoid recalculating things twice */
170 int i_source_offset, i_dest_offset, i_c_height, i_c_select;
172 i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
173 + (p_mb->i_motion_l_y + i_offset
175 * p_mb->p_picture->i_width
176 + (i_mv_y >> 1) * i_l_stride;
177 if( i_source_offset >= p_source->i_width * p_source->i_height )
179 intf_ErrMsg( "vdec error: bad motion vector (lum)\n" );
184 MotionComponent( /* source */
185 p_source->p_y + i_source_offset,
189 + (p_mb->i_motion_l_y + b_dest_field + i_offset)
190 * p_mb->p_picture->i_width,
191 /* prediction width and height */
196 ((i_mv_y & 1) << 1) | (i_mv_x & 1),
199 i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
200 + (p_mb->i_motion_c_y + (i_offset >> 1)
202 * p_mb->p_picture->i_chroma_width
203 + ((i_mv_y/2) >> 1) * i_c_stride;
204 if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
206 intf_ErrMsg( "vdec error: bad motion vector (chroma)\n" );
210 i_dest_offset = (p_mb->i_c_x)
211 + (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,
223 i_c_select, b_average );
226 MotionComponent( p_source->p_v
230 8, i_c_height, 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
265 * p_mb->p_picture->i_width
266 + (i_mv_y >> 1) * p_mb->i_l_stride,
270 + (p_mb->i_motion_l_y + b_dest_field)
271 * p_mb->p_picture->i_width,
272 /* prediction width and height */
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
283 * p_mb->p_picture->i_chroma_width
284 + (i_mv_y) >> 1) * p_mb->i_c_stride;
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,
296 i_c_select, b_average );
299 MotionComponent( p_source->p_v
303 8, i_height, 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
336 * p_mb->p_picture->i_width
337 + (i_mv_y >> 1) * p_mb->i_l_stride;
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,
350 i_select, b_average );
353 MotionComponent( p_source->p_u
357 16, i_height, i_l_stride,
358 i_select, b_average );
361 MotionComponent( p_source->p_v
365 16, i_height, i_l_stride,
366 i_select, b_average );
370 /*****************************************************************************
371 * vdec_MotionFieldField : motion compensation for field motion type (field)
372 *****************************************************************************/
373 #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 ); \
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] >> 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] >> 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] >> 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] >> 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] >> 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] >> 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 )