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 utility functions to for motion estimation and */
38 /* Some codes of this project come from MoMuSys MPEG-4 implementation. */
39 /* Please see seperate acknowledgement file for a list of contributors. */
41 #include "mom_structs.h"
42 #include "vm_common_defs.h"
46 /* ------------------------------------------------------------------------- */
48 /* Macro to compute the MB absolute error difference of the inside the shape */
51 #define DIFF1(v1,v2,idx) (P_diff = (v1[idx]-v2[idx]), ABS(P_diff))
53 /***********************************************************CommentBegin******
55 * -- InterpolateImage -- Interpolates a complete (SInt)image
58 * Interpolates a complete (SInt) image for easier half pel prediction
60 ***********************************************************CommentEnd********/
64 Image
*input_image
, /* <-- image to interpolate (SInt) */
65 Image
*output_image
, /* --> interpolated image (SInt) */
73 width
= input_image
->x
;
74 height
= input_image
->y
;
75 ii
= (SInt
*)GetImageData(output_image
);
76 oo
= (SInt
*)GetImageData(input_image
);
79 for (j
= 0; j
< height
-1; j
++)
81 for (i
= 0; i
< width
-1; i
++)
83 *(ii
+ (i
<<1)) = *(oo
+ i
);
84 *(ii
+ (i
<<1)+1) = (*(oo
+ i
) + *(oo
+ i
+ 1) + 1- rounding_control
)>>1;
85 *(ii
+ (i
<<1)+(width
<<1)) = (*(oo
+ i
) + *(oo
+ i
+ width
) + 1-
87 *(ii
+ (i
<<1)+1+(width
<<1)) = (*(oo
+i
) + *(oo
+i
+1) +
88 *(oo
+i
+width
) + *(oo
+i
+1+width
) + 2-
91 /* last pels on each line */
92 *(ii
+ (width
<<1) - 2) = *(oo
+ width
- 1);
93 *(ii
+ (width
<<1) - 1) = *(oo
+ width
- 1);
94 *(ii
+ (width
<<1)+ (width
<<1)-2) = (*(oo
+width
-1)+*(oo
+width
+width
-1)+1-
96 *(ii
+ (width
<<1)+ (width
<<1)-1) = (*(oo
+width
-1)+*(oo
+width
+width
-1)+1-
103 for (i
= 0; i
< width
-1; i
++)
105 *(ii
+ (i
<<1)) = *(oo
+ i
);
106 *(ii
+ (i
<<1)+1) = (*(oo
+ i
) + *(oo
+ i
+ 1) + 1- rounding_control
)>>1;
107 *(ii
+ (width
<<1)+ (i
<<1)) = *(oo
+ i
);
108 *(ii
+ (width
<<1)+ (i
<<1)+1) = (*(oo
+ i
) + *(oo
+ i
+ 1) + 1-
109 rounding_control
)>>1;
112 /* bottom right corner pels */
113 *(ii
+ (width
<<1) - 2) = *(oo
+ width
-1);
114 *(ii
+ (width
<<1) - 1) = *(oo
+ width
-1);
115 *(ii
+ (width
<<2) - 2) = *(oo
+ width
-1);
116 *(ii
+ (width
<<2) - 1) = *(oo
+ width
-1);
122 /***********************************************************CommentBegin******
124 * -- GetMotionImages --
127 * Translate the MVs data from the resulting separated four
128 * (Float) Images (16x16/8x8, X,Y) of the motion estimation process
129 * into two Images, which contain the 16x16 and 8x8 MVs
130 * values acording to the modes (MBM_INTRA, MBM_INTER16,
131 * MBM_INTER8). It also
132 * makes a copy of imode16 (SInt-Image of modes).
135 * 1 on success, -1 on error
137 ***********************************************************CommentEnd********/
141 Image
*imv16_w
, /* <-- 16x16 horiz. MV Float-Image (MxN) (cuad.) */
142 Image
*imv16_h
, /* <-- 16x16 verti. MV Float-Image (MxN) (cuad.) */
143 Image
*imv8_w
, /* <-- 8x8 horizontal MV Float-Image (MxN) */
144 Image
*imv8_h
, /* <-- 8x8 vertical MV Float-Image (MxN) */
145 Image
*imode16
, /* <-- SInt-Image of modes (M/2xN/2) */
146 Image
**mv_x
, /* --> horizontal MV Float-Image (MxN) */
147 Image
**mv_y
, /* --> vertical MV Float-Image (MxN) */
148 Image
**mode
/* --> SInt-Image of modes (M/2xN/2) */
153 Int width
, height
, base
;
155 Float
*data_x
, *data_y
,
158 SInt
*mode16
, *data_mode
;
161 width
= imode16
->x
; height
= imode16
->y
;
163 (*mode
)=AllocImage(width
,height
,SHORT_TYPE
);
164 (*mv_x
)=AllocImage(width
*2,height
*2,FLOAT_TYPE
);
165 (*mv_y
)=AllocImage(width
*2,height
*2,FLOAT_TYPE
);
166 data_x
= (Float
*)GetImageData((*mv_x
));
167 data_y
= (Float
*)GetImageData((*mv_y
));
168 data_mode
= (SInt
*)GetImageData((*mode
));
169 mode16
=(SInt
*)GetImageData(imode16
);
170 mv16_w
=(Float
*)GetImageData(imv16_w
);
171 mv16_h
=(Float
*)GetImageData(imv16_h
);
172 mv8_w
=(Float
*)GetImageData(imv8_w
);
173 mv8_h
=(Float
*)GetImageData(imv8_h
);
175 for(j
=0;j
<height
;j
++)
177 for(i
=0;i
< width
;i
++)
179 modo
=data_mode
[j
*width
+i
]=mode16
[j
*width
+i
];
180 if ( modo
==MBM_INTRA
) /*INTRA*/
182 base
=2*j
*2*width
+2*i
;
183 data_x
[base
]=0.0; data_x
[base
+1]=0.0;
184 data_y
[base
]=0.0; data_y
[base
+1]=0.0;
186 data_x
[base
]=0.0; data_x
[base
+1]=0.0;
187 data_y
[base
]=0.0; data_y
[base
+1]=0.0;
189 else if(modo
==MBM_INTER16
) /*INTER 16*/
191 base
=2*j
*2*width
+2*i
;
192 val_x
=mv16_w
[base
];val_y
=mv16_h
[base
];
194 data_x
[base
]=val_x
; data_x
[base
+1]=val_x
;
195 data_y
[base
]=val_y
; data_y
[base
+1]=val_y
;
197 data_x
[base
]=val_x
; data_x
[base
+1]=val_x
;
198 data_y
[base
]=val_y
; data_y
[base
+1]=val_y
;
200 else if (modo
==MBM_INTER8
) /*INTER4*8*/
202 base
=2*j
*2*width
+2*i
;
204 data_x
[base
] = mv8_w
[base
];
205 data_y
[base
] = mv8_h
[base
];
206 data_x
[base
+1] = mv8_w
[base
+1];
207 data_y
[base
+1] = mv8_h
[base
+1];
209 data_x
[base
] = mv8_w
[base
];
210 data_y
[base
] = mv8_h
[base
];
211 data_x
[base
+1] = mv8_w
[base
+1];
212 data_y
[base
+1] = mv8_h
[base
+1];
221 /***********************************************************CommentBegin******
223 * -- ChooseMode -- chooses coding mode INTRA/INTER dependig on the SAD values
226 * chooses coding mode INTRA/INTER dependig on the SAD values
229 * 1 for INTER, 0 for INTRA
231 ***********************************************************CommentEnd********/
235 SInt
*curr
, /* <-- current Y values (not extended) */
236 Int x_pos
, /* <-- upper-left MB corner hor. coor. */
237 Int y_pos
, /* <-- upper-left MB corner ver. coor. */
238 Int min_SAD
, /* <-- min SAD (from integer pel search) */
239 UInt width
/* <-- current Y picture width */
243 Int MB_mean
= 0, A
= 0;
246 for (j
= 0; j
< MB_SIZE
; j
++)
248 y_off
= (y_pos
+ j
) * width
;
249 for (i
= 0; i
< MB_SIZE
; i
++)
251 MB_mean
+= *(curr
+ x_pos
+ i
+ y_off
);
257 for (j
= 0; j
< MB_SIZE
; j
++)
259 y_off
= (y_pos
+ j
) * width
;
260 for (i
= 0; i
< MB_SIZE
; i
++)
262 A
+= abs( *(curr
+ x_pos
+ i
+ y_off
) - MB_mean
);
266 if (A
< (min_SAD
- 2*256))
273 /***********************************************************CommentBegin******
275 * -- SAD_Macroblock -- obtains the SAD for a Macroblock
278 * obtains the SAD for a Macroblock
283 ***********************************************************CommentEnd********/
287 SInt
*ii
, /* <-- Pointer to the upper-left pel of first MB */
288 SInt
*act_block
, /* <-- Id, second MB (width=16) */
289 UInt h_length
, /* <-- Width of first area */
290 Int Min_FRAME
/* <-- Minimum prediction error so far */
302 sad += (DIFF1(ii,kk,0)+DIFF1(ii,kk,1)
303 +DIFF1(ii,kk,2)+DIFF1(ii,kk,3)
304 +DIFF1(ii,kk,4)+DIFF1(ii,kk,5)
305 +DIFF1(ii,kk,6)+DIFF1(ii,kk,7)
306 +DIFF1(ii,kk,8)+DIFF1(ii,kk,9)
307 +DIFF1(ii,kk,10)+DIFF1(ii,kk,11)
308 +DIFF1(ii,kk,12)+DIFF1(ii,kk,13)
309 +DIFF1(ii,kk,14)+DIFF1(ii,kk,15)
322 SInt
*p1
= ii
, *p2
= act_block
;
328 sad
+= abs((int)*(p1
++) - (int)*(p2
++));
338 /***********************************************************CommentBegin******
340 * -- SAD_Block -- obtains the SAD for a Block
343 * obtains the SAD for a Block
348 ***********************************************************CommentEnd********/
352 SInt
*ii
, /* <-- First area */
353 SInt
*act_block
, /* <-- Id. second MB (width=16) */
354 UInt h_length
, /* <-- Width of first area */
355 Int min_sofar
/* <-- Minimum prediction error so far */
367 sad += (DIFF1(ii,kk,0)+DIFF1(ii,kk,1)
368 +DIFF1(ii,kk,2)+DIFF1(ii,kk,3)
369 +DIFF1(ii,kk,4)+DIFF1(ii,kk,5)
370 +DIFF1(ii,kk,6)+DIFF1(ii,kk,7)
383 SInt
*p1
= ii
, *p2
= act_block
;
389 sad
+= abs((int)*(p1
++) - (int)*(p2
++));
401 /***********************************************************CommentBegin******
403 * -- LoadArea -- fills array with a image-data
406 * fills array with a image-data
409 * Pointer to the filled array
411 ***********************************************************CommentEnd********/
415 SInt
*im
, /* <-- pointer to image */
416 Int x
, /* <-- horizontal pos */
417 Int y
, /* <-- vertical pos */
418 Int x_size
, /* <-- width of array */
419 Int y_size
, /* <-- height of array */
420 Int lx
, /* <-- width of the image data */
421 SInt
*block
/* <-> pointer to the array */
429 in
= im
+ (y
*lx
) + x
;
444 /***********************************************************CommentBegin******
446 * -- SetArea -- fills a image-data with an array
449 * fills a image-data with an array
451 ***********************************************************CommentEnd********/
455 SInt
*block
, /* <-- pointer to array */
456 Int x
, /* <-- horizontal pos in image */
457 Int y
, /* <-- vertical pos in image */
458 Int x_size
, /* <-- width of array */
459 Int y_size
, /* <-- height of array */
460 Int lx
, /* <-- width of the image data */
461 SInt
*im
/* --> pointer to image */
470 out
= im
+ (y
*lx
) + x
;