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 do motion estimation and */
37 /* for the current image in one pass. */
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 "vm_common_defs.h"
44 #include "mot_est_mb.h"
48 /* For correct rounding of chrominance vectors */
49 static Int roundtab16
[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};
51 Void
MotionEstCompPicture (
98 /***********************************************************CommentBegin******
100 * -- MotionEstimationCompensation -- Estimates the motion vectors and
101 * do motion compensation
104 * Estimates the motion vectors in advanced/not_advanced unrestricted
105 * mode. The output are four images containing x/y components of
106 * MV's (one per 8x8 block), modes (one value per MB). The motion
107 * compensation is also performed.
110 * 1) memory is allocated for these images.
111 * 2) mot_x/mot_y have 4 identical vector for a MB coded inter 16
112 * 3) mot_x/mot_y have 4 identical zero vectors for a MB coded intra
113 * 4) if _NO_ESTIMATION_ is used, the output is the following:
114 * - mot_x : all MV's are 0.0
115 * - mot_y : all MV's are 0.0
116 * - mode : all modes are MB_INTRA (IGNORING THE SHAPE)
118 * Based on: CodeOneOrTwo (TMN5, coder.c)
120 ***********************************************************CommentEnd********/
123 MotionEstimationCompensation (
124 Vop
*curr_vop
, /* <-- current Vop (for luminance) */
125 Vop
*prev_rec_vop
, /* <-- reference Vop (reconstructed)(1/2 pixel) */
126 Int enable_8x8_mv
, /* <-- 8x8 MV (=1) or only 16x16 MV (=0) */
127 Int edge
, /* <-- restricted(==0)/unrestricted(==edge) mode */
128 Int f_code
, /* <-- MV search range 1/2 pel: 1=32,2=64,...,7=2048*/
129 Vop
*curr_comp_vop
, /* <-> motion compensated current VOP */
130 Float
*mad
, /* <-> mad value of the ME/MC result */
131 Image
**mot_x
, /* --> horizontal MV coordinates */
132 Image
**mot_y
, /* --> vertical MV coordinates */
133 Image
**mode
/* --> modes for each MB */
136 Image
*pr_rec_y
; /* Reference image (reconstructed) */
137 Image
*pi_y
; /* Interp.ref.image Y */
145 SInt
*prev_ipol_y
, /* Interp.ref.image Y (subimage) */
146 *prev_orig_y
; /* Ref. original image with edge (subimage) */
148 Int vop_width
, vop_height
;
157 br_y
=curr_vop
->ver_spat_ref
;
158 br_x
=curr_vop
->hor_spat_ref
;
159 br_height
=curr_vop
->height
;
160 br_width
=curr_vop
->width
;
161 mv_h
=br_height
/MB_SIZE
;
162 mv_w
=br_width
/MB_SIZE
;
165 ** WE SUPPOSE prev_rec_vop & prev_vop HAVE EQUAL SIZE AND POSITIONS
168 vop_width
=prev_rec_vop
->width
;
169 vop_height
=prev_rec_vop
->height
;
172 ** Get images and interpolate them
175 pr_rec_y
= prev_rec_vop
->y_chan
;
176 prev_orig_y
= (SInt
*)GetImageData(pr_rec_y
);
177 pi_y
= AllocImage (2*vop_width
, 2*vop_height
, SHORT_TYPE
);
178 InterpolateImage(pr_rec_y
, pi_y
, GetVopRoundingType(curr_vop
));
179 prev_ipol_y
= (SInt
*)GetImageData(pi_y
);
182 * allocate memory for mv's and modes data
186 mode16
=AllocImage (mv_w
,mv_h
,SHORT_TYPE
);
187 SetConstantImage (mode16
,(Float
)MBM_INTRA
);
190 ** mv16 have 2x2 repeted the mv value to share the functions of
191 ** mv prediction between CodeVopVotion and MotionEstimation
194 mv16_w
=AllocImage (mv_w
*2,mv_h
*2,FLOAT_TYPE
);
195 mv16_h
=AllocImage (mv_w
*2,mv_h
*2,FLOAT_TYPE
);
196 mv8_w
=AllocImage (mv_w
*2,mv_h
*2,FLOAT_TYPE
);
197 mv8_h
=AllocImage (mv_w
*2,mv_h
*2,FLOAT_TYPE
);
198 SetConstantImage (mv16_h
,+0.0);
199 SetConstantImage (mv16_w
,+0.0);
200 SetConstantImage (mv8_h
,+0.0);
201 SetConstantImage (mv8_w
,+0.0);
203 SetConstantImage (curr_comp_vop
->u_chan
, 0);
204 SetConstantImage (curr_comp_vop
->v_chan
, 0);
206 /* Compute motion vectors and modes for each MB
210 MotionEstCompPicture(
211 (SInt
*)GetImageData(GetVopY(curr_vop
)), //curr_vop,
212 prev_orig_y
, /* Y padd with edge */
213 prev_ipol_y
, /* Y interpolated (from pi_y) */
214 (SInt
*)GetImageData(prev_rec_vop
->u_chan
) + (vop_width
/2) * (16/2) + (16/2),
215 (SInt
*)GetImageData(prev_rec_vop
->v_chan
) + (vop_width
/2) * (16/2) + (16/2),
216 prev_rec_vop
->hor_spat_ref
,
217 prev_rec_vop
->ver_spat_ref
,
218 vop_width
,vop_height
,
221 GetVopSearchRangeFor(curr_vop
),
223 GetVopRoundingType(curr_vop
),
224 br_x
,br_y
, /* pos. of the bounding rectangle */
225 br_width
,br_height
, /* dims. of the bounding rectangle */
226 (SInt
*)GetImageData(curr_comp_vop
->y_chan
),
227 (SInt
*)GetImageData(curr_comp_vop
->u_chan
),
228 (SInt
*)GetImageData(curr_comp_vop
->v_chan
),
230 (Float
*)GetImageData(mv16_w
),
231 (Float
*)GetImageData(mv16_h
),
232 (Float
*)GetImageData(mv8_w
),
233 (Float
*)GetImageData(mv8_h
),
234 (SInt
*) GetImageData(mode16
)
237 /* Convert output to MOMUSYS format */
238 GetMotionImages(mv16_w
, mv16_h
, mv8_w
, mv8_h
, mode16
, mot_x
, mot_y
, mode
);
240 /* Deallocate dynamic memory */
241 FreeImage(mv16_w
); FreeImage(mv16_h
);
242 FreeImage(mv8_w
); FreeImage(mv8_h
);
247 /***********************************************************CommentBegin******
249 * -- MotionEstCompPicture -- Computes MV's and predictor errors and
250 * do motion compensation
253 * Computes MV's (8x8 and 16x16) and predictor errors for the whole
254 * vop. Perform motion compensation for the whole vop.
256 ***********************************************************CommentEnd********/
259 MotionEstCompPicture(
260 SInt
*curr
, /* <-- Current VOP */
261 SInt
*prev
, /* <-- Original Y padd with edge */
262 SInt
*prev_ipol
, /* <-- Y interpolated (from pi_y) */
263 SInt
*prev_u
, /* <-- Original U padd with edge */
264 SInt
*prev_v
, /* <-- Original V padd with edge */
265 Int prev_x
, /* <-- absolute horiz. position of previous vop */
266 Int prev_y
, /* <-- absolute verti. position of previous vop */
267 Int vop_width
, /* <-- horizontal previous vop dimension */
268 Int vop_height
, /* <-- vertical previous vop dimension */
269 Int enable_8x8_mv
, /* <-- 8x8 MV (=1) or only 16x16 MV (=0) */
270 Int edge
, /* <-- edge arround the reference vop */
271 Int sr_for
, /* <-- forward search range */
272 Int f_code
, /* MW QPEL 07-JUL-1998 *//* <-- MV search range 1/2 or 1/4 pel: 1=32,2=64,...,7=2048*/
273 Int rounding_type
, /* <-- The rounding type of the current vop */
274 Int br_x
, /* <-- absolute horiz. position of the current vop */
275 Int br_y
, /* <-- absolute verti. position of the current vop */
276 Int br_width
, /* <-- current bounding rectangule width */
277 Int br_height
, /* <-- current bounding rectangle height */
278 SInt
*curr_comp_y
, /* <-> motion compensated current Y */
279 SInt
*curr_comp_u
, /* <-> motion compensated current U */
280 SInt
*curr_comp_v
, /* <-> motion compensated current V */
281 Float
*mad
, /* <-> the mad value of current ME/MC result */
282 Float
*mv16_w
, /* --> predicted horizontal 16x16 MV(if approp.) */
283 Float
*mv16_h
, /* --> predicted vertical 16x16 MV (if approp.) */
284 Float
*mv8_w
, /* --> predicted horizontal 8x8 MV (if approp.) */
285 Float
*mv8_h
, /* --> predicted vertical 8x8 MV (if approp.) */
286 SInt
*mode16
/* --> mode of the preditect motion vector */
290 SInt curr_mb
[MB_SIZE
][MB_SIZE
];
291 SInt curr_comp_mb_16
[MB_SIZE
][MB_SIZE
];
292 SInt curr_comp_mb_8
[MB_SIZE
][MB_SIZE
];
293 Int sad8
= MV_MAX_ERROR
, sad16
, sad
;
294 Int imas_w
, imas_h
, Mode
;
295 Int posmode
, pos16
, pos8
;
297 min_error8_0
, min_error8_1
, min_error8_2
, min_error8_3
;
298 // SInt *curr = (SInt *)GetImageData(GetVopY(curr_vop));
299 /***************************************************************************
300 array of flags, which contains for the MB and for each one of the 4 Blocks
301 the following info sequentially:
302 xm, 1 if the lower search (x axis) is completed (no 1/2 search can be done)
303 0, do 1/2 search in the lower bound (x axis)
304 xM, 1 if the upper search (x axis) is completed (no 1/2 search can be done)
305 0, do 1/2 search in the upper bound (x axis)
306 ym, 1 if the lower search (y axis) is completed (no 1/2 search can be done)
307 0, do 1/2 search in the lower bound (y axis)
308 yM, 1 if the upper search (y axis) is completed (no 1/2 search can be done)
309 0, do 1/2 search in the upper bound (y axis)
310 ***************************************************************************/
312 Float hint_mv_w
, hint_mv_h
;
314 Int prev_x_min
,prev_x_max
,prev_y_min
,prev_y_max
;
316 prev_x_min
= 2 * prev_x
+ 2 * 16;
317 prev_y_min
= 2 * prev_y
+ 2 * 16;
318 prev_x_max
= prev_x_min
+ 2 * vop_width
- 4 * 16;
319 prev_y_max
= prev_y_min
+ 2 * vop_height
- 4 * 16;
321 imas_w
=br_width
/MB_SIZE
;
322 imas_h
=br_height
/MB_SIZE
;
324 /* Do motion estimation and store result in array */
326 halfpelflags
=(SInt
*)malloc(5*4*sizeof(SInt
));
327 /* halfpelflags=(SInt*)malloc(9*4*sizeof(SInt)); */
330 for ( j
=0; j
< (br_height
/MB_SIZE
); j
++)
332 hint_mv_w
= hint_mv_h
= 0.f
;
333 for ( i
=0; i
< (br_width
/MB_SIZE
); i
++)
335 /* Integer pel search */
338 posmode
= j
* imas_w
+ i
;
339 pos16
= pos8
= 2*j
*2*imas_w
+ 2*i
;
341 MBMotionEstimation(curr
,
343 br_width
, i
, j
, prev_x
, prev_y
,
344 vop_width
, vop_height
, enable_8x8_mv
, edge
,
346 hint_mv_w
, hint_mv_h
, // the hint seeds
348 mv8_w
, mv8_h
, &min_error
, halfpelflags
);
350 /* Inter/Intra decision */
351 Mode
= ChooseMode(curr
,
352 i
*MB_SIZE
,j
*MB_SIZE
, min_error
, br_width
);
354 hint_mv_w
= mv16_w
[pos16
];
355 hint_mv_h
= mv16_h
[pos16
];
357 LoadArea(curr
, i
*MB_SIZE
, j
*MB_SIZE
, 16, 16, br_width
, (SInt
*)curr_mb
);
359 /* 0==MBM_INTRA,1==MBM_INTER16||MBM_INTER8 */
362 FindSubPel (i
*MB_SIZE
,j
*MB_SIZE
, prev_ipol
,
363 &curr_mb
[0][0], 16, 16 , 0,
364 br_x
-prev_x
,br_y
-prev_y
,vop_width
, vop_height
,
365 edge
, halfpelflags
, &curr_comp_mb_16
[0][0],
366 &mv16_w
[pos16
], &mv16_h
[pos16
], &min_error16
);
368 /* sad16(0,0) already decreased by Nb/2+1 in FindHalfPel() */
370 mode16
[posmode
] = MBM_INTER16
;
376 FindSubPel(i
*MB_SIZE
, j
*MB_SIZE
, prev_ipol
,
377 &curr_mb
[0][0], 8, 8 , 0,
378 br_x
-prev_x
,br_y
-prev_y
, vop_width
, vop_height
,
379 edge
, halfpelflags
, &curr_comp_mb_8
[0][0],
380 &mv8_w
[pos8
], &mv8_h
[pos8
], &min_error8_0
);
381 xsum
+= (Int
)(2*(mv8_w
[pos8
]));
382 ysum
+= (Int
)(2*(mv8_h
[pos8
]));
384 FindSubPel(i
*MB_SIZE
, j
*MB_SIZE
, prev_ipol
,
385 &curr_mb
[0][8], 8, 8 , 1,
386 br_x
-prev_x
,br_y
-prev_y
, vop_width
,vop_height
,
387 edge
, halfpelflags
, &curr_comp_mb_8
[0][8],
388 &mv8_w
[pos8
+1], &mv8_h
[pos8
+1], &min_error8_1
);
389 xsum
+= (Int
)(2*(mv8_w
[pos8
+1]));
390 ysum
+= (Int
)(2*(mv8_h
[pos8
+1]));
394 FindSubPel(i
*MB_SIZE
, j
*MB_SIZE
, prev_ipol
,
395 &curr_mb
[8][0], 8, 8 , 2,
396 br_x
-prev_x
,br_y
-prev_y
, vop_width
,vop_height
,
397 edge
, halfpelflags
, &curr_comp_mb_8
[8][0],
398 &mv8_w
[pos8
], &mv8_h
[pos8
], &min_error8_2
);
399 xsum
+= (Int
)(2*(mv8_w
[pos8
]));
400 ysum
+= (Int
)(2*(mv8_h
[pos8
]));
402 FindSubPel(i
*MB_SIZE
, j
*MB_SIZE
, prev_ipol
,
403 &curr_mb
[8][8], 8, 8 , 3,
404 br_x
-prev_x
,br_y
-prev_y
, vop_width
,vop_height
,
405 edge
, halfpelflags
, &curr_comp_mb_8
[8][8],
406 &mv8_w
[pos8
+1], &mv8_h
[pos8
+1], &min_error8_3
);
407 xsum
+= (Int
)(2*(mv8_w
[pos8
+1]));
408 ysum
+= (Int
)(2*(mv8_h
[pos8
+1]));
410 sad8
= min_error8_0
+min_error8_1
+min_error8_2
+min_error8_3
;
412 /* Choose 8x8 or 16x16 vectors */
413 if (sad8
< (sad16
-(128+1)))
414 mode16
[posmode
] = MBM_INTER8
;
415 } /* end of enable_8x8_mv mode */
417 /* When choose 16x16 vectors */
418 /* sad16(0,0) was decreased by MB_Nb, now add it back */
419 if ((mv16_w
[pos16
]==0.0) && (mv16_h
[pos16
]==0.0) && (mode16
[posmode
]==MBM_INTER16
))
422 /* calculate motion vectors for chroma compensation */
423 if(mode16
[posmode
] == MBM_INTER8
)
425 dx
= SIGN (xsum
) * (roundtab16
[ABS (xsum
) % 16] + (ABS (xsum
) / 16) * 2);
426 dy
= SIGN (ysum
) * (roundtab16
[ABS (ysum
) % 16] + (ABS (ysum
) / 16) * 2);
429 else /* mode == MBM_INTER16 */
431 dx
= (Int
)(2 * mv16_w
[pos16
]);
432 dy
= (Int
)(2 * mv16_h
[pos16
]);
433 dx
= ( dx
% 4 == 0 ? dx
>> 1 : (dx
>>1)|1 );
434 dy
= ( dy
% 4 == 0 ? dy
>> 1 : (dy
>>1)|1 );
438 GetPred_Chroma (i
*MB_SIZE
, j
*MB_SIZE
, dx
, dy
,
439 prev_u
, prev_v
, curr_comp_u
, curr_comp_v
,
441 prev_x_min
/4,prev_y_min
/4,prev_x_max
/4,prev_y_max
/4, rounding_type
);
443 } /* end of mode non zero */
444 else /* mode = 0 INTRA */
446 mode16
[posmode
] = MBM_INTRA
;
447 for (k
= 0; k
< MB_SIZE
*MB_SIZE
; k
++)
449 // for INTRA MB, set compensated 0 to generate correct error image
450 curr_comp_mb_16
[k
/MB_SIZE
][k
%MB_SIZE
] = 0;
451 // for INTRA_MB, SAD is recalculated from image instead of using min_error
452 sad
+= curr_mb
[k
/MB_SIZE
][k
%MB_SIZE
];
456 if (mode16
[posmode
] == MBM_INTER8
)
457 SetArea((SInt
*)curr_comp_mb_8
, i
*MB_SIZE
, j
*MB_SIZE
, 16, 16, br_width
, curr_comp_y
);
459 SetArea((SInt
*)curr_comp_mb_16
, i
*MB_SIZE
, j
*MB_SIZE
, 16, 16, br_width
, curr_comp_y
);
460 } /* end of i loop */
461 } /* end of j loop */
463 *mad
= (float)sad
/(br_width
*br_height
);
465 free((Char
*)halfpelflags
);
470 /***********************************************************CommentBegin******
472 * unrestricted_MC_chro
475 * To make unrestricted MC
477 ***********************************************************CommentEnd********/
478 /*Int unrestricted_MC_chro(Int x,Int y, Int npix,
479 Int prev_x_min,Int prev_y_min,
480 Int prev_x_max, Int prev_y_max)
483 if (x < prev_x_min) x = prev_x_min;
484 else if (x >=prev_x_max) x = prev_x_max-1;
486 if (y < prev_y_min) y = prev_y_min;
487 else if (y >=prev_y_max) y = prev_y_max-1;
491 #define unrestricted_MC_chro(x,y,npix,prev_x_min,prev_y_min,prev_x_max,prev_y_max) ((x)+(y)*(npix))
494 /***********************************************************CommentBegin******
496 * -- GetPred_Chroma -- Predicts chrominance macroblock
499 * Does the chrominance prediction for P-frames
502 * current position in image,
504 * pointers to compensated and previous Vops,
505 * width of the compensated Vop
506 * width of the previous/reference Vop
508 ***********************************************************CommentEnd********/
510 Void
GetPred_Chroma (
525 Int rounding_control
)
529 Int x
, y
, ofx
, ofy
, lx
;
532 Int index1
,index2
,index3
,index4
;
546 for (n
= 0; n
< 8; n
++)
548 for (m
= 0; m
< 8; m
++)
552 index1
= unrestricted_MC_chro(ofx
,ofy
,lx
,prev_x_min
,
553 prev_y_min
,prev_x_max
,prev_y_max
);
554 comp_u
[(y
+n
)*width
/2+x
+m
]
556 comp_v
[(y
+n
)*width
/2+x
+m
]
563 for (n
= 0; n
< 8; n
++)
565 for (m
= 0; m
< 8; m
++)
569 index1
= unrestricted_MC_chro(ofx
,ofy
,lx
,prev_x_min
,
570 prev_y_min
,prev_x_max
,prev_y_max
);
571 index2
= unrestricted_MC_chro(ofx
,ofy
+yh
,lx
,prev_x_min
,
572 prev_y_min
,prev_x_max
,prev_y_max
);
574 comp_u
[(y
+n
)*width
/2+x
+m
]
575 = (*(prev_u
+index1
) +
576 *(prev_u
+index2
) + 1- rounding_control
)>>1;
578 comp_v
[(y
+n
)*width
/2+x
+m
]
579 = (*(prev_v
+index1
) +
580 *(prev_v
+index2
) + 1- rounding_control
)>>1;
586 for (n
= 0; n
< 8; n
++)
588 for (m
= 0; m
< 8; m
++)
592 index1
= unrestricted_MC_chro(ofx
,ofy
,lx
,prev_x_min
,
593 prev_y_min
,prev_x_max
,prev_y_max
);
594 index2
= unrestricted_MC_chro(ofx
+xh
,ofy
,lx
,prev_x_min
,
595 prev_y_min
,prev_x_max
,prev_y_max
);
597 comp_u
[(y
+n
)*width
/2+x
+m
]
598 = (*(prev_u
+index1
) +
599 *(prev_u
+index2
) + 1- rounding_control
)>>1;
601 comp_v
[(y
+n
)*width
/2+x
+m
]
602 = (*(prev_v
+index1
) +
603 *(prev_v
+index2
) + 1- rounding_control
)>>1;
609 for (n
= 0; n
< 8; n
++)
611 for (m
= 0; m
< 8; m
++)
615 index1
= unrestricted_MC_chro(ofx
,ofy
,lx
,prev_x_min
,
616 prev_y_min
,prev_x_max
,prev_y_max
);
617 index2
= unrestricted_MC_chro(ofx
+xh
,ofy
,lx
,prev_x_min
,
618 prev_y_min
,prev_x_max
,prev_y_max
);
619 index3
= unrestricted_MC_chro(ofx
,ofy
+yh
,lx
,prev_x_min
,
620 prev_y_min
,prev_x_max
,prev_y_max
);
621 index4
= unrestricted_MC_chro(ofx
+xh
,ofy
+yh
,lx
,prev_x_min
,
622 prev_y_min
,prev_x_max
,prev_y_max
);
624 comp_u
[(y
+n
)*width
/2+x
+m
]
629 2- rounding_control
)>>2;
631 comp_v
[(y
+n
)*width
/2+x
+m
]
636 2- rounding_control
)>>2;