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

流媒体/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_est_comp.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 do motion estimation and          */
  34. /* for the current image in one pass.                                     */
  35. /* Some codes of this project come from MoMuSys MPEG-4 implementation.    */
  36. /* Please see seperate acknowledgement file for a list of contributors.   */
  37. #include "vm_common_defs.h"
  38. #include "mom_util.h"
  39. #include "mot_util.h"
  40. #include "mot_est_mb.h"
  41. extern FILE *ftrace;
  42. /* For correct rounding of chrominance vectors */
  43. static Int roundtab16[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};
  44. Void   MotionEstCompPicture (
  45. SInt *curr,
  46. SInt *prev,
  47. SInt *prev_ipol_y,
  48. SInt *prev_ipol_u,
  49. SInt *prev_ipol_v,
  50. Int prev_x,
  51. Int prev_y,
  52. Int vop_width,
  53. Int vop_height,
  54. Int enable_8x8_mv,
  55. Int edge,
  56. Int sr_for,
  57. Int f_code,
  58. Int rounding_type,
  59. Int br_x,
  60. Int br_y,
  61. Int br_width,
  62. Int br_height,
  63. SInt *curr_comp_y,
  64. SInt *curr_comp_u,
  65. SInt *curr_comp_v,
  66. Float *mad,
  67. Float *mv16_w,
  68. Float *mv16_h,
  69. Float *mv8_w,
  70. Float *mv8_h,
  71. SInt *mode16
  72. );
  73. Void GetPred_Chroma (
  74. Int x_curr,
  75. Int y_curr,
  76. Int dx,
  77. Int dy,
  78. SInt *prev_u,
  79. SInt *prev_v,
  80. SInt *comp_u,
  81. SInt *comp_v,
  82. Int width,
  83. Int width_prev,
  84. Int prev_x_min,
  85. Int prev_y_min,
  86. Int prev_x_max,
  87. Int prev_y_max,
  88. Int rounding_control
  89. );
  90. /***********************************************************CommentBegin******
  91.  *
  92.  * -- MotionEstimationCompensation -- Estimates the motion vectors and 
  93.  * do motion compensation
  94.  *
  95.  * Purpose :
  96.  *      Estimates the motion vectors in advanced/not_advanced unrestricted
  97.  *      mode. The output are four images containing x/y components of
  98.  *      MV's (one per 8x8 block), modes (one value per MB). The motion
  99.  * compensation is also performed.
  100.  *
  101.  * Description :
  102.  *      1)  memory is allocated for these images.
  103.  *      2)  mot_x/mot_y have 4 identical vector for a MB coded inter 16
  104.  *      3)  mot_x/mot_y have 4 identical zero vectors for a MB coded intra
  105.  *      4)  if _NO_ESTIMATION_ is used, the output is the following:
  106.  *              - mot_x     :    all MV's are 0.0
  107.  *              - mot_y     :    all MV's are 0.0
  108.  *              - mode      :    all modes are MB_INTRA (IGNORING THE SHAPE)
  109.  *
  110.  *      Based on: CodeOneOrTwo (TMN5, coder.c)
  111.  *
  112.  ***********************************************************CommentEnd********/
  113. Void
  114. MotionEstimationCompensation (
  115. Vop    *curr_vop,   /* <-- current Vop (for luminance)                  */
  116. Vop    *prev_rec_vop,   /* <-- reference Vop (reconstructed)(1/2 pixel)     */
  117. Int    enable_8x8_mv,   /* <-- 8x8 MV (=1) or only 16x16 MV (=0)            */
  118. Int    edge,   /* <-- restricted(==0)/unrestricted(==edge) mode    */
  119. Int    f_code,   /* <-- MV search range 1/2 pel: 1=32,2=64,...,7=2048*/
  120. Vop    *curr_comp_vop,   /* <-> motion compensated current VOP   */
  121. Float  *mad,   /* <-> mad value of the ME/MC result                */
  122. Image  **mot_x,   /* --> horizontal MV coordinates                    */
  123. Image  **mot_y,   /* --> vertical MV coordinates                      */
  124. Image  **mode   /* --> modes for each MB                            */
  125. )
  126. {
  127. Image   *pr_rec_y;   /* Reference image (reconstructed)   */
  128. Image   *pi_y;   /* Interp.ref.image Y                */
  129. Image   *mode16;
  130. Image   *mv16_w;
  131. Image   *mv16_h;
  132. Image   *mv8_w;
  133. Image   *mv8_h;
  134. SInt    *prev_ipol_y,   /* Interp.ref.image Y (subimage)            */
  135. *prev_orig_y;   /* Ref. original image with edge (subimage) */
  136. Int     vop_width, vop_height;
  137. Int     br_x;
  138. Int     br_y;
  139. Int     br_height;
  140. Int     br_width;
  141. Int     mv_h, mv_w;
  142. /*GETBBR*/
  143. br_y=curr_vop->ver_spat_ref;
  144. br_x=curr_vop->hor_spat_ref;
  145. br_height=curr_vop->height;
  146. br_width=curr_vop->width;
  147. mv_h=br_height/MB_SIZE;
  148. mv_w=br_width/MB_SIZE;
  149. /*
  150.  ** WE SUPPOSE prev_rec_vop & prev_vop HAVE EQUAL SIZE AND POSITIONS
  151.  */
  152. vop_width=prev_rec_vop->width;
  153. vop_height=prev_rec_vop->height;
  154. /*
  155.  ** Get images and interpolate them
  156.  */
  157. pr_rec_y = prev_rec_vop->y_chan;
  158. prev_orig_y = (SInt*)GetImageData(pr_rec_y);
  159. pi_y = AllocImage (2*vop_width, 2*vop_height, SHORT_TYPE);
  160. InterpolateImage(pr_rec_y, pi_y, GetVopRoundingType(curr_vop));
  161. prev_ipol_y = (SInt*)GetImageData(pi_y);
  162. /*
  163.  * allocate memory for mv's and modes data
  164.  *
  165.  */
  166. mode16=AllocImage (mv_w,mv_h,SHORT_TYPE);
  167. SetConstantImage (mode16,(Float)MBM_INTRA);
  168. /*
  169.  **   mv16 have 2x2 repeted the mv value to share the functions of
  170.  **   mv prediction between CodeVopVotion and MotionEstimation
  171.  */
  172. mv16_w=AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
  173. mv16_h=AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
  174. mv8_w =AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
  175. mv8_h =AllocImage (mv_w*2,mv_h*2,FLOAT_TYPE);
  176. SetConstantImage (mv16_h,+0.0);
  177. SetConstantImage (mv16_w,+0.0);
  178. SetConstantImage (mv8_h,+0.0);
  179. SetConstantImage (mv8_w,+0.0);
  180. SetConstantImage (curr_comp_vop->u_chan, 0);
  181. SetConstantImage (curr_comp_vop->v_chan, 0);
  182. /* Compute motion vectors and modes for each MB
  183.  ** (TMN5 functions)
  184.  */
  185. MotionEstCompPicture(
  186. (SInt *)GetImageData(GetVopY(curr_vop)), //curr_vop,
  187. prev_orig_y,   /* Y padd with edge */
  188. prev_ipol_y,   /* Y interpolated (from pi_y) */
  189. (SInt*)GetImageData(prev_rec_vop->u_chan) + (vop_width/2) * (16/2) + (16/2),
  190. (SInt*)GetImageData(prev_rec_vop->v_chan) + (vop_width/2) * (16/2) + (16/2),
  191. prev_rec_vop->hor_spat_ref,
  192. prev_rec_vop->ver_spat_ref,
  193. vop_width,vop_height,
  194. enable_8x8_mv,
  195. edge,
  196. GetVopSearchRangeFor(curr_vop), 
  197. f_code,
  198. GetVopRoundingType(curr_vop),
  199. br_x,br_y,   /* pos. of the bounding rectangle */
  200. br_width,br_height,   /* dims. of the bounding rectangle */
  201. (SInt*)GetImageData(curr_comp_vop->y_chan),
  202. (SInt*)GetImageData(curr_comp_vop->u_chan),
  203. (SInt*)GetImageData(curr_comp_vop->v_chan),
  204. mad,
  205. (Float*)GetImageData(mv16_w),
  206. (Float*)GetImageData(mv16_h),
  207. (Float*)GetImageData(mv8_w),
  208. (Float*)GetImageData(mv8_h),
  209. (SInt*) GetImageData(mode16)
  210. );
  211. /* Convert output to MOMUSYS format */
  212. GetMotionImages(mv16_w, mv16_h, mv8_w, mv8_h, mode16, mot_x, mot_y, mode);
  213. /* Deallocate dynamic memory */
  214. FreeImage(mv16_w); FreeImage(mv16_h);
  215. FreeImage(mv8_w);  FreeImage(mv8_h);
  216. FreeImage(mode16);
  217. FreeImage(pi_y);
  218. }
  219. /***********************************************************CommentBegin******
  220.  *
  221.  * -- MotionEstCompPicture -- Computes MV's and predictor errors and 
  222.  * do motion compensation
  223.  *
  224.  * Purpose :
  225.  *      Computes MV's (8x8 and 16x16) and predictor errors for the whole
  226.  *      vop. Perform motion compensation for the whole vop.
  227.  *
  228.  ***********************************************************CommentEnd********/
  229. Void
  230. MotionEstCompPicture(
  231. SInt    *curr,   /* <-- Current VOP                                  */
  232. SInt    *prev,   /* <-- Original Y padd with edge                    */
  233. SInt    *prev_ipol,   /* <-- Y interpolated (from pi_y)                  */
  234. SInt    *prev_u,   /* <-- Original U padd with edge                   */
  235. SInt    *prev_v,   /* <-- Original V padd with edge                  */
  236. Int     prev_x,   /* <-- absolute horiz. position of previous vop     */
  237. Int     prev_y,   /* <-- absolute verti. position of  previous vop    */
  238. Int     vop_width,   /* <-- horizontal previous vop dimension            */
  239. Int     vop_height,   /* <-- vertical previous vop dimension              */
  240. Int     enable_8x8_mv,   /* <-- 8x8 MV (=1) or only 16x16 MV (=0)            */
  241. Int     edge,   /* <-- edge arround the reference vop               */
  242. Int sr_for,   /* <-- forward search range                         */
  243. Int     f_code,          /* MW QPEL 07-JUL-1998 *//* <-- MV search range 1/2 or 1/4 pel: 1=32,2=64,...,7=2048*/
  244. Int rounding_type,   /* <-- The rounding type of the current vop         */
  245. Int     br_x,   /* <-- absolute horiz. position of the current vop  */
  246. Int     br_y,   /* <-- absolute verti. position of the current vop  */
  247. Int     br_width,   /* <-- current bounding rectangule width            */
  248. Int     br_height,   /* <-- current bounding rectangle height            */
  249. SInt *curr_comp_y,   /* <-> motion compensated current Y                 */
  250. SInt *curr_comp_u,   /* <-> motion compensated current U                 */
  251. SInt *curr_comp_v,   /* <-> motion compensated current V                 */
  252. Float *mad,   /* <-> the mad value of current ME/MC result        */
  253. Float   *mv16_w,   /* --> predicted horizontal 16x16 MV(if approp.)    */
  254. Float   *mv16_h,   /* --> predicted vertical 16x16 MV  (if approp.)    */
  255. Float   *mv8_w,   /* --> predicted horizontal 8x8 MV  (if approp.)    */
  256. Float   *mv8_h,   /* --> predicted vertical 8x8 MV    (if approp.)    */
  257. SInt    *mode16   /* --> mode of the preditect motion vector          */
  258. )
  259. {
  260. Int i, j, k;
  261. SInt curr_mb[MB_SIZE][MB_SIZE];
  262. SInt curr_comp_mb_16[MB_SIZE][MB_SIZE];
  263. SInt curr_comp_mb_8[MB_SIZE][MB_SIZE];
  264. Int sad8 = MV_MAX_ERROR, sad16, sad;
  265. Int imas_w, imas_h, Mode;
  266. Int posmode, pos16, pos8;
  267. Int min_error16,
  268. min_error8_0, min_error8_1, min_error8_2, min_error8_3;
  269. // SInt *curr = (SInt *)GetImageData(GetVopY(curr_vop));
  270. /***************************************************************************
  271. array of flags, which contains for the MB and for each one of the 4 Blocks
  272. the following info sequentially:
  273.   xm, 1 if the lower search (x axis) is completed (no 1/2 search can be done)
  274.  0, do 1/2 search in the lower bound (x axis)
  275.   xM, 1 if the upper search (x axis) is completed (no 1/2 search can be done)
  276.  0, do 1/2 search in the upper bound (x axis)
  277.   ym, 1 if the lower search (y axis) is completed (no 1/2 search can be done)
  278.  0, do 1/2 search in the lower bound (y axis)
  279.   yM, 1 if the upper search (y axis) is completed (no 1/2 search can be done)
  280.  0, do 1/2 search in the upper bound (y axis)
  281. ***************************************************************************/
  282. SInt *halfpelflags;
  283. Float hint_mv_w, hint_mv_h;
  284. Int xsum,ysum,dx,dy;
  285. Int prev_x_min,prev_x_max,prev_y_min,prev_y_max;
  286. prev_x_min = 2 * prev_x + 2 * 16;
  287. prev_y_min = 2 * prev_y + 2 * 16;
  288. prev_x_max = prev_x_min + 2 * vop_width - 4 * 16;
  289. prev_y_max = prev_y_min + 2 * vop_height - 4 * 16; 
  290. imas_w=br_width/MB_SIZE;
  291. imas_h=br_height/MB_SIZE;
  292. /* Do motion estimation and store result in array */
  293. halfpelflags=(SInt*)malloc(5*4*sizeof(SInt));
  294. /* halfpelflags=(SInt*)malloc(9*4*sizeof(SInt)); */
  295. sad = 0;
  296. for ( j=0; j< (br_height/MB_SIZE); j++)
  297. {
  298. hint_mv_w = hint_mv_h = 0.f;
  299. for ( i=0; i< (br_width/MB_SIZE); i++)
  300. {
  301. /* Integer pel search */
  302. Int min_error;
  303. posmode =          j * imas_w +   i;
  304. pos16   = pos8 = 2*j*2*imas_w + 2*i;
  305. MBMotionEstimation(curr,
  306. prev, br_x, br_y,
  307. br_width, i, j, prev_x, prev_y,
  308. vop_width, vop_height, enable_8x8_mv, edge,
  309. f_code, sr_for, 
  310. hint_mv_w, hint_mv_h, // the hint seeds
  311. mv16_w, mv16_h,
  312. mv8_w, mv8_h, &min_error, halfpelflags);
  313. /* Inter/Intra decision */
  314. Mode = ChooseMode(curr, 
  315. i*MB_SIZE,j*MB_SIZE, min_error, br_width);
  316. hint_mv_w = mv16_w[pos16];
  317. hint_mv_h = mv16_h[pos16];
  318. LoadArea(curr, i*MB_SIZE, j*MB_SIZE, 16, 16, br_width, (SInt *)curr_mb);
  319. /* 0==MBM_INTRA,1==MBM_INTER16||MBM_INTER8 */
  320. if ( Mode != 0)
  321. {
  322. FindSubPel (i*MB_SIZE,j*MB_SIZE, prev_ipol,
  323. &curr_mb[0][0], 16, 16 , 0,
  324. br_x-prev_x,br_y-prev_y,vop_width, vop_height,
  325. edge, halfpelflags, &curr_comp_mb_16[0][0],
  326. &mv16_w[pos16], &mv16_h[pos16], &min_error16);
  327. /* sad16(0,0) already decreased by Nb/2+1 in FindHalfPel() */
  328. sad16 = min_error16;
  329. mode16[posmode] = MBM_INTER16;
  330. if (enable_8x8_mv)
  331. {
  332. xsum = 0; ysum = 0;
  333. FindSubPel(i*MB_SIZE, j*MB_SIZE, prev_ipol,
  334. &curr_mb[0][0], 8, 8 , 0,
  335. br_x-prev_x,br_y-prev_y, vop_width, vop_height,
  336. edge, halfpelflags, &curr_comp_mb_8[0][0],
  337. &mv8_w[pos8], &mv8_h[pos8], &min_error8_0);
  338. xsum += (Int)(2*(mv8_w[pos8]));
  339. ysum += (Int)(2*(mv8_h[pos8]));
  340. FindSubPel(i*MB_SIZE, j*MB_SIZE, prev_ipol,
  341. &curr_mb[0][8], 8, 8 , 1,
  342. br_x-prev_x,br_y-prev_y, vop_width,vop_height,
  343. edge, halfpelflags, &curr_comp_mb_8[0][8],
  344. &mv8_w[pos8+1], &mv8_h[pos8+1], &min_error8_1);
  345. xsum += (Int)(2*(mv8_w[pos8+1]));
  346. ysum += (Int)(2*(mv8_h[pos8+1]));
  347. pos8+=2*imas_w;
  348. FindSubPel(i*MB_SIZE, j*MB_SIZE, prev_ipol,
  349. &curr_mb[8][0], 8, 8 , 2,
  350. br_x-prev_x,br_y-prev_y, vop_width,vop_height,
  351. edge, halfpelflags, &curr_comp_mb_8[8][0], 
  352. &mv8_w[pos8], &mv8_h[pos8], &min_error8_2);
  353. xsum += (Int)(2*(mv8_w[pos8]));
  354. ysum += (Int)(2*(mv8_h[pos8]));
  355. FindSubPel(i*MB_SIZE, j*MB_SIZE, prev_ipol, 
  356. &curr_mb[8][8], 8, 8 , 3,
  357. br_x-prev_x,br_y-prev_y, vop_width,vop_height,
  358. edge, halfpelflags, &curr_comp_mb_8[8][8], 
  359. &mv8_w[pos8+1], &mv8_h[pos8+1], &min_error8_3);
  360. xsum += (Int)(2*(mv8_w[pos8+1]));
  361. ysum += (Int)(2*(mv8_h[pos8+1]));
  362. sad8 = min_error8_0+min_error8_1+min_error8_2+min_error8_3;
  363. /* Choose 8x8 or 16x16 vectors */
  364. if (sad8 < (sad16 -(128+1)))
  365. mode16[posmode] = MBM_INTER8;
  366. }   /* end of enable_8x8_mv mode */
  367. /* When choose 16x16 vectors */
  368. /* sad16(0,0) was decreased by MB_Nb, now add it back */
  369. if ((mv16_w[pos16]==0.0) && (mv16_h[pos16]==0.0) && (mode16[posmode]==MBM_INTER16))
  370. sad16 += 128+1;
  371. /* calculate motion vectors for chroma compensation */
  372. if(mode16[posmode] == MBM_INTER8)
  373. {
  374. dx = SIGN (xsum) * (roundtab16[ABS (xsum) % 16] + (ABS (xsum) / 16) * 2);
  375. dy = SIGN (ysum) * (roundtab16[ABS (ysum) % 16] + (ABS (ysum) / 16) * 2);
  376. sad += sad8;
  377. }
  378. else /* mode == MBM_INTER16 */
  379. {
  380. dx = (Int)(2 * mv16_w[pos16]);
  381. dy = (Int)(2 * mv16_h[pos16]);
  382. dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
  383. dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
  384. sad += sad16;
  385. }
  386. GetPred_Chroma (i*MB_SIZE, j*MB_SIZE, dx, dy, 
  387. prev_u, prev_v, curr_comp_u, curr_comp_v,
  388. br_width, vop_width,
  389. prev_x_min/4,prev_y_min/4,prev_x_max/4,prev_y_max/4, rounding_type);
  390. }   /* end of mode non zero */
  391. else   /* mode = 0 INTRA */
  392. {
  393. mode16[posmode] = MBM_INTRA;
  394. for (k = 0; k < MB_SIZE*MB_SIZE; k++) 
  395. {
  396. // for INTRA MB, set compensated 0 to generate correct error image
  397. curr_comp_mb_16[k/MB_SIZE][k%MB_SIZE] = 0;
  398. // for INTRA_MB, SAD is recalculated from image instead of using min_error
  399. sad += curr_mb[k/MB_SIZE][k%MB_SIZE];
  400. }
  401. }
  402. if (mode16[posmode] == MBM_INTER8)
  403. SetArea((SInt*)curr_comp_mb_8, i*MB_SIZE, j*MB_SIZE, 16, 16, br_width, curr_comp_y);
  404. else
  405. SetArea((SInt*)curr_comp_mb_16, i*MB_SIZE, j*MB_SIZE, 16, 16, br_width, curr_comp_y);
  406. }   /* end of i loop */
  407. } /* end of j loop */
  408. *mad = (float)sad/(br_width*br_height);
  409. free((Char*)halfpelflags);
  410. return;
  411. }
  412. /***********************************************************CommentBegin******
  413.  *
  414.  * unrestricted_MC_chro
  415.  *
  416.  * Purpose :
  417.  * To make unrestricted MC
  418.  *
  419.  ***********************************************************CommentEnd********/
  420. /*Int unrestricted_MC_chro(Int x,Int y, Int npix,
  421. Int prev_x_min,Int prev_y_min,
  422. Int prev_x_max, Int prev_y_max)
  423. {
  424. if (x < prev_x_min) x = prev_x_min;
  425. else if (x >=prev_x_max) x = prev_x_max-1;
  426. if (y < prev_y_min) y = prev_y_min;
  427. else if (y >=prev_y_max) y = prev_y_max-1;
  428. return(x+y*npix);
  429. }*/
  430. #define unrestricted_MC_chro(x,y,npix,prev_x_min,prev_y_min,prev_x_max,prev_y_max) ((x)+(y)*(npix))
  431. /***********************************************************CommentBegin******
  432.  *
  433.  * -- GetPred_Chroma -- Predicts chrominance macroblock
  434.  *
  435.  * Purpose :
  436.  * Does the chrominance prediction for P-frames
  437.  *
  438.  * Arguments in :
  439.  * current position in image,
  440.  * motionvectors,
  441.  * pointers to compensated and previous Vops,
  442.  * width of the compensated Vop
  443.  *  width of the previous/reference Vop
  444.  *
  445.  ***********************************************************CommentEnd********/
  446. Void GetPred_Chroma (
  447. Int x_curr,
  448. Int y_curr,
  449. Int dx,
  450. Int dy,
  451. SInt *prev_u,
  452. SInt *prev_v,
  453. SInt *comp_u,
  454. SInt *comp_v,
  455. Int width,
  456. Int width_prev,
  457. Int prev_x_min,
  458. Int prev_y_min,
  459. Int prev_x_max,
  460. Int prev_y_max,
  461. Int rounding_control)
  462. {
  463. Int m,n;
  464. Int x, y, ofx, ofy, lx;
  465. Int xint, yint;
  466. Int xh, yh;
  467. Int index1,index2,index3,index4;
  468. lx = width_prev/2;
  469. x = x_curr>>1;
  470. y = y_curr>>1;
  471. xint = dx>>1;
  472. xh = dx & 1;
  473. yint = dy>>1;
  474. yh = dy & 1;
  475. if (!xh && !yh)
  476. {
  477. for (n = 0; n < 8; n++)
  478. {
  479. for (m = 0; m < 8; m++)
  480. {
  481. ofx = x + xint + m;
  482. ofy = y + yint + n;
  483. index1 = unrestricted_MC_chro(ofx,ofy,lx,prev_x_min,
  484. prev_y_min,prev_x_max,prev_y_max);
  485. comp_u[(y+n)*width/2+x+m]
  486. = *(prev_u+index1);
  487. comp_v[(y+n)*width/2+x+m]
  488. = *(prev_v+index1);
  489. }
  490. }
  491. }
  492. else if (!xh && yh)
  493. {
  494. for (n = 0; n < 8; n++)
  495. {
  496. for (m = 0; m < 8; m++)
  497. {
  498. ofx = x + xint + m;
  499. ofy = y + yint + n;
  500. index1 =  unrestricted_MC_chro(ofx,ofy,lx,prev_x_min,
  501. prev_y_min,prev_x_max,prev_y_max);
  502. index2 =  unrestricted_MC_chro(ofx,ofy+yh,lx,prev_x_min,
  503. prev_y_min,prev_x_max,prev_y_max);
  504. comp_u[(y+n)*width/2+x+m]
  505. = (*(prev_u+index1) +
  506. *(prev_u+index2) + 1- rounding_control)>>1;
  507. comp_v[(y+n)*width/2+x+m]
  508. = (*(prev_v+index1) +
  509. *(prev_v+index2) + 1- rounding_control)>>1;
  510. }
  511. }
  512. }
  513. else if (xh && !yh)
  514. {
  515. for (n = 0; n < 8; n++)
  516. {
  517. for (m = 0; m < 8; m++)
  518. {
  519. ofx = x + xint + m;
  520. ofy = y + yint + n;
  521. index1 =  unrestricted_MC_chro(ofx,ofy,lx,prev_x_min,
  522. prev_y_min,prev_x_max,prev_y_max);
  523. index2 =  unrestricted_MC_chro(ofx+xh,ofy,lx,prev_x_min,
  524. prev_y_min,prev_x_max,prev_y_max);
  525. comp_u[(y+n)*width/2+x+m]
  526. = (*(prev_u+index1) +
  527. *(prev_u+index2) + 1- rounding_control)>>1;
  528. comp_v[(y+n)*width/2+x+m]
  529. = (*(prev_v+index1) +
  530. *(prev_v+index2) + 1- rounding_control)>>1;
  531. }
  532. }
  533. }
  534. else
  535. {   /* xh && yh */
  536. for (n = 0; n < 8; n++)
  537. {
  538. for (m = 0; m < 8; m++)
  539. {
  540. ofx = x + xint + m;
  541. ofy = y + yint + n;
  542. index1 =  unrestricted_MC_chro(ofx,ofy,lx,prev_x_min,
  543. prev_y_min,prev_x_max,prev_y_max);
  544. index2 =  unrestricted_MC_chro(ofx+xh,ofy,lx,prev_x_min,
  545. prev_y_min,prev_x_max,prev_y_max);
  546. index3 =  unrestricted_MC_chro(ofx,ofy+yh,lx,prev_x_min,
  547. prev_y_min,prev_x_max,prev_y_max);
  548. index4 =  unrestricted_MC_chro(ofx+xh,ofy+yh,lx,prev_x_min,
  549. prev_y_min,prev_x_max,prev_y_max);
  550. comp_u[(y+n)*width/2+x+m]
  551. = (*(prev_u+index1)+
  552. *(prev_u+index2)+
  553. *(prev_u+index3)+
  554. *(prev_u+index4)+
  555. 2- rounding_control)>>2;
  556. comp_v[(y+n)*width/2+x+m]
  557. = (*(prev_v+index1)+
  558. *(prev_v+index2)+
  559. *(prev_v+index3)+
  560. *(prev_v+index4)+
  561. 2- rounding_control)>>2;
  562. }
  563. }
  564. }
  565. return;
  566. }