2 /**************************************************************************
4 * This code is developed by Adam Li. This software is an *
5 * implementation of a part of one or more MPEG-4 Video tools as *
6 * specified in ISO/IEC 14496-2 standard. Those intending to use this *
7 * software module in hardware or software products are advised that its *
8 * use may infringe existing patents or copyrights, and any such use *
9 * would be at such party's own risk. The original developer of this *
10 * software module and his/her company, and subsequent editors and their *
11 * companies (including Project Mayo), will have no liability for use of *
12 * this software or modifications or derivatives thereof. *
14 * Project Mayo gives users of the Codec a license to this software *
15 * module or modifications thereof for use in hardware or software *
16 * products claiming conformance to the MPEG-4 Video Standard as *
17 * described in the Open DivX license. *
19 * The complete Open DivX license can be found at *
20 * http://www.projectmayo.com/opendivx/license.php . *
22 **************************************************************************/
24 /**************************************************************************
28 * Copyright (C) 2001 Project Mayo
32 * DivX Advance Research Center <darc@projectmayo.com>
34 **************************************************************************/
36 /* This file contains some functions to code the motion data of the image.*/
37 /* Some codes of this project come from MoMuSys MPEG-4 implementation. */
38 /* Please see seperate acknowledgement file for a list of contributors. */
40 #include "vm_common_defs.h"
41 #include "bitstream.h"
45 /* ------------------------------------------------------------------------- */
47 /* Specific macros (include references to internal vars. of the functions) */
49 /* 16x16 MV obtainment */
50 #define MBV_H(h,v) (ph[2*(v)*2*hdim+2*(h)])
51 #define MBV_V(h,v) (pv[2*(v)*2*hdim+2*(h)])
53 /* 8x8 MV obtainment */
54 #define BV_H(h,v,h2,v2) (ph[(2*(v)+(v2))*2*hdim+2*(h)+(h2)])
55 #define BV_V(h,v,h2,v2) (pv[(2*(v)+(v2))*2*hdim+2*(h)+(h2)])
57 /* MB mode obtainment */
58 #define MB_MODE(h,v) ( ((h)<0||(h)>=hdim||(v)<0||(v)>=vdim ? MBM_OUT : (pm[(v)*hdim+(h)])) )
60 /* get 8x8 MV component */
61 #define BV(p,xdim,h,v,h2,v2) (p[(2*(v)+(v2))*(xdim)+2*(h)+(h2)])
63 /* ------------------------------------------------------------------------- */
66 /* declaration for functions in this file */
67 Int
WriteMVcomponent(Int f_code
, Int dmv
, Image
*bs
);
68 Void
ScaleMVD (Int f_code
, Int diff_vector
, Int
*residual
, Int
*vlc_code_mag
);
69 Void
find_pmvs (Image
*mot_x
, Image
*mot_y
, Image
*MB_decisions
, Image
*B_decisions
,
70 Int x
, Int y
, Int block
, Int transparent_value
, Int quarter_pel
, Int
*error_flag
,
71 Int
*mvx
, Int
*mvy
, Int newgob
);
72 SInt
ModeMB (Image
*MB_decision
, Int i
, Int j
);
75 /***********************************************************CommentBegin******
77 * -- Bits_CountMB_Motion --
80 * Encodes the MV's Images acording to modes and alpha Images
81 * (see notes below). The codewords are appended to the bitstream.
82 * Included in text_code.h .
85 * Int mv_bits Returns the number of bits sent to the bitstream
88 * 1) No checking is made for the consistence of image sizes
89 * 2) It assumes the output image has been previously allocated.
90 * 3) Transparent MB's are not coded (no codeword is transmited).
91 * 4) Motion vectors for 8x8 transparent blocks within
92 * non-totally-transparent MB's are transmitted as MV (0,0) (not MVD
93 * (0,0)). This is made in the hope that this MV's are neither
94 * employed for block reconstruction nor for MV prediction.
96 ***********************************************************CommentEnd********/
100 Image
*mot_h
, /* <-- motion vectors (Float) - per block */
101 Image
*mot_v
, /* <-- motion vectors (Float) - per block */
102 Image
*alpha
, /* <-- macroblocks modes (SInt) - per block */
103 Image
*modes
, /* <-- macroblocks modes (SInt) - per MB */
104 Int h
, /* <-- horizontal coordinate of the MB */
105 Int v
, /* <-- vertical coordinate of the MB */
106 Int f_code
, /* <-- MV range in 1/2 or 1/4 pel units 1=32,2=64,...,7=2048 */
107 /* <-- flag for quarter pel MC mode */
108 Int quarter_pel
, /* MW QPEL 07-JUL-1998 */
109 Image
*bs
, /* --> output (SInt) */
110 Int error_res_disable
,
116 Int vdim
, hdim
; /* Dimensions in macroblocks */
117 Float
*ph
, *pv
; /* Motion vectors */
118 SInt
*pm
; /* Modes */
119 SInt
*pa
; /* Alpha */
123 /* From switch statement */
124 Int i
, error_flag
=0,mvx
=0,mvy
=0;
125 Float pred_h
, pred_v
;
126 Float diff_h
, diff_v
;
128 Int local_f_code
; /* MW QPEL 07-JUL-1998 */
129 Float subdim
; /* MW QPEL 07-JUL-1998 */
131 vdim
= (Int
)modes
->y
;
132 hdim
= (Int
)modes
->x
;
133 ph
=(Float
*)GetImageData(mot_h
);
134 pv
=(Float
*)GetImageData(mot_v
);
135 pm
=(SInt
*)GetImageData(modes
);
136 pa
=NULL
;//(SInt*)GetImageData(alpha);
139 /* MW QPEL 07-JUL-1998 >> */
140 /* Set local_f_code and subdim according to quarter_pel */
143 local_f_code
= f_code
+1;
148 local_f_code
= f_code
;
151 /* << MW QPEL 07-JUL-1998 */
153 switch (mode
=MB_MODE(h
,v
))
159 /* Prediction obtainment */
160 find_pmvs(mot_h
,mot_v
,modes
,alpha
,h
,v
,0,MBM_TRANSPARENT
,
161 /* MW QPEL 07-JUL-1998 */
162 quarter_pel
,&error_flag
,&mvx
,&mvy
,0);
164 pred_h
=((Float
)mvx
)/subdim
; /* MW QPEL 07-JUL-1998 */
165 pred_v
=((Float
)mvy
)/subdim
; /* MW QPEL 07-JUL-1998 */
167 /* MW QPEL 07-JUL-1998 */
168 bits_mot
+= WriteMVcomponent(local_f_code
, (Int
)(subdim
*(MBV_H(h
,v
) - pred_h
)), bs
);
169 /* MW QPEL 07-JUL-1998 */
170 bits_mot
+= WriteMVcomponent(local_f_code
, (Int
)(subdim
*(MBV_V(h
,v
) - pred_v
)), bs
);
176 for (bv
=0; bv
<=1; bv
++)
177 for (bh
=0; bh
<=1; bh
++)
179 find_pmvs(mot_h
,mot_v
,modes
,alpha
,h
,v
,i
,MBM_TRANSPARENT
,
180 /* MW QPEL 07-JUL-1998 */
181 quarter_pel
,&error_flag
,&mvx
,&mvy
,0);
183 pred_h
=((Float
)mvx
)/subdim
; /* MW QPEL 07-JUL-1998 */
184 pred_v
=((Float
)mvy
)/subdim
; /* MW QPEL 07-JUL-1998 */
188 diff_h
=BV_H(h
,v
,bh
,bv
)-pred_h
;
189 diff_v
=BV_V(h
,v
,bh
,bv
)-pred_v
;
191 /* MW QPEL 07-JUL-1998 */
192 bits_mot
+= WriteMVcomponent(local_f_code
, (Int
)(subdim
*diff_h
), bs
);
193 /* MW QPEL 07-JUL-1998 */
194 bits_mot
+= WriteMVcomponent(local_f_code
, (Int
)(subdim
*diff_v
), bs
);
203 /***********************************************************CommentBegin******
205 * -- WriteMVcomponent -- Encodes a single motion vector component
208 * Scales the motion vector difference, VLC the most significant part,
209 * then outputs the residual (least significant part) as a FLC.
212 * Int f_code, Range for MV, (1/2/3) => (32/64/128) 1/2 units
213 * Float diff_vector, MV Diff. component (in 1/2 units (in field))
214 * Image bs Bitstream output
217 * The number of bits for this encoding
220 * The encoded motion vector is added to the bitstream
222 ***********************************************************CommentEnd********/
231 Int residual
, vlc_code_mag
, bits
, entry
;
233 ScaleMVD(f_code
, dmv
, &residual
, &vlc_code_mag
);
235 if (vlc_code_mag
< 0)
236 entry
= vlc_code_mag
+ 65;
238 entry
= vlc_code_mag
;
240 bits
= PutMV (entry
, bs
);
242 if ((f_code
!= 1) && (vlc_code_mag
!= 0))
244 BitstreamPutBits(bs
, residual
, f_code
-1);
251 /***********************************************************CommentBegin******
253 * -- ScaleMVD -- Scales MVD component acording to the MV range
256 * Scales a Motion Vector Difference (MVD) component (x or y) according
257 * to the MV range. The maximum range that can be represented is
258 * determined by the f_code encoded in the VOP header. Two values,
259 * vlc_code_mag and residual, are generated.
262 * 1) The range of the MV's is computed according to the f_code.
263 * 2) The range of the MVD component is reduced to fall in the
265 * 3) Two values are generated:
266 * vlc_code_mag: It will be VLC coded in other function.
267 * residual : It will be FLC coded in other function.
269 ***********************************************************CommentEnd********/
273 Int f_code
, /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048 */
274 Int diff_vector
, /* <-- MV Difference commponent in 1/2 units */
275 Int
*residual
, /* --> value to be FLC coded */
276 Int
*vlc_code_mag
/* --> value to be VLC coded */
287 scale_factor
= 1<<r_size
;
288 range
= 32*scale_factor
;
291 if (diff_vector
< low
)
293 diff_vector
+= 2*range
;
295 else if (diff_vector
> high
)
297 diff_vector
-= 2*range
;
305 else if (scale_factor
==1)
307 *vlc_code_mag
= diff_vector
;
312 aux
= ABS(diff_vector
) + scale_factor
- 1;
313 *vlc_code_mag
= aux
>>r_size
;
316 *vlc_code_mag
= -*vlc_code_mag
;
318 *residual
= aux
& (scale_factor
-1);
323 /***********************************************************CommentBegin******
328 * Makes the motion vectors prediction for block 'block' (0 = whole MB)
330 ***********************************************************CommentEnd********/
334 Image
*mot_x
, /* x-motion vector field */
335 Image
*mot_y
, /* y-motion vector field */
336 Image
*MB_decisions
, /* MB modes */
337 Image
*B_decisions
, /* field with number of vectors per MB */
338 Int x
, /* xpos of the MB in multiples of 16 (hor coord) */
339 Int y
, /* ypos of the MB in multiples of 16 (ver coord) */
340 Int block
, /* block number (0 if one vector per MB, 1..4 else) */
341 Int transparent_value
, /* value of the transparency (0=enc, 2=dec) */
342 Int quarter_pel
, /* MW QPEL 06-JUL-1998 */ /* flag to indicate quarter pel mc */
343 Int
*error_flag
, /* set if an error occured */
344 Int
*mvx
, /* hor predicted motion vector [ in half-pixels units ] */
345 Int
*mvy
, /* ver predicted motion vector [ in half-pixels units ] */
351 Int xin1
, xin2
, xin3
;
352 Int yin1
, yin2
, yin3
;
353 Int vec1
, vec2
, vec3
;
354 Int rule1
, rule2
, rule3
;
355 Int subdim
; /* MW QPEL 06-JUL-1998 */
356 Float
*motxdata
= (Float
*) GetImageData(mot_x
);
357 Float
*motydata
= (Float
*) GetImageData(mot_y
);
358 Int xM
= GetImageSizeX(mot_x
);
362 /* MW QPEL 06-JUL-1998 >> */
371 /* << MW QPEL 06-JUL-1998 */
373 /* In a previous version, a MB vector (block = 0) was predicted the same way
374 as block 1, which is the most likely interpretation of the VM.
376 Therefore, if we have advanced pred. mode, and if all MBs around have
377 only one 16x16 vector each, we chose the appropiate block as if these
380 This different prediction affects only 16x16 vectors of MBs with
383 In the current version, we choose for the 16x16 mode the first
384 non-transparent block in the surrounding MBs
390 vec1
= 1 ; yin1
= y
; xin1
= x
-1;
391 vec2
= 2 ; yin2
= y
-1; xin2
= x
;
392 vec3
= 2 ; yin3
= y
-1; xin3
= x
+1;
395 vec1
= 1 ; yin1
= y
; xin1
= x
-1;
396 vec2
= 2 ; yin2
= y
-1; xin2
= x
;
397 vec3
= 2 ; yin3
= y
-1; xin3
= x
+1;
400 vec1
= 0 ; yin1
= y
; xin1
= x
;
401 vec2
= 3 ; yin2
= y
-1; xin2
= x
;
402 vec3
= 2 ; yin3
= y
-1; xin3
= x
+1;
405 vec1
= 3 ; yin1
= y
; xin1
= x
-1;
406 vec2
= 0 ; yin2
= y
; xin2
= x
;
407 vec3
= 1 ; yin3
= y
; xin3
= x
;
410 vec1
= 2 ; yin1
= y
; xin1
= x
;
411 vec2
= 0 ; yin2
= y
; xin2
= x
;
412 vec3
= 1 ; yin3
= y
; xin3
= x
;
415 printf("Illegal block number in find_pmv (mot_decode.c)");
423 /* according to the motion encoding, we must choose a first non-transparent
424 block in the surrounding MBs (16-mode)
427 if (x
>0 /*&& ValidCandidateMVP(x,y,xin1,yin1,vec1,xB,transparent_value,
428 MB_decisions,dcsn_data)*/)
433 if ((y
>0 && newgob
==0) /*&& ValidCandidateMVP(x,y,xin2,yin2,vec2,xB,transparent_value,
434 MB_decisions,dcsn_data)*/)
439 if ((x
!= xB
/2 -1) &&
440 ((y
>0 && newgob
==0)) /*&& ValidCandidateMVP(x,y,xin3,yin3,vec3,xB,transparent_value,
441 MB_decisions,dcsn_data)*/)
449 /* check borders for single blocks (advanced mode) */
452 if (((block
== 1 || block
== 3) && (x
== 0)) /*||
453 /* left block/MB is transparent *
454 (!ValidCandidateMVP(x,y,xin1,yin1,vec1,xB,transparent_value,
455 MB_decisions,dcsn_data))*/)
462 if (((block
== 1 || block
== 2) && (y
== 0)) /*||
463 /* top block/MB is transparent *
464 (!ValidCandidateMVP(x,y,xin2,yin2,vec2,xB,transparent_value,
465 MB_decisions,dcsn_data))*/)
471 if (((block
== 1 || block
== 2) && (x
== xB
/2 -1 || y
== 0)) /*||
472 /* right & top border *
473 /* right block/MB is transparent *
474 (!ValidCandidateMVP(x,y,xin3,yin3,vec3,xB,transparent_value,
475 MB_decisions,dcsn_data))*/)
486 else if (((mb_mode
= ModeMB(MB_decisions
,xin1
,yin1
)) >= MBM_FIELD00
) && (mb_mode
<= MBM_FIELD11
))
488 /* MW QPEL 06-JUL-1998 */
489 sum
= subdim
*(BV(motxdata
, xM
, xin1
, yin1
, 0, 0) + BV(motxdata
, xM
, xin1
, yin1
, 1, 0));
490 p1x
= (Float
)((sum
& 3) ? ((sum
| 2) >> 1) : (sum
>> 1))/(Float
)subdim
;
491 sum
= subdim
*(BV(motydata
, xM
, xin1
, yin1
, 0, 0) + BV(motydata
, xM
, xin1
, yin1
, 1, 0));
492 p1y
= (Float
)((sum
& 3) ? ((sum
| 2) >> 1) : (sum
>> 1))/(Float
)subdim
;
496 p1x
= BV(motxdata
, xM
, xin1
, yin1
, vec1
&0x1, vec1
>>1 );
497 p1y
= BV(motydata
, xM
, xin1
, yin1
, vec1
&0x1, vec1
>>1 );
504 else if (((mb_mode
= ModeMB(MB_decisions
,xin2
,yin2
)) >= MBM_FIELD00
) && (mb_mode
<= MBM_FIELD11
))
506 /* MW QPEL 06-JUL-1998 */
507 sum
= subdim
*(BV(motxdata
, xM
, xin2
, yin2
, 0, 0) + BV(motxdata
, xM
, xin2
, yin2
, 1, 0));
508 p2x
= (Float
)((sum
& 3) ? ((sum
| 2) >> 1) : (sum
>> 1))/(Float
)subdim
;
509 sum
= subdim
*(BV(motydata
, xM
, xin2
, yin2
, 0, 0) + BV(motydata
, xM
, xin2
, yin2
, 1, 0));
510 p2y
= (Float
)((sum
& 3) ? ((sum
| 2) >> 1) : (sum
>> 1))/(Float
)subdim
;
514 p2x
= BV(motxdata
, xM
, xin2
, yin2
, vec2
&0x1, vec2
>>1 );
515 p2y
= BV(motydata
, xM
, xin2
, yin2
, vec2
&0x1, vec2
>>1 );
522 else if (((mb_mode
= ModeMB(MB_decisions
,xin3
,yin3
)) >= MBM_FIELD00
) && (mb_mode
<= MBM_FIELD11
))
524 /* MW QPEL 06-JUL-1998 */
525 sum
= subdim
*(BV(motxdata
, xM
, xin3
, yin3
, 0, 0) + BV(motxdata
, xM
, xin3
, yin3
, 1, 0));
526 p3x
= (Float
)((sum
& 3) ? ((sum
| 2) >> 1) : (sum
>> 1))/(Float
)subdim
;
527 sum
= subdim
*(BV(motydata
, xM
, xin3
, yin3
, 0, 0) + BV(motydata
, xM
, xin3
, yin3
, 1, 0));
528 p3y
= (Float
)((sum
& 3) ? ((sum
| 2) >> 1) : (sum
>> 1))/(Float
)subdim
;
532 p3x
= BV(motxdata
, xM
, xin3
, yin3
, vec3
&0x1, vec3
>>1 );
533 p3y
= BV(motydata
, xM
, xin3
, yin3
, vec3
&0x1, vec3
>>1 );
536 if (rule1
&& rule2
&& rule3
)
538 /* all MBs are outside the VOP */
541 else if (rule1
+rule2
+rule3
== 2)
543 /* two of three are zero */
544 /* MW QPEL 06-JUL-1998 */
545 *mvx
=(Int
) subdim
*(p1x
+p2x
+p3x
); /* MW QPEL 06-JUL-1998 */
546 *mvy
=(Int
) subdim
*(p1y
+p2y
+p3y
); /* MW QPEL 06-JUL-1998 */
550 /* MW QPEL 06-JUL-1998 */
551 /* MW QPEL 06-JUL-1998 */
552 *mvx
=(Int
)(subdim
*(p1x
+p2x
+p3x
-MAX(p1x
,MAX(p2x
,p3x
))-MIN(p1x
,MIN(p2x
,p3x
))));
553 /* MW QPEL 06-JUL-1998 */
554 *mvy
=(Int
)(subdim
*(p1y
+p2y
+p3y
-MAX(p1y
,MAX(p2y
,p3y
))-MIN(p1y
,MIN(p2y
,p3y
))));
558 fprintf(stdout
,"find_pmvs (%2d,%2d, rule %1d%1d%1d) :\np1 %6.2f / %6.2f\np2 %6.2f / %6.2f\np3 %6.2f / %6.2f\n",x
,y
,rule1
,rule2
,rule3
,p1x
,p1y
,p2x
,p2y
,p3x
,p3y
);
565 /***********************************************************CommentBegin******
567 * -- ModeMB -- Get the MB mode
572 ***********************************************************CommentEnd********/
574 SInt
ModeMB (Image
*MB_decision
, Int i
, Int j
)
576 Int width
= MB_decision
->x
;
577 SInt
*p
= (SInt
*)GetImageData(MB_decision
);