]> git.sesse.net Git - vlc/blob - src/video_decoder/vdec_motion.c
14c7a2b1eaeb814977e0ffec6a91ebaec20a89cb
[vlc] / src / video_decoder / vdec_motion.c
1 /*****************************************************************************
2  * vdec_motion.c : motion compensation routines
3  * (c)1999 VideoLAN
4  *****************************************************************************/
5
6 /*****************************************************************************
7  * Preamble
8  *****************************************************************************/
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <sys/uio.h>
15
16 #include "config.h"
17 #include "common.h"
18 #include "mtime.h"
19 #include "vlc_thread.h"
20
21 #include "intf_msg.h"
22 #include "debug.h"                 /* XXX?? temporaire, requis par netlist.h */
23
24 #include "input.h"
25 #include "input_netlist.h"
26 #include "decoder_fifo.h"
27 #include "video.h"
28 #include "video_output.h"
29
30 #include "vdec_idct.h"
31 #include "video_decoder.h"
32 #include "vdec_motion.h"
33
34 #include "vpar_blocks.h"
35 #include "vpar_headers.h"
36 #include "vpar_synchro.h"
37 #include "video_parser.h"
38 #include "video_fifo.h"
39
40 #define __MotionComponents(width,height)                \
41 void MotionComponent_x_y_copy_##width##_##height ();    \
42 void MotionComponent_X_y_copy_##width##_##height ();    \
43 void MotionComponent_x_Y_copy_##width##_##height ();    \
44 void MotionComponent_X_Y_copy_##width##_##height ();    \
45 void MotionComponent_x_y_avg_##width##_##height ();     \
46 void MotionComponent_X_y_avg_##width##_##height ();     \
47 void MotionComponent_x_Y_avg_##width##_##height ();     \
48 void MotionComponent_X_Y_avg_##width##_##height ();
49
50 __MotionComponents (16,16)      /* 444, 422, 420 */
51 __MotionComponents (16,8)       /* 444, 422, 420 */
52 __MotionComponents (8,8)        /* 422, 420 */
53 __MotionComponents (8,4)        /* 420 */
54 #if 0
55 __MotionComponents (8,16)       /* 422 */
56 #endif
57
58 #define ___callTheRightOne(width,height)                                     \
59     if ((i_width == width) && (i_height == height))                          \
60     {                                                                        \
61         if (!b_average)                                                      \
62         {                                                                    \
63             switch (i_select)                                                \
64             {                                                                \
65             case 0:                                                          \
66                 MotionComponent_x_y_copy_##width##_##height (p_src, p_dest,  \
67                                                              i_stride);      \
68                 break;                                                       \
69             case 1:                                                          \
70                 MotionComponent_X_y_copy_##width##_##height (p_src, p_dest,  \
71                                                              i_stride);      \
72                 break;                                                       \
73             case 2:                                                          \
74                 MotionComponent_x_Y_copy_##width##_##height (p_src, p_dest,  \
75                                                              i_stride,       \
76                                                              i_step);        \
77                 break;                                                       \
78             case 3:                                                          \
79                 MotionComponent_X_Y_copy_##width##_##height (p_src, p_dest,  \
80                                                              i_stride,       \
81                                                              i_step);        \
82                 break;                                                       \
83             }                                                                \
84         }                                                                    \
85         else                                                                 \
86         {                                                                    \
87             switch (i_select)                                                \
88             {                                                                \
89             case 0:                                                          \
90                 MotionComponent_x_y_avg_##width##_##height (p_src, p_dest,   \
91                                                             i_stride);       \
92                 break;                                                       \
93             case 1:                                                          \
94                 MotionComponent_X_y_avg_##width##_##height (p_src, p_dest,   \
95                                                             i_stride);       \
96                 break;                                                       \
97             case 2:                                                          \
98                 MotionComponent_x_Y_avg_##width##_##height (p_src, p_dest,   \
99                                                             i_stride,        \
100                                                             i_step);         \
101                 break;                                                       \
102             case 3:                                                          \
103                 MotionComponent_X_Y_avg_##width##_##height (p_src, p_dest,   \
104                                                             i_stride,        \
105                                                             i_step);         \
106                 break;                                                       \
107             }                                                                \
108         }                                                                    \
109     }
110 /*****************************************************************************
111  * vdec_MotionComponent : last stage of motion compensation
112  *****************************************************************************/
113 static __inline__ void MotionComponent(
114                     yuv_data_t * p_src,     /* source block */
115                     yuv_data_t * p_dest,    /* dest block */
116                     int i_width,            /* (explicit) width of block */
117                     int i_height,           /* (explicit) height of block */
118                     int i_stride,           /* number of coeffs to jump
119                                              * between each predicted line */
120                     int i_step,             /* number of coeffs to jump to
121                                              * go to the next line of the
122                                              * field */
123                     int i_select,           /* half-pel vectors */
124                     boolean_t b_average     /* (explicit) averaging of several
125                                              * predictions */ )
126 {
127 ___callTheRightOne (16,16)
128 ___callTheRightOne (16,8)
129 ___callTheRightOne (8,8)
130 ___callTheRightOne (8,4)
131 #if 0
132 ___callTheRightOne (8,16)
133 #endif
134 }
135
136 /*****************************************************************************
137  * Motion420 : motion compensation for a 4:2:0 macroblock
138  *****************************************************************************/
139 static __inline__ void Motion420(
140                     macroblock_t * p_mb,        /* destination macroblock */
141                     picture_t * p_source,       /* source picture */
142                     boolean_t b_source_field,   /* source field */
143                     boolean_t b_dest_field,     /* destination field */
144                     int i_mv_x, int i_mv_y,     /* motion vector coordinates,
145                                                  * in half pels */
146                     int i_l_stride,             /* number of coeffs to jump to
147                                                  * go to the next predicted
148                                                  * line */
149                     int i_c_stride,
150                     int i_height,               /* height of the block to
151                                                  * predict, in luminance
152                                                  * (explicit) */
153                     int i_offset,               /* position of the first
154                                                  * predicted line (explicit) */
155                     boolean_t b_average         /* (explicit) averaging of
156                                                  * several predictions */ )
157 {
158     /* Temporary variables to avoid recalculating things twice */
159     int     i_source_offset, i_dest_offset, i_c_height, i_c_select;
160
161     i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
162                        + (p_mb->i_motion_l_y + i_offset
163                          + (i_mv_y >> 1)
164                          + b_source_field)
165                          * p_mb->p_picture->i_width;
166     if( i_source_offset >= p_source->i_width * p_source->i_height )
167     {
168         fprintf( stderr, "vdec error: bad motion vector\n" );
169         return;
170     }
171
172     /* Luminance */
173     MotionComponent( /* source */
174                      p_source->p_y + i_source_offset,
175                      /* destination */
176                      p_mb->p_picture->p_y
177                        + (p_mb->i_l_x)
178                        + (p_mb->i_motion_l_y + b_dest_field)
179                          * p_mb->p_picture->i_width,
180                      /* prediction width and height */
181                      16, i_height,
182                      /* stride */
183                      i_l_stride, p_mb->i_l_stride,
184                      /* select */
185                      ((i_mv_y & 1) << 1) | (i_mv_x & 1),
186                      b_average );
187
188     i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
189                         + ((p_mb->i_motion_c_y + (i_offset >> 1)
190                            + ((i_mv_y/2) >> 1))
191                            + b_source_field)
192                           * p_mb->p_picture->i_chroma_width;
193     if( i_source_offset >= (p_source->i_width * p_source->i_height) / 4 )
194     {
195         fprintf( stderr, "vdec error: bad motion vector\n" );
196         return;
197     }
198
199     i_dest_offset = (p_mb->i_c_x)
200                       + (p_mb->i_motion_c_y + b_dest_field)
201                         * p_mb->p_picture->i_chroma_width;
202     i_c_height = i_height >> 1;
203     i_c_select = (((i_mv_y/2) & 1) << 1) | ((i_mv_x/2) & 1);
204
205     /* Chrominance Cr */
206     MotionComponent( p_source->p_u
207                        + i_source_offset,
208                      p_mb->p_picture->p_u
209                        + i_dest_offset,
210                      8, i_c_height, i_c_stride, p_mb->i_c_stride,
211                      i_c_select, b_average );
212
213     /* Chrominance Cb */
214     MotionComponent( p_source->p_v
215                        + i_source_offset,
216                      p_mb->p_picture->p_v
217                        + i_dest_offset,
218                      8, i_c_height, i_c_stride, p_mb->i_c_stride,
219                      i_c_select, b_average );
220 }
221
222 /*****************************************************************************
223  * Motion422 : motion compensation for a 4:2:2 macroblock
224  *****************************************************************************/
225 static __inline__ void Motion422(
226                     macroblock_t * p_mb,        /* destination macroblock */
227                     picture_t * p_source,       /* source picture */
228                     boolean_t b_source_field,   /* source field */
229                     boolean_t b_dest_field,     /* destination field */
230                     int i_mv_x, int i_mv_y,     /* motion vector coordinates,
231                                                  * in half pels */
232                     int i_l_stride,             /* number of coeffs to jump to
233                                                  * go to the next predicted
234                                                  * line */
235                     int i_c_stride,
236                     int i_height,               /* height of the block to
237                                                  * predict, in luminance
238                                                  * (explicit) */
239                     int i_offset,               /* position of the first
240                                                  * predicted line (explicit) */
241                     boolean_t b_average         /* (explicit) averaging of
242                                                  * several predictions */ )
243 {
244 #if 0
245     int     i_source_offset, i_dest_offset, i_c_select;
246
247     /* Luminance */
248     MotionComponent( /* source */
249                      p_source->p_y
250                        + (p_mb->i_l_x + (i_mv_x >> 1))
251                        + (p_mb->i_motion_l_y + i_offset
252                           + (i_mv_y >> 1)
253                           + b_source_field)
254                          * p_mb->p_picture->i_width,
255                      /* destination */
256                      p_mb->p_picture->p_y
257                        + (p_mb->i_l_x)
258                        + (p_mb->i_motion_l_y + b_dest_field)
259                          * p_mb->p_picture->i_width,
260                      /* prediction width and height */
261                      16, i_height,
262                      /* stride */
263                      i_l_stride, p_mb->i_l_stride,
264                      /* select */
265                      ((i_mv_y & 1) << 1) | (i_mv_x & 1),
266                      b_average );
267
268     i_source_offset = (p_mb->i_c_x + ((i_mv_x/2) >> 1))
269                         + ((p_mb->i_motion_c_y + (i_offset)
270                            + ((i_mv_y) >> 1))
271                            + b_source_field)
272                           * p_mb->p_picture->i_chroma_width;
273     i_dest_offset = (p_mb->i_c_x)
274                       + (p_mb->i_motion_c_y + b_dest_field)
275                         * p_mb->p_picture->i_chroma_width;
276     i_c_select = ((i_mv_y & 1) << 1) | ((i_mv_x/2) & 1);
277
278     /* Chrominance Cr */
279     MotionComponent( p_source->p_u
280                        + i_source_offset,
281                      p_mb->p_picture->p_u
282                        + i_dest_offset,
283                      8, i_height, i_c_stride, p_mb->i_c_stride,
284                      i_c_select, b_average );
285
286     /* Chrominance Cb */
287     MotionComponent( p_source->p_v
288                        + i_source_offset,
289                      p_mb->p_picture->p_u
290                        + i_dest_offset,
291                      8, i_height, i_c_stride, p_mb->i_c_stride,
292                      i_c_select, b_average );
293 #endif
294 }
295
296 /*****************************************************************************
297  * Motion444 : motion compensation for a 4:4:4 macroblock
298  *****************************************************************************/
299 static __inline__ void Motion444(
300                     macroblock_t * p_mb,        /* destination macroblock */
301                     picture_t * p_source,       /* source picture */
302                     boolean_t b_source_field,   /* source field */
303                     boolean_t b_dest_field,     /* destination field */
304                     int i_mv_x, int i_mv_y,     /* motion vector coordinates,
305                                                  * in half pels */
306                     int i_l_stride,             /* number of coeffs to jump to
307                                                  * go to the next predicted
308                                                  * line */
309                     int i_c_stride,
310                     int i_height,               /* height of the block to
311                                                  * predict, in luminance
312                                                  * (explicit) */
313                     int i_offset,               /* position of the first
314                                                  * predicted line (explicit) */
315                     boolean_t b_average         /* (explicit) averaging of
316                                                  * several predictions */ )
317 {
318 #if 0
319     int     i_source_offset, i_dest_offset, i_select;
320
321     i_source_offset = (p_mb->i_l_x + (i_mv_x >> 1))
322                         + (p_mb->i_motion_l_y + i_offset
323                            + (i_mv_y >> 1)
324                            + b_source_field)
325                           * p_mb->p_picture->i_width;
326     i_dest_offset = (p_mb->i_l_x)
327                       + (p_mb->i_motion_l_y + b_dest_field)
328                         * p_mb->p_picture->i_width;
329     i_select = ((i_mv_y & 1) << 1) | (i_mv_x & 1);
330
331
332     /* Luminance */
333     MotionComponent( p_source->p_y
334                        + i_source_offset,
335                      p_mb->p_picture->p_y
336                        + i_dest_offset,
337                      16, i_height, i_l_stride, p_mb->i_l_stride,
338                      i_select, b_average );
339
340     /* Chrominance Cr */
341     MotionComponent( p_source->p_u
342                        + i_source_offset,
343                      p_mb->p_picture->p_u
344                        + i_dest_offset,
345                      16, i_height, i_l_stride, p_mb->i_l_stride,
346                      i_select, b_average );
347
348     /* Chrominance Cb */
349     MotionComponent( p_source->p_v
350                        + i_source_offset,
351                      p_mb->p_picture->p_v
352                        + i_dest_offset,
353                      16, i_height, i_l_stride, p_mb->i_l_stride,
354                      i_select, b_average );
355 #endif
356 }
357
358 /*****************************************************************************
359  * vdec_MotionFieldField : motion compensation for field motion type (field)
360  *****************************************************************************/
361 #define FIELDFIELD( MOTION )                                            \
362     picture_t *     p_pred;                                             \
363                                                                         \
364     if( p_mb->i_mb_type & MB_MOTION_FORWARD )                           \
365     {                                                                   \
366         if( p_mb->b_P_second                                            \
367              && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
368             p_pred = p_mb->p_picture;                                   \
369         else                                                            \
370             p_pred = p_mb->p_forward;                                   \
371                                                                         \
372         MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0],             \
373                 p_mb->b_motion_field,                                   \
374                 p_mb->pppi_motion_vectors[0][0][0],                     \
375                 p_mb->pppi_motion_vectors[0][0][1],                     \
376                 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 );         \
377                                                                         \
378         if( p_mb->i_mb_type & MB_MOTION_BACKWARD )                      \
379         {                                                               \
380             MOTION( p_mb, p_mb->p_backward,                             \
381                     p_mb->ppi_field_select[0][1],                       \
382                     p_mb->b_motion_field,                               \
383                     p_mb->pppi_motion_vectors[0][1][0],                 \
384                     p_mb->pppi_motion_vectors[0][1][1],                 \
385                     p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 );     \
386     }                                                                   \
387                                                                         \
388     else /* MB_MOTION_BACKWARD */                                       \
389     {                                                                   \
390         MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1],   \
391                 p_mb->b_motion_field,                                   \
392                 p_mb->pppi_motion_vectors[0][1][0],                     \
393                 p_mb->pppi_motion_vectors[0][1][1],                     \
394                 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 );         \
395     }                                                                   \
396 }
397
398 void vdec_MotionFieldField420( macroblock_t * p_mb )
399 {
400     FIELDFIELD( Motion420 )
401 }
402
403 void vdec_MotionFieldField422( macroblock_t * p_mb )
404 {
405     //FIELDFIELD( Motion422 )
406 }
407
408 void vdec_MotionFieldField444( macroblock_t * p_mb )
409 {
410     //FIELDFIELD( Motion444 )
411 }
412
413 /*****************************************************************************
414  * vdec_MotionField16x8XXX?? : motion compensation for 16x8 motion type (field)
415  *****************************************************************************/
416 #define FIELD16X8( MOTION )                                             \
417 {                                                                       \
418     picture_t *     p_pred;                                             \
419                                                                         \
420     if( p_mb->i_mb_type & MB_MOTION_FORWARD )                           \
421     {                                                                   \
422         if( p_mb->b_P_second                                            \
423              && (p_mb->b_motion_field != p_mb->ppi_field_select[0][0]) )\
424             p_pred = p_mb->p_picture;                                   \
425         else                                                            \
426             p_pred = p_mb->p_forward;                                   \
427                                                                         \
428         MOTION( p_mb, p_pred, p_mb->ppi_field_select[0][0],             \
429                 p_mb->b_motion_field,                                   \
430                 p_mb->pppi_motion_vectors[0][0][0],                     \
431                 p_mb->pppi_motion_vectors[0][0][1],                     \
432                 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 );          \
433                                                                         \
434         if( p_mb->b_P_second                                            \
435              && (p_mb->b_motion_field != p_mb->ppi_field_select[1][0]) )\
436             p_pred = p_mb->p_picture;                                   \
437         else                                                            \
438             p_pred = p_mb->p_forward;                                   \
439                                                                         \
440         MOTION( p_mb, p_pred, p_mb->ppi_field_select[1][0],             \
441                 p_mb->b_motion_field,                                   \
442                 p_mb->pppi_motion_vectors[1][0][0],                     \
443                 p_mb->pppi_motion_vectors[1][0][1],                     \
444                 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 );          \
445                                                                         \
446         if( p_mb->i_mb_type & MB_MOTION_BACKWARD )                      \
447         {                                                               \
448             MOTION( p_mb, p_mb->p_backward,                             \
449                     p_mb->ppi_field_select[0][1],                       \
450                     p_mb->b_motion_field,                               \
451                     p_mb->pppi_motion_vectors[0][1][0],                 \
452                     p_mb->pppi_motion_vectors[0][1][1],                 \
453                     p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 1 );      \
454                                                                         \
455             MOTION( p_mb, p_mb->p_backward,                             \
456                     p_mb->ppi_field_select[1][1],                       \
457                     p_mb->b_motion_field,                               \
458                     p_mb->pppi_motion_vectors[1][1][0],                 \
459                     p_mb->pppi_motion_vectors[1][1][1],                 \
460                     p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 1 );      \
461         }                                                               \
462     }                                                                   \
463                                                                         \
464     else /* MB_MOTION_BACKWARD */                                       \
465     {                                                                   \
466         MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1],   \
467                 p_mb->b_motion_field,                                   \
468                 p_mb->pppi_motion_vectors[0][1][0],                     \
469                 p_mb->pppi_motion_vectors[0][1][1],                     \
470                 p_mb->i_l_stride, p_mb->i_c_stride, 8, 0, 0 );          \
471                                                                         \
472         MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[1][1],   \
473                 p_mb->b_motion_field,                                   \
474                 p_mb->pppi_motion_vectors[1][1][0],                     \
475                 p_mb->pppi_motion_vectors[1][1][1],                     \
476                 p_mb->i_l_stride, p_mb->i_c_stride, 8, 8, 0 );          \
477     }                                                                   \
478 }
479
480 void vdec_MotionField16x8420( macroblock_t * p_mb )
481 {
482     FIELD16X8( Motion420 )
483 }
484
485 void vdec_MotionField16x8422( macroblock_t * p_mb )
486 {
487     //FIELD16X8( Motion422 )
488 }
489
490 void vdec_MotionField16x8444( macroblock_t * p_mb )
491 {
492     //FIELD16X8( Motion444 )
493 }
494
495 /*****************************************************************************
496  * vdec_MotionFieldDMVXXX?? : motion compensation for dmv motion type (field)
497  *****************************************************************************/
498 #define FIELDDMV( MOTION )                                              \
499 {                                                                       \
500     /* This is necessarily a MOTION_FORWARD only macroblock, in a P     \
501      * picture. */                                                      \
502     picture_t *     p_pred;                                             \
503                                                                         \
504     /* predict from field of same parity */                             \
505     MOTION( p_mb, p_mb->p_forward,                                      \
506             p_mb->b_motion_field, p_mb->b_motion_field,                 \
507             p_mb->pppi_motion_vectors[0][0][0],                         \
508             p_mb->pppi_motion_vectors[0][0][1],                         \
509             p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 );             \
510                                                                         \
511     if( p_mb->b_P_second )                                              \
512         p_pred = p_mb->p_picture;                                       \
513     else                                                                \
514         p_pred = p_mb->p_forward;                                       \
515                                                                         \
516     /* predict from field of opposite parity */                         \
517     MOTION( p_mb, p_pred, !p_mb->b_motion_field, p_mb->b_motion_field,  \
518             p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1],                   \
519             p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 );             \
520 } /* FIELDDMV */
521
522 void vdec_MotionFieldDMV420( macroblock_t * p_mb )
523 {
524     FIELDDMV( Motion420 )
525 }
526
527 void vdec_MotionFieldDMV422( macroblock_t * p_mb )
528 {
529     //FIELDDMV( Motion422 )
530 }
531
532 void vdec_MotionFieldDMV444( macroblock_t * p_mb )
533 {
534     //FIELDDMV( Motion444 )
535 }
536
537 /*****************************************************************************
538  * vdec_MotionFrameFrameXXX?? : motion compensation for frame motion type (frame)
539  *****************************************************************************/
540 #define FRAMEFRAME( MOTION )                                            \
541 {                                                                       \
542     if( p_mb->i_mb_type & MB_MOTION_FORWARD )                           \
543     {                                                                   \
544         MOTION( p_mb, p_mb->p_forward, 0, 0,                            \
545                 p_mb->pppi_motion_vectors[0][0][0],                     \
546                 p_mb->pppi_motion_vectors[0][0][1],                     \
547                 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 );         \
548                                                                         \
549         if( p_mb->i_mb_type & MB_MOTION_BACKWARD )                      \
550         {                                                               \
551             MOTION( p_mb, p_mb->p_backward, 0, 0,                       \
552                     p_mb->pppi_motion_vectors[0][1][0],                 \
553                     p_mb->pppi_motion_vectors[0][1][1],                 \
554                     p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 1 );     \
555         }                                                               \
556     }                                                                   \
557                                                                         \
558     else /* MB_MOTION_BACKWARD */                                       \
559     {                                                                   \
560         MOTION( p_mb, p_mb->p_backward, 0, 0,                           \
561                 p_mb->pppi_motion_vectors[0][1][0],                     \
562                 p_mb->pppi_motion_vectors[0][1][1],                     \
563                 p_mb->i_l_stride, p_mb->i_c_stride, 16, 0, 0 );         \
564     }                                                                   \
565 } /* FRAMEFRAME */
566
567 void vdec_MotionFrameFrame420( macroblock_t * p_mb )
568 {
569     FRAMEFRAME( Motion420 )
570 }
571
572 void vdec_MotionFrameFrame422( macroblock_t * p_mb )
573 {
574     //FRAMEFRAME( Motion422 )
575 }
576
577 void vdec_MotionFrameFrame444( macroblock_t * p_mb )
578 {
579     //FRAMEFRAME( Motion444 )
580 }
581
582 /*****************************************************************************
583  * vdec_MotionFrameFieldXXX?? : motion compensation for field motion type (frame)
584  *****************************************************************************/
585 #define FRAMEFIELD( MOTION )                                            \
586 {                                                                       \
587     int i_l_stride = p_mb->i_l_stride << 1;                             \
588     int i_c_stride = p_mb->i_c_stride << 1;                             \
589                                                                         \
590     if( p_mb->i_mb_type & MB_MOTION_FORWARD )                           \
591     {                                                                   \
592         MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[0][0], 0, \
593                 p_mb->pppi_motion_vectors[0][0][0],                     \
594                 p_mb->pppi_motion_vectors[0][0][1],                     \
595                 i_l_stride, i_c_stride, 8, 0, 0 );                      \
596                                                                         \
597         MOTION( p_mb, p_mb->p_forward, p_mb->ppi_field_select[1][0], 1, \
598                 p_mb->pppi_motion_vectors[1][0][0],                     \
599                 p_mb->pppi_motion_vectors[1][0][1],                     \
600                 i_l_stride, i_c_stride, 8, 0, 0 );                      \
601                                                                         \
602         if( p_mb->i_mb_type & MB_MOTION_BACKWARD )                      \
603         {                                                               \
604             MOTION( p_mb, p_mb->p_backward,                             \
605                     p_mb->ppi_field_select[0][1], 0,                    \
606                     p_mb->pppi_motion_vectors[0][1][0],                 \
607                     p_mb->pppi_motion_vectors[0][1][1],                 \
608                     i_l_stride, i_c_stride, 8, 0, 1 );                  \
609                                                                         \
610             MOTION( p_mb, p_mb->p_backward,                             \
611                     p_mb->ppi_field_select[1][1], 1,                    \
612                     p_mb->pppi_motion_vectors[1][1][0],                 \
613                     p_mb->pppi_motion_vectors[1][1][1],                 \
614                     i_l_stride, i_c_stride, 8, 0, 1 );                  \
615         }                                                               \
616     }                                                                   \
617                                                                         \
618     else /* MB_MOTION_BACKWARD only */                                  \
619     {                                                                   \
620         MOTION( p_mb, p_mb->p_backward, p_mb->ppi_field_select[0][1], 0,\
621                 p_mb->pppi_motion_vectors[0][1][0],                     \
622                 p_mb->pppi_motion_vectors[0][1][1],                     \
623                 i_l_stride, i_c_stride, 8, 0, 0 );                      \
624                                                                         \
625         MOTION( p_mb, p_mb->p_backward, 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, 0 );                      \
629     }                                                                   \
630 } /* FRAMEFIELD */
631
632 void vdec_MotionFrameField420( macroblock_t * p_mb )
633 {
634     FRAMEFIELD( Motion420 )
635 }
636
637 void vdec_MotionFrameField422( macroblock_t * p_mb )
638 {
639     //FRAMEFIELD( Motion422 )
640 }
641
642 void vdec_MotionFrameField444( macroblock_t * p_mb )
643 {
644     //FRAMEFIELD( Motion444 )
645 }
646
647 /*****************************************************************************
648  * vdec_MotionFrameDMVXXX?? : motion compensation for dmv motion type (frame)
649  *****************************************************************************/
650 #define FRAMEDMV( MOTION )                                              \
651 {                                                                       \
652     /* This is necessarily a MOTION_FORWARD only macroblock, in a P     \
653      * picture. */                                                      \
654                                                                         \
655     /* predict top field from top field */                              \
656     MOTION( p_mb, p_mb->p_forward, 0, 0,                                \
657             p_mb->pppi_motion_vectors[0][0][0],                         \
658             p_mb->pppi_motion_vectors[0][0][1],                         \
659             /* XXX?? XXX?? >> 1 ? */                                        \
660             p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 0 );    \
661                                                                         \
662     /* predict and add to top field from bottom field */                \
663     MOTION( p_mb, p_mb->p_forward, 1, 0,                                \
664             p_mb->ppi_dmv[0][0], p_mb->ppi_dmv[0][1],                   \
665             p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 );    \
666                                                                         \
667     /* predict bottom field from bottom field */                        \
668     MOTION( p_mb, p_mb->p_forward, 1, 1,                                \
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 );    \
673                                                                         \
674     /* predict and add to bottom field from top field */                \
675     MOTION( p_mb, p_mb->p_forward, 1, 0,                                \
676             p_mb->ppi_dmv[1][0], p_mb->ppi_dmv[1][1],                   \
677             p_mb->i_l_stride << 1, p_mb->i_c_stride << 1, 8, 0, 1 );    \
678 } /* FRAMEDMV */
679
680 void vdec_MotionFrameDMV420( macroblock_t * p_mb )
681 {
682     FRAMEDMV( Motion420 )
683 }
684
685 void vdec_MotionFrameDMV422( macroblock_t * p_mb )
686 {
687     //FRAMEDMV( Motion422 )
688 }
689
690 void vdec_MotionFrameDMV444( macroblock_t * p_mb )
691 {
692     //FRAMEDMV( Motion444 )
693 }