1 /*!
2  ***************************************************************************
3  * \file rd_intra_jm.c
4  *
5  * \brief
6  *    Rate-Distortion optimized mode decision
7  *
8  * \author
9  *    - Heiko Schwarz
10  *    - Valeri George
11  *    - Lowell Winger              <lwinger@lsil.com>
12  *    - Alexis Michael Tourapis    <alexismt@ieee.org>
13  * \date
14  *    12. April 2001
15  **************************************************************************
16  */
17 
18 #include <limits.h>
19 
20 #include "global.h"
21 
22 #include "image.h"
23 #include "macroblock.h"
24 #include "mb_access.h"
25 #include "rdopt_coding_state.h"
26 #include "mode_decision.h"
27 #include "rdopt.h"
28 #include "rd_intra_jm.h"
29 #include "q_around.h"
30 #include "intra4x4.h"
31 #include "intra8x8.h"
32 #include "md_common.h"
33 #include "transform8x8.h"
34 #include "md_distortion.h"
35 #include "elements.h"
36 #include "symbol.h"
37 #include "intra16x16.h"
38 #include "intra4x4.h"
39 #include "intra8x8.h"
40 
41 extern int MBType2Value (Macroblock* currMB);
42 
43 /*!
44  *************************************************************************************
45  * \brief
46  *    Mode Decision for an 4x4 Intra block
47  *************************************************************************************
48  */
mode_decision_for_I4x4_blocks_JM_High(Macroblock * currMB,int b8,int b4,int lambda,distblk * min_cost)49 int mode_decision_for_I4x4_blocks_JM_High (Macroblock *currMB, int  b8,  int  b4,  int  lambda,  distblk*  min_cost)
50 {
51   VideoParameters *p_Vid = currMB->p_Vid;
52   InputParameters *p_Inp = currMB->p_Inp;
53   Slice *currSlice = currMB->p_Slice;
54   RDOPTStructure  *p_RDO = currSlice->p_RDO;
55 
56   int     ipmode, best_ipmode = 0, y;
57   int     available_mode;
58   int     c_nz, nonzero = 0;
59   int*    ACLevel = currSlice->cofAC[b8][b4][0];
60   int*    ACRun   = currSlice->cofAC[b8][b4][1];
61   distblk rdcost = 0;
62   distblk min_rdcost  = DISTBLK_MAX;
63   int    block_x     = ((b8 & 0x01) << 3) + ((b4 & 0x01) << 2);
64   int    block_y     = ((b8 >> 1) << 3)  + ((b4 >> 1) << 2);
65   int    pic_pix_x   = currMB->pix_x  + block_x;
66   int    pic_pix_y   = currMB->pix_y  + block_y;
67   int    pic_opix_x  = currMB->pix_x + block_x;
68   int    pic_opix_y  = currMB->opix_y + block_y;
69   int    pic_block_x = pic_pix_x >> 2;
70   int    pic_block_y = pic_pix_y >> 2;
71 
72   int left_available, up_available, all_available;
73   int *mb_size = p_Vid->mb_size[IS_LUMA];
74 
75   char   upMode, leftMode;
76   int    mostProbableMode;
77 
78   PixelPos left_block, top_block;
79 
80   int  lrec4x4[4][4];
81   int best_nz_coeff = 0;
82   int block_x4 = block_x>>2;
83   int block_y4 = block_y>>2;
84 
85 #ifdef BEST_NZ_COEFF
86   int best_coded_block_flag = 0;
87   int bit_pos = 1 + ((((b8>>1)<<1)+(b4>>1))<<2) + (((b8&1)<<1)+(b4&1));
88   int64 cbp_bits;
89 
90   if (b8==0 && b4==0)
91     cbp_bits = 0;
92 #endif
93 
94   get4x4Neighbour(currMB, block_x - 1, block_y    , mb_size, &left_block);
95   get4x4Neighbour(currMB, block_x,     block_y - 1, mb_size, &top_block );
96 
97   // constrained intra pred
98   if (p_Inp->UseConstrainedIntraPred)
99   {
100     left_block.available = left_block.available ? p_Vid->intra_block[left_block.mb_addr] : 0;
101     top_block.available  = top_block.available  ? p_Vid->intra_block[top_block.mb_addr]  : 0;
102   }
103 
104   upMode            =  top_block.available ? p_Vid->ipredmode[top_block.pos_y ][top_block.pos_x ] : (char) -1;
105   leftMode          = left_block.available ? p_Vid->ipredmode[left_block.pos_y][left_block.pos_x] : (char) -1;
106 
107   mostProbableMode  = (upMode < 0 || leftMode < 0) ? DC_PRED : upMode < leftMode ? upMode : leftMode;
108   *min_cost = DISTBLK_MAX;
109 
110   currMB->ipmode_DPCM = NO_INTRA_PMODE; ////For residual DPCM
111 
112   //===== INTRA PREDICTION FOR 4x4 BLOCK =====
113   // set intra prediction values for 4x4 intra prediction
114   currSlice->set_intrapred_4x4(currMB, PLANE_Y, pic_pix_x, pic_pix_y, &left_available, &up_available, &all_available);
115 
116   //===== LOOP OVER ALL 4x4 INTRA PREDICTION MODES =====
117   for (ipmode = 0; ipmode < NO_INTRA_PMODE; ipmode++)
118   {
119     available_mode =  (all_available) || (ipmode==DC_PRED) ||
120       (up_available && (ipmode==VERT_PRED||ipmode==VERT_LEFT_PRED||ipmode==DIAG_DOWN_LEFT_PRED)) ||
121       (left_available && (ipmode==HOR_PRED||ipmode==HOR_UP_PRED));
122 
123     if (valid_intra_mode(currSlice, ipmode) == 0)
124       continue;
125 
126     if( available_mode)
127     {
128       // generate intra 4x4 prediction block given availability
129       get_intrapred_4x4(currMB, PLANE_Y, ipmode, block_x, block_y, left_available, up_available);
130 
131       // get prediction and prediction error
132       generate_pred_error_4x4(&p_Vid->pCurImg[pic_opix_y], currSlice->mpr_4x4[0][ipmode], &currSlice->mb_pred[0][block_y], &currSlice->mb_ores[0][block_y], pic_opix_x, block_x);
133 
134       // get and check rate-distortion cost
135 #ifdef BEST_NZ_COEFF
136       currMB->cbp_bits[0] = cbp_bits;
137 #endif
138 
139       rdcost = currSlice->rdcost_for_4x4_intra_blocks (currMB, &c_nz, b8, b4, ipmode, lambda, mostProbableMode, min_rdcost);
140       if ((rdcost < min_rdcost) || (rdcost == min_rdcost && ipmode == mostProbableMode))
141       {
142         //--- set coefficients ---
143         memcpy(p_RDO->cofAC4x4[0], ACLevel, 18 * sizeof(int));
144         memcpy(p_RDO->cofAC4x4[1], ACRun,   18 * sizeof(int));
145 
146         //--- set reconstruction ---
147         copy_4x4block(p_RDO->rec4x4[PLANE_Y], &p_Vid->enc_picture->imgY[pic_pix_y], 0, pic_pix_x);
148 
149         // SP/SI reconstruction
150         if(currSlice->slice_type == SP_SLICE && !currSlice->sp2_frame_indicator)
151         {
152           for (y=0; y<4; y++)
153           {
154             memcpy(lrec4x4[y],&p_Vid->lrec[pic_pix_y+y][pic_pix_x], BLOCK_SIZE * sizeof(int));// stores the mode coefficients
155           }
156         }
157 
158         //--- flag if transform-coefficients must be coded ---
159         nonzero = c_nz;
160 
161         //--- set best mode update minimum cost ---
162         *min_cost     = rdcost;
163         min_rdcost    = rdcost;
164         best_ipmode   = ipmode;
165 
166         best_nz_coeff = p_Vid->nz_coeff [currMB->mbAddrX][block_x4][block_y4];
167 #ifdef BEST_NZ_COEFF
168         best_coded_block_flag = (int)((currMB->cbp_bits[0] >> bit_pos)&(int64)(1));
169 #endif
170         if (p_Vid->AdaptiveRounding)
171         {
172           store_adaptive_rounding_4x4 (p_Vid, p_Vid->ARCofAdj4x4, I4MB, block_y, block_x);
173         }
174       }
175     }
176   }
177 #if INTRA_RDCOSTCALC_NNZ
178   p_Vid->nz_coeff [currMB->mbAddrX][block_x4][block_y4] = best_nz_coeff;
179 #endif
180 #ifdef BEST_NZ_COEFF
181   cbp_bits &= (~(int64)(1<<bit_pos));
182   cbp_bits |= (int64)(best_coded_block_flag<<bit_pos);
183 #endif
184 
185   //===== set intra mode prediction =====
186   p_Vid->ipredmode[pic_block_y][pic_block_x] = (char) best_ipmode;
187   currMB->intra_pred_modes[4*b8+b4] =
188     (char) (mostProbableMode == best_ipmode ? -1 : (best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1));
189 
190   //===== restore coefficients =====
191   memcpy (ACLevel, p_RDO->cofAC4x4[0], 18 * sizeof(int));
192   memcpy (ACRun,   p_RDO->cofAC4x4[1], 18 * sizeof(int));
193 
194   //===== restore reconstruction and prediction (needed if single coeffs are removed) =====
195   copy_4x4block(&p_Vid->enc_picture->imgY[pic_pix_y], p_RDO->rec4x4[PLANE_Y], pic_pix_x, 0);
196   copy_4x4block(&currSlice->mb_pred[0][block_y], currSlice->mpr_4x4[0][best_ipmode], block_x, 0);
197 
198   // SP/SI reconstuction
199   if(currSlice->slice_type == SP_SLICE && !currSlice->sp2_frame_indicator)
200   {
201     for (y=0; y<BLOCK_SIZE; y++)
202     {
203       memcpy (&p_Vid->lrec[pic_pix_y+y][pic_pix_x], lrec4x4[y], BLOCK_SIZE * sizeof(int));//restore coefficients when encoding primary SP frame
204     }
205   }
206 
207   if (p_Vid->AdaptiveRounding)
208   {
209     update_adaptive_rounding_4x4 (p_Vid,p_Vid->ARCofAdj4x4, I4MB, block_y, block_x);
210   }
211 
212   return nonzero;
213 }
214 
215 /*!
216 *************************************************************************************
217 * \brief
218 *    8x8 Intra mode decision for a macroblock - High complexity
219 *************************************************************************************
220 */
mode_decision_for_I8x8_blocks_JM_High(Macroblock * currMB,int b8,int lambda,distblk * min_cost)221 int mode_decision_for_I8x8_blocks_JM_High (Macroblock *currMB, int b8, int lambda, distblk *min_cost)
222 {
223   VideoParameters *p_Vid = currMB->p_Vid;
224   InputParameters *p_Inp = currMB->p_Inp;
225   Slice *currSlice = currMB->p_Slice;
226   RDOPTStructure  *p_RDO = currSlice->p_RDO;
227 
228   int     ipmode, best_ipmode = 0, j;
229   int     c_nz, nonzero = 0;
230   distblk  rdcost = 0;
231   distblk  min_rdcost  = DISTBLK_MAX;
232   int     block_x     = (b8 & 0x01) << 3;
233   int     block_y     = (b8 >> 1) << 3;
234   int     pic_pix_x   = currMB->pix_x + block_x;
235   int     pic_pix_y   = currMB->pix_y + block_y;
236   int     pic_opix_x  = currMB->pix_x + block_x;
237   int     pic_opix_y  = currMB->opix_y + block_y;
238   int     pic_block_x = pic_pix_x >> 2;
239   int     pic_block_y = pic_pix_y >> 2;
240   int     mb_block_y  = (currMB->block_y) + ((b8 >> 1) << 1);
241   int     mb_block_x  = (currMB->block_x) + ((b8 & 0x01) << 1);
242   int     *p_AC8x8 = p_RDO->coefAC8x8intra[b8][0][0][0];
243   int     *cofAC   = currSlice->cofAC[b8][0][0];
244 
245   int    left_available, up_available, all_available;
246   int    **mb_ores = currSlice->mb_ores[0];
247   imgpel **mb_pred = currSlice->mb_pred[0];
248 
249   char   upMode, leftMode;
250   int    mostProbableMode;
251 
252   PixelPos left_block, top_block;
253 
254   int *mb_size = p_Vid->mb_size[IS_LUMA];
255 
256   get4x4Neighbour(currMB, block_x - 1, block_y    , mb_size, &left_block);
257   get4x4Neighbour(currMB, block_x,     block_y - 1, mb_size, &top_block );
258 
259   // constrained intra pred
260   if (p_Inp->UseConstrainedIntraPred)
261   {
262     left_block.available = left_block.available ? p_Vid->intra_block [left_block.mb_addr] : 0;
263     top_block.available  = top_block.available  ? p_Vid->intra_block [top_block.mb_addr ] : 0;
264   }
265 
266   if(b8 >> 1)
267     upMode    =  top_block.available ? p_Vid->ipredmode8x8[top_block.pos_y ][top_block.pos_x ] : (char) -1;
268   else
269     upMode    =  top_block.available ? p_Vid->ipredmode   [top_block.pos_y ][top_block.pos_x ] : (char) -1;
270 
271   if(b8 & 0x01)
272     leftMode  = left_block.available ? p_Vid->ipredmode8x8[left_block.pos_y][left_block.pos_x] : (char) -1;
273   else
274     leftMode  = left_block.available ? p_Vid->ipredmode[left_block.pos_y][left_block.pos_x] : (char) -1;
275 
276   mostProbableMode  = (upMode < 0 || leftMode < 0) ? DC_PRED : upMode < leftMode ? upMode : leftMode;
277   *min_cost = DISTBLK_MAX;
278   currMB->ipmode_DPCM = NO_INTRA_PMODE; //For residual DPCM
279 
280   //===== INTRA PREDICTION FOR 8x8 BLOCK =====
281   currSlice->set_intrapred_8x8(currMB, PLANE_Y, pic_pix_x, pic_pix_y, &left_available, &up_available, &all_available);
282 
283   //===== LOOP OVER ALL 8x8 INTRA PREDICTION MODES =====
284   for (ipmode = 0; ipmode < NO_INTRA_PMODE; ipmode++)
285   {
286     if( (ipmode==DC_PRED) ||
287       ((ipmode==VERT_PRED||ipmode==VERT_LEFT_PRED||ipmode==DIAG_DOWN_LEFT_PRED) && up_available ) ||
288       ((ipmode==HOR_PRED||ipmode==HOR_UP_PRED) && left_available ) ||
289       (all_available) )
290     {
291       get_intrapred_8x8(currMB, PLANE_Y, ipmode, left_available, up_available);
292       // get prediction and prediction error
293       generate_pred_error_8x8(&p_Vid->pCurImg[pic_opix_y], currSlice->mpr_8x8[0][ipmode], &mb_pred[block_y], &mb_ores[block_y], pic_opix_x, block_x);
294 
295       currMB->ipmode_DPCM = (short) ipmode;
296 
297       // get and check rate-distortion cost
298 
299       rdcost = currSlice->rdcost_for_8x8_intra_blocks (currMB, &c_nz, b8, ipmode, lambda, min_rdcost, mostProbableMode);
300       if ((rdcost < min_rdcost) || (rdcost == min_rdcost && ipmode == mostProbableMode))
301       {
302         //--- set coefficients ---
303         memcpy(p_AC8x8, cofAC, 4 * 2 * 65 * sizeof(int));
304 
305         //--- set reconstruction ---
306         copy_image_data_8x8(p_RDO->rec8x8[PLANE_Y], &p_Vid->enc_picture->imgY[pic_pix_y], 0, pic_pix_x);
307 
308         if (p_Vid->AdaptiveRounding)
309         {
310           for (j = block_y; j < block_y + 8; j++)
311             memcpy(&p_Vid->ARCofAdj8x8[0][DUMMY][j][block_x],&p_Vid->ARCofAdj8x8[0][I8MB][j][block_x], 8 * sizeof(int));
312         }
313 
314         //--- flag if transform coefficients must be coded ---
315         nonzero = c_nz;
316 
317         //--- set best mode update minimum cost ---
318         *min_cost   = rdcost;
319         min_rdcost  = rdcost;
320         best_ipmode = ipmode;
321       }
322     }
323   }
324 
325   //===== set intra mode prediction =====
326   p_Vid->ipredmode8x8[pic_block_y][pic_block_x] = (char) best_ipmode;
327   currMB->ipmode_DPCM = (short) best_ipmode; //For residual DPCM
328 
329   currMB->intra_pred_modes8x8[4*b8] = (char) ((mostProbableMode == best_ipmode)
330     ? -1
331     : (best_ipmode < mostProbableMode ? best_ipmode : best_ipmode - 1));
332 
333   memset(&p_Vid->ipredmode8x8[mb_block_y    ][mb_block_x], best_ipmode, 2 * sizeof(char));
334   memset(&p_Vid->ipredmode8x8[mb_block_y + 1][mb_block_x], best_ipmode, 2 * sizeof(char));
335 
336   //===== restore coefficients =====
337   memcpy(cofAC, p_AC8x8, 4 * 2 * 65 * sizeof(int));
338 
339   if (p_Vid->AdaptiveRounding)
340   {
341     for (j=block_y; j< block_y + 8; j++)
342       memcpy(&p_Vid->ARCofAdj8x8[0][I8MB][j][block_x], &p_Vid->ARCofAdj8x8[0][DUMMY][j][block_x], 8 * sizeof(int));
343   }
344 
345   //===== restore reconstruction and prediction (needed if single coeffs are removed) =====
346   copy_image_data_8x8(&p_Vid->enc_picture->imgY[pic_pix_y], p_RDO->rec8x8[0], pic_pix_x, 0);
347   copy_image_data_8x8(&mb_pred[block_y], currSlice->mpr_8x8[0][best_ipmode], block_x, 0);
348 
349   return nonzero;
350 }
351 
352 /*!
353  *************************************************************************************
354  * \brief
355  *    Mode Decision for an 8x8 Intra block
356  *************************************************************************************
357  */
Mode_Decision_for_IntraSubMBlocks(Macroblock * currMB,int b8,int lambda,distblk * cost,int non_zero[3])358 int Mode_Decision_for_IntraSubMBlocks(Macroblock *currMB, int b8, int lambda, distblk *cost, int non_zero[3])
359 {
360   Slice *currSlice = currMB->p_Slice;
361   int  b4;
362   distblk  cost4x4;
363   currMB->cr_cbp[0] = 0;
364   currMB->cr_cbp[1] = 0;
365   currMB->cr_cbp[2] = 0;
366 
367   memset(non_zero, 0, 3 * sizeof(int));
368  *cost = weighted_cost(lambda, 6);        //6 * lambda;
369   for (b4=0; b4<4; b4++)
370   {
371     non_zero[0] |= currSlice->mode_decision_for_I4x4_blocks (currMB, b8, b4, lambda, &cost4x4);
372     non_zero[1] |= currMB->cr_cbp[1];
373     non_zero[2] |= currMB->cr_cbp[2];
374     *cost += cost4x4;
375   }
376 
377   return non_zero[0];
378 }
379 
380 /*!
381  *************************************************************************************
382  * \brief
383  *    4x4 Intra mode decision for an macroblock
384  *************************************************************************************
385  */
mode_decision_for_I4x4_MB(Macroblock * currMB,int lambda,distblk * cost)386 int mode_decision_for_I4x4_MB (Macroblock *currMB, int lambda,  distblk* cost)
387 {
388   Slice *currSlice = currMB->p_Slice;
389   int  cbp=0, b8;
390   distblk cost8x8;
391   int non_zero[3] = {0, 0, 0};
392 
393   currSlice->cmp_cbp[1] = currSlice->cmp_cbp[2] = 0;
394 
395   for (*cost=0, b8=0; b8<4; b8++)
396   {
397     if (Mode_Decision_for_IntraSubMBlocks (currMB, b8, lambda, &cost8x8, non_zero))
398     {
399       cbp |= (1<<b8);
400     }
401     *cost += cost8x8;
402     if (non_zero[1])
403     {
404       currSlice->cmp_cbp[1] |= (1<<b8);
405       cbp |= currSlice->cmp_cbp[1];
406       currSlice->cmp_cbp[1] = cbp;
407       currSlice->cmp_cbp[2] = cbp;
408     }
409     if (non_zero[2])
410     {
411       currSlice->cmp_cbp[2] |= (1<<b8);
412       cbp |= currSlice->cmp_cbp[2];
413       currSlice->cmp_cbp[1] = cbp;
414       currSlice->cmp_cbp[2] = cbp;
415     }
416   }
417   return cbp;
418 }
419 
find_best_mode_I16x16_MB(Macroblock * currMB,int lambda,distblk min_cost)420 int find_best_mode_I16x16_MB (Macroblock *currMB, int lambda,  distblk min_cost)
421 {
422   Slice *currSlice = currMB->p_Slice;
423   currMB->luma_transform_size_8x8_flag = FALSE;
424   return (int) currSlice->find_sad_16x16 (currMB);
425 }
426 
427 /*!
428 *************************************************************************************
429 * \brief
430 *    Intra 16x16 mode decision
431 *************************************************************************************
432 */
mode_decision_for_I16x16_MB(Macroblock * currMB,int lambda)433 int mode_decision_for_I16x16_MB (Macroblock* currMB, int lambda)
434 {
435   find_best_mode_I16x16_MB (currMB, lambda, DISTBLK_MAX);
436   return currMB->residual_transform_quant_luma_16x16 (currMB, PLANE_Y);
437 }
438 
439 
440 /************************************************************************************
441 * \brief
442 *    Intra 16x16 mode decision using Rate-Distortion Optimization
443 *************************************************************************************
444 */
mode_decision_for_I16x16_MB_RDO(Macroblock * currMB,int lambda)445 int mode_decision_for_I16x16_MB_RDO (Macroblock* currMB, int lambda)
446 {
447   VideoParameters *p_Vid = currMB->p_Vid;
448   InputParameters *p_Inp = currMB->p_Inp;
449   Slice *currSlice = currMB->p_Slice;
450 
451   SyntaxElement   se;
452   const int*      partMap    = assignSE2partition[currSlice->partition_mode];
453   DataPartition*  dataPart   = &(currSlice->partArr[partMap[SE_MBTYPE]]);
454 
455   distblk min_rdcost = DISTBLK_MAX, rdcost;
456   distblk distortionY;
457   int rate;
458   int i,k;
459   int b8, b4;
460 
461 
462   int up_avail, left_avail, left_up_avail;
463 
464   int  best_mode = 0, best_cbp = 0;
465   int  bestCofAC[4][4][2][65];
466   int  bestCofDC[2][18];
467   imgpel bestRec[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
468 
469   currMB->mb_type = I16MB;
470 
471   currSlice->set_intrapred_16x16(currMB, PLANE_Y, &left_avail, &up_avail, &left_up_avail);
472 
473   for (k = 0;k < 4; k++)
474   {
475     if (p_Inp->IntraDisableInterOnly == 0 || (currSlice->slice_type != I_SLICE && currSlice->slice_type != SI_SLICE))
476     {
477       if (p_Inp->Intra16x16ParDisable && (k==VERT_PRED_16||k==HOR_PRED_16))
478         continue;
479 
480       if (p_Inp->Intra16x16PlaneDisable && k==PLANE_16)
481         continue;
482     }
483 
484     if ((k==0 && !up_avail) || (k==1 && !left_avail) || (k==3 && (!left_avail || !up_avail || !left_up_avail)))
485       continue;
486 
487     get_intrapred_16x16(currMB, PLANE_Y, k, left_avail, up_avail);
488 
489     currMB->i16mode = (char) k;
490     currMB->cbp = currMB->residual_transform_quant_luma_16x16(currMB, PLANE_Y);
491     distortionY = compute_SSE16x16_thres(&p_Vid->pCurImg[currMB->opix_y], &p_Vid->enc_picture->p_curr_img[currMB->pix_y], currMB->pix_x, currMB->pix_x, min_rdcost);
492 
493     if (distortionY < min_rdcost - weighted_cost(lambda, 4))
494     {
495       currSlice->store_coding_state (currMB, currSlice->p_RDO->cs_tmp);
496       currMB->i16offset = I16Offset  (currMB->cbp, currMB->i16mode);
497       se.value1  = MBType2Value (currMB);
498       se.value2  = 0;
499       se.type    = SE_MBTYPE;
500 
501       currSlice->writeMB_typeInfo (currMB, &se, dataPart);
502 
503       rate = se.len;
504       if (distortionY + weighted_cost(lambda, rate) < min_rdcost)
505       {
506         rate += currSlice->writeCoeff16x16   (currMB, PLANE_Y);
507         currSlice->reset_coding_state (currMB, currSlice->p_RDO->cs_tmp);
508 
509         rdcost = distortionY + weighted_cost(lambda, rate);
510 
511         if(rdcost < min_rdcost)
512         {
513           min_rdcost = rdcost;
514           best_mode = k;
515           best_cbp = currMB->cbp;
516           for(b8 = 0; b8 < 4; b8++)
517           {
518             for(b4 = 0; b4 < 4; b4++)
519             {
520               memcpy(bestCofAC[b8][b4][0], currSlice->cofAC[b8][b4][0], sizeof(int) * 65);
521               memcpy(bestCofAC[b8][b4][1], currSlice->cofAC[b8][b4][1], sizeof(int) * 65);
522             }
523           }
524 
525           memcpy(bestCofDC[0], currSlice->cofDC[0][0], sizeof(int)*18);
526           memcpy(bestCofDC[1], currSlice->cofDC[0][1], sizeof(int)*18);
527 
528           for(i = 0; i < MB_BLOCK_SIZE; i++)
529             memcpy(bestRec[i], &p_Vid->enc_picture->p_curr_img[currMB->pix_y + i][currMB->pix_x], sizeof(imgpel)*MB_BLOCK_SIZE);
530         }
531       }
532       else
533       {
534         currSlice->reset_coding_state (currMB, currSlice->p_RDO->cs_tmp);
535       }
536     }
537   }
538 
539   currMB->i16mode = (char) best_mode;
540   currMB->cbp = best_cbp;
541   currMB->i16offset = I16Offset  (currMB->cbp, currMB->i16mode);
542 
543   for(b8 = 0; b8 < 4; b8++)
544   {
545     for(b4 = 0; b4 < 4; b4++)
546     {
547       memcpy(currSlice->cofAC[b8][b4][0], bestCofAC[b8][b4][0], sizeof(int)*65);
548       memcpy(currSlice->cofAC[b8][b4][1], bestCofAC[b8][b4][1], sizeof(int)*65);
549     }
550   }
551 
552   memcpy(currSlice->cofDC[0][0], bestCofDC[0], sizeof(int)*18);
553   memcpy(currSlice->cofDC[0][1], bestCofDC[1], sizeof(int)*18);
554 
555   for(i = 0; i < MB_BLOCK_SIZE; i++)
556   {
557     memcpy(&p_Vid->enc_picture->p_curr_img[currMB->pix_y+i][currMB->pix_x], bestRec[i], MB_BLOCK_SIZE*sizeof(imgpel));
558   }
559 
560   return currMB->cbp;
561 }
562 
563 
564