r936: Sane default sample zoom...
[cinelerra_cv/mob.git] / quicktime / encore50 / mot_code.c
blobdec21ee69af6e90bc30c43f903940909cf2b1b4a
2 /**************************************************************************
3 * *
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. *
13 * *
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. *
18 * *
19 * The complete Open DivX license can be found at *
20 * http://www.projectmayo.com/opendivx/license.php . *
21 * *
22 **************************************************************************/
24 /**************************************************************************
26 * mot_code.c
28 * Copyright (C) 2001 Project Mayo
30 * Adam Li
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"
43 #include "putvlc.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 --
79 * Purpose :
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 .
84 * Return values :
85 * Int mv_bits Returns the number of bits sent to the bitstream
87 * Description :
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********/
98 Int
99 Bits_CountMB_Motion(
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,
111 Int after_marker,
112 Int **slice_nb,
113 Int arbitrary_shape
116 Int vdim, hdim; /* Dimensions in macroblocks */
117 Float *ph, *pv; /* Motion vectors */
118 SInt *pm; /* Modes */
119 SInt *pa; /* Alpha */
120 Int mode;
121 Int bits_mot = 0;
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;
127 Int bh, bv;
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 */
141 if (quarter_pel)
143 local_f_code = f_code+1;
144 subdim = 4.0;
146 else
148 local_f_code = f_code;
149 subdim = 2.0;
151 /* << MW QPEL 07-JUL-1998 */
153 switch (mode=MB_MODE(h,v))
155 case MBM_INTRA:
156 break;
158 case MBM_INTER16:
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);
172 break;
174 case MBM_INTER8:
175 i=1;
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 */
186 i++;
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);
196 break;
199 return bits_mot;
203 /***********************************************************CommentBegin******
205 * -- WriteMVcomponent -- Encodes a single motion vector component
207 * Purpose :
208 * Scales the motion vector difference, VLC the most significant part,
209 * then outputs the residual (least significant part) as a FLC.
211 * Arguments in :
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
216 * Return values :
217 * The number of bits for this encoding
219 * Side effects :
220 * The encoded motion vector is added to the bitstream
222 ***********************************************************CommentEnd********/
225 WriteMVcomponent(
226 Int f_code,
227 Int dmv,
228 Image *bs
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;
237 else
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);
245 bits += f_code - 1;
247 return(bits);
251 /***********************************************************CommentBegin******
253 * -- ScaleMVD -- Scales MVD component acording to the MV range
255 * Purpose :
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.
261 * Description :
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
264 * correct range.
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********/
271 Void
272 ScaleMVD (
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 */
279 Int range;
280 Int scale_factor;
281 Int r_size;
282 Int low;
283 Int high;
284 Int aux;
286 r_size = f_code-1;
287 scale_factor = 1<<r_size;
288 range = 32*scale_factor;
289 low = -range;
290 high = range-1;
291 if (diff_vector < low)
293 diff_vector += 2*range;
295 else if (diff_vector > high)
297 diff_vector -= 2*range;
300 if (diff_vector==0)
302 *vlc_code_mag = 0;
303 *residual = 0;
305 else if (scale_factor==1)
307 *vlc_code_mag = diff_vector;
308 *residual = 0;
310 else
312 aux = ABS(diff_vector) + scale_factor - 1;
313 *vlc_code_mag = aux>>r_size;
315 if (diff_vector<0)
316 *vlc_code_mag = -*vlc_code_mag;
318 *residual = aux & (scale_factor-1);
323 /***********************************************************CommentBegin******
325 * -- find_pmvs --
327 * Purpose :
328 * Makes the motion vectors prediction for block 'block' (0 = whole MB)
330 ***********************************************************CommentEnd********/
332 Void /* MVP/Noel */
333 find_pmvs(
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 ] */
346 Int newgob
349 Float p1x,p2x,p3x;
350 Float p1y,p2y,p3y;
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);
359 Int xB = xM;
360 Int mb_mode, sum;
362 /* MW QPEL 06-JUL-1998 >> */
363 if (quarter_pel)
365 subdim=4;
367 else
369 subdim=2;
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
378 MBs have 4 vectors.
380 This different prediction affects only 16x16 vectors of MBs with
381 transparent blocks.
383 In the current version, we choose for the 16x16 mode the first
384 non-transparent block in the surrounding MBs
387 switch (block)
389 case 0:
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;
393 break;
394 case 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;
398 break;
399 case 2:
400 vec1 = 0 ; yin1 = y ; xin1 = x;
401 vec2 = 3 ; yin2 = y-1; xin2 = x;
402 vec3 = 2 ; yin3 = y-1; xin3 = x+1;
403 break;
404 case 3:
405 vec1 = 3 ; yin1 = y ; xin1 = x-1;
406 vec2 = 0 ; yin2 = y ; xin2 = x;
407 vec3 = 1 ; yin3 = y ; xin3 = x;
408 break;
409 case 4:
410 vec1 = 2 ; yin1 = y ; xin1 = x;
411 vec2 = 0 ; yin2 = y ; xin2 = x;
412 vec3 = 1 ; yin3 = y ; xin3 = x;
413 break;
414 default:
415 printf("Illegal block number in find_pmv (mot_decode.c)");
416 *error_flag = 1;
417 *mvx=*mvy=0;
418 return ;
421 if (block==0)
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)*/)
429 rule1 = 0;
430 else
431 rule1 = 1;
433 if ((y>0 && newgob==0) /*&& ValidCandidateMVP(x,y,xin2,yin2,vec2,xB,transparent_value,
434 MB_decisions,dcsn_data)*/)
435 rule2 = 0;
436 else
437 rule2 = 1;
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)*/)
442 rule3 = 0;
443 else
444 rule3 = 1;
447 else
449 /* check borders for single blocks (advanced mode) */
450 /* rule 1 */
451 /* left border */
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))*/)
456 rule1 = 1;
457 else
458 rule1 = 0;
460 /* rule 2 */
461 /* top border */
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))*/)
466 rule2 = 1;
467 else
468 rule2 = 0;
470 /* rule 3 */
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))*/)
476 rule3 = 1;
477 else
478 rule3 = 0;
482 if (rule1 )
484 p1x = p1y = 0;
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;
494 else
496 p1x = BV(motxdata, xM, xin1, yin1, vec1&0x1, vec1>>1 );
497 p1y = BV(motydata, xM, xin1, yin1, vec1&0x1, vec1>>1 );
500 if (rule2)
502 p2x = p2y = 0 ;
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;
512 else
514 p2x = BV(motxdata, xM, xin2, yin2, vec2&0x1, vec2>>1 );
515 p2y = BV(motydata, xM, xin2, yin2, vec2&0x1, vec2>>1 );
518 if (rule3 )
520 p3x = p3y =0;
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;
530 else
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 */
539 *mvx=*mvy=0;
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 */
548 else
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))));
557 #ifdef _DEBUG_PMVS_
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);
559 #endif
561 return;
565 /***********************************************************CommentBegin******
567 * -- ModeMB -- Get the MB mode
569 * Purpose :
570 * 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);
579 return p[width*j+i];