mot_code.c
上传用户:enenge
上传日期:2007-01-08
资源大小:96k
文件大小:18k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *                                                                        *
  3.  * This code is developed by Adam Li.  This software is an                *
  4.  * implementation of a part of one or more MPEG-4 Video tools as          *
  5.  * specified in ISO/IEC 14496-2 standard.  Those intending to use this    *
  6.  * software module in hardware or software products are advised that its  *
  7.  * use may infringe existing patents or copyrights, and any such use      *
  8.  * would be at such party's own risk.  The original developer of this     *
  9.  * software module and his/her company, and subsequent editors and their  *
  10.  * companies (including Project Mayo), will have no liability for use of  *
  11.  * this software or modifications or derivatives thereof.                 *
  12.  *                                                                        *
  13.  * Project Mayo gives users of the Codec a license to this software       *
  14.  * module or modifications thereof for use in hardware or software        *
  15.  * products claiming conformance to the MPEG-4 Video Standard as          *
  16.  * described in the Open DivX license.                                    *
  17.  *                                                                        *
  18.  * The complete Open DivX license can be found at                         *
  19.  * http://www.projectmayo.com/opendivx/license.php .                      *
  20.  *                                                                        *
  21.  **************************************************************************/
  22. /**************************************************************************
  23.  *
  24.  *  mot_code.c
  25.  *
  26.  *  Copyright (C) 2001  Project Mayo
  27.  *
  28.  *  Adam Li
  29.  *
  30.  *  DivX Advance Research Center <darc@projectmayo.com>
  31.  *
  32.  **************************************************************************/
  33. /* This file contains some functions to code the motion data of the image.*/
  34. /* Some codes of this project come from MoMuSys MPEG-4 implementation.    */
  35. /* Please see seperate acknowledgement file for a list of contributors.   */
  36. #include "vm_common_defs.h"
  37. #include "bitstream.h"
  38. #include "putvlc.h"
  39. /* ------------------------------------------------------------------------- */
  40. /* Specific macros (include references to internal vars. of the functions) */
  41. /* 16x16 MV obtainment */
  42. #define MBV_H(h,v)      (ph[2*(v)*2*hdim+2*(h)])
  43. #define MBV_V(h,v)      (pv[2*(v)*2*hdim+2*(h)])
  44. /* 8x8 MV obtainment */
  45. #define BV_H(h,v,h2,v2) (ph[(2*(v)+(v2))*2*hdim+2*(h)+(h2)])
  46. #define BV_V(h,v,h2,v2) (pv[(2*(v)+(v2))*2*hdim+2*(h)+(h2)])
  47. /* MB mode obtainment */
  48. #define MB_MODE(h,v)    ( ((h)<0||(h)>=hdim||(v)<0||(v)>=vdim ? MBM_OUT : (pm[(v)*hdim+(h)])) )
  49. /* get 8x8 MV component */
  50. #define BV(p,xdim,h,v,h2,v2) (p[(2*(v)+(v2))*(xdim)+2*(h)+(h2)])
  51. /* ------------------------------------------------------------------------- */
  52. /* declaration for functions in this file */
  53. Int WriteMVcomponent(Int f_code, Int dmv, Image *bs);
  54. Void ScaleMVD (Int f_code, Int diff_vector, Int *residual, Int *vlc_code_mag);
  55. Void   find_pmvs (Image *mot_x, Image *mot_y, Image *MB_decisions, Image *B_decisions,
  56. Int x, Int y, Int block, Int transparent_value, Int quarter_pel, Int *error_flag,
  57. Int *mvx, Int *mvy, Int newgob);
  58. SInt ModeMB (Image *MB_decision, Int i, Int j);
  59. /***********************************************************CommentBegin******
  60.  *
  61.  * -- Bits_CountMB_Motion --
  62.  *
  63.  * Purpose :
  64.  *      Encodes the MV's Images acording to modes and alpha Images
  65.  *      (see notes below). The codewords are appended to the bitstream.
  66.  *      Included in text_code.h .
  67.  *
  68.  * Return values :
  69.  *      Int     mv_bits   Returns the number of bits sent to the bitstream
  70.  *
  71.  * Description :
  72.  *      1) No checking is made for the consistence of image sizes
  73.  *      2) It assumes the output image has been previously allocated.
  74.  *      3) Transparent MB's are not coded (no codeword is transmited).
  75.  *      4) Motion vectors for 8x8 transparent blocks within
  76.  *         non-totally-transparent MB's are transmitted as MV (0,0) (not MVD
  77.  *         (0,0)). This is made in the  hope that this MV's are neither
  78.  *         employed for block reconstruction nor for MV prediction.
  79.  *
  80.  ***********************************************************CommentEnd********/
  81. Int
  82. Bits_CountMB_Motion(
  83. Image   *mot_h,   /* <-- motion vectors (Float) - per block    */
  84. Image   *mot_v,   /* <-- motion vectors (Float) - per block    */
  85. Image   *alpha,   /* <-- macroblocks modes (SInt) - per block  */
  86. Image   *modes,   /* <-- macroblocks modes (SInt) - per MB     */
  87. Int     h,   /* <-- horizontal coordinate of the MB       */
  88. Int     v,   /* <-- vertical coordinate of the MB         */
  89. Int     f_code,   /* <-- MV range in 1/2 or 1/4 pel units 1=32,2=64,...,7=2048 */
  90.   /* <-- flag for quarter pel MC mode     */
  91. Int     quarter_pel,       /* MW QPEL 07-JUL-1998 */
  92. Image   *bs,   /* --> output (SInt)                         */
  93. Int     error_res_disable,
  94. Int     after_marker,
  95. Int     **slice_nb,
  96. Int arbitrary_shape
  97. )
  98. {
  99. Int     vdim, hdim;   /* Dimensions in macroblocks */
  100. Float   *ph, *pv;   /* Motion vectors            */
  101. SInt    *pm;   /* Modes                     */
  102. SInt    *pa;   /* Alpha                     */
  103. Int     mode;
  104. Int     bits_mot = 0;
  105. /* From switch statement */
  106. Int     i, error_flag=0,mvx=0,mvy=0;
  107. Float   pred_h, pred_v;
  108. Float   diff_h, diff_v;
  109. Int     bh, bv;
  110. Int     local_f_code;   /* MW QPEL 07-JUL-1998 */
  111. Float   subdim;   /* MW QPEL 07-JUL-1998 */
  112. vdim = (Int)modes->y;
  113. hdim = (Int)modes->x;
  114. ph=(Float*)GetImageData(mot_h);
  115. pv=(Float*)GetImageData(mot_v);
  116. pm=(SInt*)GetImageData(modes);
  117. pa=NULL;//(SInt*)GetImageData(alpha);
  118. /* MW QPEL 07-JUL-1998 >> */
  119. /* Set local_f_code and subdim according to quarter_pel */
  120. if (quarter_pel)
  121. {
  122. local_f_code = f_code+1;
  123. subdim = 4.0;
  124. }
  125. else
  126. {
  127. local_f_code = f_code;
  128. subdim = 2.0;
  129. }
  130. /* << MW QPEL 07-JUL-1998 */
  131. switch (mode=MB_MODE(h,v))
  132. {
  133. case MBM_INTRA:
  134. break;
  135. case MBM_INTER16:
  136. /* Prediction obtainment */
  137. find_pmvs(mot_h,mot_v,modes,alpha,h,v,0,MBM_TRANSPARENT,
  138.   /* MW QPEL 07-JUL-1998 */
  139. quarter_pel,&error_flag,&mvx,&mvy,0);
  140. pred_h=((Float)mvx)/subdim;   /* MW QPEL 07-JUL-1998 */
  141. pred_v=((Float)mvy)/subdim;   /* MW QPEL 07-JUL-1998 */
  142.   /* MW QPEL 07-JUL-1998 */
  143. bits_mot += WriteMVcomponent(local_f_code, (Int)(subdim*(MBV_H(h,v) - pred_h)), bs);
  144.   /* MW QPEL 07-JUL-1998 */
  145. bits_mot += WriteMVcomponent(local_f_code, (Int)(subdim*(MBV_V(h,v) - pred_v)), bs);
  146. break;
  147. case MBM_INTER8:
  148. i=1;
  149. for (bv=0; bv<=1; bv++)
  150. for (bh=0; bh<=1; bh++)
  151. {
  152. find_pmvs(mot_h,mot_v,modes,alpha,h,v,i,MBM_TRANSPARENT,
  153.   /* MW QPEL 07-JUL-1998 */
  154. quarter_pel,&error_flag,&mvx,&mvy,0);
  155. pred_h=((Float)mvx)/subdim;   /* MW QPEL 07-JUL-1998 */
  156. pred_v=((Float)mvy)/subdim;   /* MW QPEL 07-JUL-1998 */
  157. i++;
  158. diff_h=BV_H(h,v,bh,bv)-pred_h;
  159. diff_v=BV_V(h,v,bh,bv)-pred_v;
  160.   /* MW QPEL 07-JUL-1998 */
  161. bits_mot += WriteMVcomponent(local_f_code, (Int)(subdim*diff_h), bs);
  162.   /* MW QPEL 07-JUL-1998 */
  163. bits_mot += WriteMVcomponent(local_f_code, (Int)(subdim*diff_v), bs);
  164. }
  165. break;
  166. }
  167. return bits_mot;
  168. }
  169. /***********************************************************CommentBegin******
  170.  *
  171.  * -- WriteMVcomponent -- Encodes a single motion vector component
  172.  *
  173.  * Purpose :
  174.  *      Scales the motion vector difference, VLC the most significant part,
  175.  *      then outputs the residual (least significant part) as a FLC.
  176.  *
  177.  * Arguments in :
  178.  *      Int   f_code,         Range for MV, (1/2/3) => (32/64/128) 1/2 units
  179.  *      Float diff_vector,    MV Diff. component (in 1/2 units (in field))
  180.  *      Image bs              Bitstream output
  181.  *
  182.  * Return values :
  183.  *      The number of bits for this encoding
  184.  *
  185.  * Side effects :
  186.  *      The encoded motion vector is added to the bitstream
  187.  *
  188.  ***********************************************************CommentEnd********/
  189. Int
  190. WriteMVcomponent(
  191. Int     f_code,
  192. Int     dmv,
  193. Image   *bs
  194. )
  195. {
  196. Int   residual, vlc_code_mag, bits, entry;
  197. ScaleMVD(f_code, dmv, &residual, &vlc_code_mag);
  198. if (vlc_code_mag < 0)
  199. entry = vlc_code_mag + 65;
  200. else
  201. entry = vlc_code_mag;
  202. bits = PutMV (entry, bs);
  203. if ((f_code != 1) && (vlc_code_mag != 0))
  204. {
  205. BitstreamPutBits(bs, residual, f_code-1);
  206. bits += f_code - 1;
  207. }
  208. return(bits);
  209. }
  210. /***********************************************************CommentBegin******
  211.  *
  212.  * -- ScaleMVD -- Scales MVD component acording to the MV range
  213.  *
  214.  * Purpose :
  215.  *      Scales a Motion Vector Difference (MVD) component (x or y) according
  216.  *      to the MV range. The maximum range that can be represented is
  217.  *      determined by the f_code encoded in the VOP header. Two values,
  218.  *      vlc_code_mag and residual, are generated.
  219.  *
  220.  * Description :
  221.  *      1) The range of the MV's is computed according to the f_code.
  222.  *      2) The range of the MVD component is reduced to fall in the
  223.  *         correct range.
  224.  *      3) Two values are generated:
  225.  *         vlc_code_mag: It will be VLC coded in other function.
  226.  *         residual    : It will be FLC coded in other function.
  227.  *
  228.  ***********************************************************CommentEnd********/
  229. Void
  230. ScaleMVD (
  231. Int  f_code,   /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048     */
  232. Int  diff_vector,   /* <-- MV Difference commponent in 1/2 units           */
  233. Int  *residual,   /* --> value to be FLC coded                           */
  234. Int  *vlc_code_mag   /* --> value to be VLC coded                           */
  235. )
  236. {
  237. Int   range;
  238. Int   scale_factor;
  239. Int   r_size;
  240. Int   low;
  241. Int   high;
  242. Int   aux;
  243. r_size = f_code-1;
  244. scale_factor = 1<<r_size;
  245. range = 32*scale_factor;
  246. low   = -range;
  247. high  =  range-1;
  248. if (diff_vector < low)
  249. {
  250. diff_vector += 2*range;
  251. }
  252. else if (diff_vector > high)
  253. {
  254. diff_vector -= 2*range;
  255. }
  256. if (diff_vector==0)
  257. {
  258. *vlc_code_mag = 0;
  259. *residual = 0;
  260. }
  261. else if (scale_factor==1)
  262. {
  263. *vlc_code_mag = diff_vector;
  264. *residual = 0;
  265. }
  266. else
  267. {
  268. aux = ABS(diff_vector) + scale_factor - 1;
  269. *vlc_code_mag = aux>>r_size;
  270. if (diff_vector<0)
  271. *vlc_code_mag = -*vlc_code_mag;
  272. *residual = aux & (scale_factor-1);
  273. }
  274. }
  275. /***********************************************************CommentBegin******
  276.  *
  277.  * -- find_pmvs --
  278.  *
  279.  * Purpose :
  280.  *      Makes the motion vectors prediction for block 'block' (0 = whole MB)
  281.  *
  282.  ***********************************************************CommentEnd********/
  283. Void   /* MVP/Noel */
  284. find_pmvs(
  285. Image  *mot_x,   /* x-motion vector field                             */
  286. Image  *mot_y,   /* y-motion vector field                             */
  287. Image  *MB_decisions,   /* MB modes                                          */
  288. Image  *B_decisions,   /* field with number of vectors per MB               */
  289. Int    x,   /* xpos of the MB in multiples of 16 (hor coord)     */
  290. Int    y,   /* ypos of the MB in multiples of 16 (ver coord)     */
  291. Int    block,   /* block number (0 if one vector per MB, 1..4 else)  */
  292. Int    transparent_value,   /* value of the transparency (0=enc, 2=dec)     */
  293. Int    quarter_pel,   /* MW QPEL 06-JUL-1998 */   /* flag to indicate quarter pel mc                   */
  294. Int    *error_flag,   /* set if an error occured                      */
  295. Int    *mvx,   /* hor predicted motion vector [ in half-pixels units ]  */
  296. Int    *mvy,   /* ver predicted motion vector [ in half-pixels units ]  */
  297. Int    newgob
  298. )
  299. {
  300. Float   p1x,p2x,p3x;
  301. Float   p1y,p2y,p3y;
  302. Int     xin1, xin2, xin3;
  303. Int     yin1, yin2, yin3;
  304. Int     vec1, vec2, vec3;
  305. Int     rule1, rule2, rule3;
  306. Int     subdim;   /* MW QPEL 06-JUL-1998 */
  307. Float   *motxdata = (Float *) GetImageData(mot_x);
  308. Float   *motydata = (Float *) GetImageData(mot_y);
  309. Int     xM = GetImageSizeX(mot_x);
  310. Int xB = xM;
  311. Int     mb_mode, sum;
  312. /* MW QPEL 06-JUL-1998 >> */
  313. if (quarter_pel)
  314. {
  315. subdim=4;
  316. }
  317. else
  318. {
  319. subdim=2;
  320. }
  321. /* << MW QPEL 06-JUL-1998 */
  322. /* In a previous version, a MB vector (block = 0) was predicted the same way
  323.    as block 1, which is the most likely interpretation of the VM.
  324.    Therefore, if we have advanced pred. mode, and if all MBs around have
  325.    only one 16x16 vector each, we chose the appropiate block as if these
  326.    MBs have 4 vectors.
  327.    This different prediction affects only 16x16 vectors of MBs with
  328.    transparent blocks.
  329.    In the current version, we choose for the 16x16 mode the first
  330. non-transparent block in the surrounding MBs
  331. */
  332. switch (block)
  333. {
  334. case 0:
  335. vec1 = 1 ; yin1 = y  ; xin1 = x-1;
  336. vec2 = 2 ; yin2 = y-1; xin2 = x;
  337. vec3 = 2 ; yin3 = y-1; xin3 = x+1;
  338. break;
  339. case 1:
  340. vec1 = 1 ; yin1 = y  ; xin1 = x-1;
  341. vec2 = 2 ; yin2 = y-1; xin2 = x;
  342. vec3 = 2 ; yin3 = y-1; xin3 = x+1;
  343. break;
  344. case 2:
  345. vec1 = 0 ; yin1 = y  ; xin1 = x;
  346. vec2 = 3 ; yin2 = y-1; xin2 = x;
  347. vec3 = 2 ; yin3 = y-1; xin3 = x+1;
  348. break;
  349. case 3:
  350. vec1 = 3 ; yin1 = y  ; xin1 = x-1;
  351. vec2 = 0 ; yin2 = y  ; xin2 = x;
  352. vec3 = 1 ; yin3 = y  ; xin3 = x;
  353. break;
  354. case 4:
  355. vec1 = 2 ; yin1 = y  ; xin1 = x;
  356. vec2 = 0 ; yin2 = y  ; xin2 = x;
  357. vec3 = 1 ; yin3 = y  ; xin3 = x;
  358. break;
  359. default:
  360. printf("Illegal block number in find_pmv (mot_decode.c)");
  361. *error_flag = 1;
  362. *mvx=*mvy=0;
  363. return ;
  364. }
  365. if (block==0)
  366. {
  367. /* according to the motion encoding, we must choose a first non-transparent
  368.    block in the surrounding MBs (16-mode)
  369.  */
  370. if (x>0 /*&& ValidCandidateMVP(x,y,xin1,yin1,vec1,xB,transparent_value,
  371. MB_decisions,dcsn_data)*/)
  372. rule1 = 0;
  373. else
  374. rule1 = 1;
  375. if ((y>0 && newgob==0) /*&& ValidCandidateMVP(x,y,xin2,yin2,vec2,xB,transparent_value,
  376. MB_decisions,dcsn_data)*/)
  377. rule2 = 0;
  378. else
  379. rule2 = 1;
  380. if ((x != xB/2 -1) &&
  381. ((y>0 && newgob==0)) /*&& ValidCandidateMVP(x,y,xin3,yin3,vec3,xB,transparent_value,
  382. MB_decisions,dcsn_data)*/)
  383. rule3 = 0;
  384. else
  385. rule3 = 1;
  386. }
  387. else
  388. {
  389. /* check borders for single blocks (advanced mode) */
  390. /* rule 1 */
  391.   /* left border */
  392. if (((block == 1 || block == 3) && (x == 0))  /*||
  393. /* left block/MB is transparent *
  394. (!ValidCandidateMVP(x,y,xin1,yin1,vec1,xB,transparent_value,
  395. MB_decisions,dcsn_data))*/)
  396. rule1 = 1;
  397. else
  398. rule1 = 0;
  399. /* rule 2 */
  400.   /* top border */
  401. if (((block == 1 || block == 2) && (y == 0))  /*||
  402. /* top block/MB is transparent *
  403. (!ValidCandidateMVP(x,y,xin2,yin2,vec2,xB,transparent_value,
  404. MB_decisions,dcsn_data))*/)
  405. rule2 = 1;
  406. else
  407. rule2 = 0;
  408. /* rule 3 */
  409. if (((block == 1 || block == 2) && (x == xB/2 -1 || y == 0)) /*||
  410. /* right & top border *
  411. /* right block/MB is transparent *
  412. (!ValidCandidateMVP(x,y,xin3,yin3,vec3,xB,transparent_value,
  413. MB_decisions,dcsn_data))*/)
  414. rule3 = 1;
  415. else
  416. rule3 = 0;
  417. }
  418. if (rule1 )
  419. {
  420. p1x = p1y = 0;
  421. }
  422. else if (((mb_mode = ModeMB(MB_decisions,xin1,yin1)) >= MBM_FIELD00) && (mb_mode <= MBM_FIELD11))
  423. {
  424. /* MW QPEL 06-JUL-1998 */
  425. sum = subdim*(BV(motxdata, xM, xin1, yin1, 0, 0) + BV(motxdata, xM, xin1, yin1, 1, 0));
  426. p1x = (Float)((sum & 3) ? ((sum | 2) >> 1) : (sum >> 1))/(Float)subdim;
  427. sum = subdim*(BV(motydata, xM, xin1, yin1, 0, 0) + BV(motydata, xM, xin1, yin1, 1, 0));
  428. p1y = (Float)((sum & 3) ? ((sum | 2) >> 1) : (sum >> 1))/(Float)subdim;
  429. }
  430. else
  431. {
  432. p1x = BV(motxdata, xM, xin1, yin1, vec1&0x1, vec1>>1 );
  433. p1y = BV(motydata, xM, xin1, yin1, vec1&0x1, vec1>>1 );
  434. }
  435. if (rule2)
  436. {
  437. p2x = p2y = 0 ;
  438. }
  439. else if (((mb_mode = ModeMB(MB_decisions,xin2,yin2)) >= MBM_FIELD00) && (mb_mode <= MBM_FIELD11))
  440. {
  441. /* MW QPEL 06-JUL-1998 */
  442. sum = subdim*(BV(motxdata, xM, xin2, yin2, 0, 0) + BV(motxdata, xM, xin2, yin2, 1, 0));
  443. p2x = (Float)((sum & 3) ? ((sum | 2) >> 1) : (sum >> 1))/(Float)subdim;
  444. sum = subdim*(BV(motydata, xM, xin2, yin2, 0, 0) + BV(motydata, xM, xin2, yin2, 1, 0));
  445. p2y = (Float)((sum & 3) ? ((sum | 2) >> 1) : (sum >> 1))/(Float)subdim;
  446. }
  447. else
  448. {
  449. p2x = BV(motxdata, xM, xin2, yin2, vec2&0x1, vec2>>1 );
  450. p2y = BV(motydata, xM, xin2, yin2, vec2&0x1, vec2>>1 );
  451. }
  452. if (rule3 )
  453. {
  454. p3x = p3y =0;
  455. }
  456. else if (((mb_mode = ModeMB(MB_decisions,xin3,yin3)) >= MBM_FIELD00) && (mb_mode <= MBM_FIELD11))
  457. {
  458. /* MW QPEL 06-JUL-1998 */
  459. sum = subdim*(BV(motxdata, xM, xin3, yin3, 0, 0) + BV(motxdata, xM, xin3, yin3, 1, 0));
  460. p3x = (Float)((sum & 3) ? ((sum | 2) >> 1) : (sum >> 1))/(Float)subdim;
  461. sum = subdim*(BV(motydata, xM, xin3, yin3, 0, 0) + BV(motydata, xM, xin3, yin3, 1, 0));
  462. p3y = (Float)((sum & 3) ? ((sum | 2) >> 1) : (sum >> 1))/(Float)subdim;
  463. }
  464. else
  465. {
  466. p3x = BV(motxdata, xM, xin3, yin3, vec3&0x1, vec3>>1 );
  467. p3y = BV(motydata, xM, xin3, yin3, vec3&0x1, vec3>>1 );
  468. }
  469. if (rule1 && rule2 && rule3 )
  470. {
  471. /* all MBs are outside the VOP */
  472. *mvx=*mvy=0;
  473. }
  474. else if (rule1+rule2+rule3 == 2)
  475. {
  476. /* two of three are zero */
  477. /* MW QPEL 06-JUL-1998 */
  478. *mvx=(Int) subdim*(p1x+p2x+p3x);   /* MW QPEL 06-JUL-1998 */
  479. *mvy=(Int) subdim*(p1y+p2y+p3y);   /* MW QPEL 06-JUL-1998 */
  480. }
  481. else
  482. {
  483. /* MW QPEL 06-JUL-1998 */
  484.   /* MW QPEL 06-JUL-1998 */
  485. *mvx=(Int)(subdim*(p1x+p2x+p3x-MAX(p1x,MAX(p2x,p3x))-MIN(p1x,MIN(p2x,p3x))));
  486.   /* MW QPEL 06-JUL-1998 */
  487. *mvy=(Int)(subdim*(p1y+p2y+p3y-MAX(p1y,MAX(p2y,p3y))-MIN(p1y,MIN(p2y,p3y))));
  488. }
  489. #ifdef _DEBUG_PMVS_
  490. fprintf(stdout,"find_pmvs (%2d,%2d, rule %1d%1d%1d) :np1 %6.2f / %6.2fnp2 %6.2f / %6.2fnp3 %6.2f / %6.2fn",x,y,rule1,rule2,rule3,p1x,p1y,p2x,p2y,p3x,p3y);
  491. #endif
  492. return;
  493. }
  494. /***********************************************************CommentBegin******
  495.  *
  496.  * -- ModeMB -- Get the MB mode
  497.  *
  498.  * Purpose :
  499.  * Get the MB mode
  500.  *
  501.  ***********************************************************CommentEnd********/
  502. SInt ModeMB (Image *MB_decision, Int i, Int j)
  503. {
  504. Int   width = MB_decision->x;
  505. SInt  *p = (SInt *)GetImageData(MB_decision);
  506. return p[width*j+i];
  507. }