www.pudn.com > wm2.5.zip > intrapred.c
/* *********************************************************************** * COPYRIGHT AND WARRANTY INFORMATION * * Copyright 2003, Advanced Audio Video Coding Standard, Part II * * DISCLAIMER OF WARRANTY * * These software programs are available to the users without any * license fee or royalty on an "as is" basis. The AVS disclaims * any and all warranties, whether express, implied, or statutory, * including any implied warranties of merchantability or of fitness * for a particular purpose. In no event shall the contributors or * the AVS be liable for any incidental, punitive, or consequential * damages of any kind whatsoever arising from the use of this program. * * This disclaimer of warranty extends to the user of this program * and user's customers, employees, agents, transferees, successors, * and assigns. * * The AVS does not represent or warrant that the program furnished * hereunder are free of infringement of any third-party patents. * Commercial implementations of AVS, including shareware, may be * subject to royalty fees to patent holders. Information regarding * the AVS patent policy is available from the AVS Web site at * http://www.avs.org.cn * * THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. ************************************************************************ */ /* ************************************************************************************* * File name: intra.c * Function: Process one macroblock * ************************************************************************************* */ #include#include #include #include "define.h" #include "global.h" #include "intrapred.h" #include "block.h" #include "rdopt.h" #include "vlc.h" #include "ratectl.h" #define INTRA_VLIW_ZP 1 #define EP (edgepixels+20) #define EPU (edgepixu+20) //qwang 2004-3-7 #define EPV (edgepixv+20) //qwang 2004-3-7 extern const short QP_SCALE_CR[64]; extern int cofAC[6][4][2][18]; // Notation for comments regarding prediction and predictors. // The pels of the 4x4 block are labelled a..p. The predictor pels above // are labelled A..H, from the left I..P, and from above left X, as follows: // // X A B C D E F G H // I a b c d // J e f g h // K i j k l // L m n o p // M // N // O // P // // Predictor array index definitions #define P_X (PredPel[0]) #define P_A (PredPel[1]) #define P_B (PredPel[2]) #define P_C (PredPel[3]) #define P_D (PredPel[4]) #define P_E (PredPel[5]) #define P_F (PredPel[6]) #define P_G (PredPel[7]) #define P_H (PredPel[8]) #define P_I (PredPel[9]) #define P_J (PredPel[10]) #define P_K (PredPel[11]) #define P_L (PredPel[12]) #define P_M (PredPel[13]) #define P_N (PredPel[14]) #define P_O (PredPel[15]) #define P_P (PredPel[16]) /*! ************************************************************************ * \brief * Make intra 4x4 prediction according to all 9 prediction modes. * The routine uses left and upper neighbouring points from * previous coded blocks to do this (if available). Notice that * inaccessible neighbouring points are signalled with a negative * value in the predmode array . * * \para Input: * Starting point of current 4x4 block image posision * * \para Output: * none ************************************************************************ */ int intrapred_luma(int img_x,int img_y,int intramode) //zhangnan { int i,j; int s0; int PredPel[17]; // array of predictor pels int block_available_up = (ipredmode[img_x/BLOCK_SIZE+1][img_y/BLOCK_SIZE] >=0); int block_available_left = (ipredmode[img_x/BLOCK_SIZE][img_y/BLOCK_SIZE+1] >=0); int block_available_up_left = (ipredmode[img_x/BLOCK_SIZE][img_y/BLOCK_SIZE] >=0); int block_available_up_right = 0; int block_available_left_down = 0; // end int b4_x, b4_y; b4_x=img_x>>2; b4_y=img_y>>2; i = (img_x & 15); j = (img_y & 15); if (block_available_up) { P_A = imgY[img_y-1][img_x+0]; P_B = imgY[img_y-1][img_x+1]; P_C = imgY[img_y-1][img_x+2]; P_D = imgY[img_y-1][img_x+3]; P_E = P_F = P_G = P_H = P_D; } else P_A = P_B = P_C = P_D = P_E = P_F = P_G = P_H = 128; if (block_available_left) { P_I = imgY[img_y+0][img_x-1]; P_J = imgY[img_y+1][img_x-1]; P_K = imgY[img_y+2][img_x-1]; P_L = imgY[img_y+3][img_x-1]; P_M = P_N = P_O = P_P = P_L; } else P_I = P_J = P_K = P_L = P_M = P_N = P_O = P_P = 128; //getting luma r0's value if (block_available_up_left) P_X = imgY[img_y-1][img_x-1]; else P_X = 128; switch (intramode) { // make DC prediction : the same as h.264 case DC_PRED: s0 = 0; if (block_available_up && block_available_left) { // no edge s0 = (P_A + P_B + P_C + P_D + P_I + P_J + P_K + P_L + 4)/(2*BLOCK_SIZE); } else if (!block_available_up && block_available_left) { // left edge s0 = (P_I + P_J + P_K + P_L + 2)/BLOCK_SIZE; } else if (block_available_up && !block_available_left) { // upper edge s0 = (P_A + P_B + P_C + P_D + 2)/BLOCK_SIZE; } else //if (!block_available_up && !block_available_left) { // top left corner, nothing to predict from s0 = 128; } for (j=0; j < BLOCK_SIZE; j++) for (i=0; i < BLOCK_SIZE; i++) pgMbData->pred_curr[0][i][j] = s0;// store DC prediction break; /////////////////////////////// // make horiz and vert prediction /////////////////////////////// case VERT_PRED: if(block_available_up) for(j=0;j pred_curr[0][j][i]=imgY[img_y-1][img_x+i];// store predicted 4x4 block else return 0; break; case HOR_PRED: if (block_available_left) for(j=0;j pred_curr[0][j][i]=imgY[img_y+j][img_x-1]; // store predicted 4x4 block else return 0; break; /* Prediction according to 'diagonal' modes */ case DOWN_RIGHT_PRED: if (block_available_up && block_available_left) { // Mode DOWN_RIGHT_PRED pgMbData->pred_curr[0][3][0] = (P_L + 2*P_K + P_J + 2) / 4; pgMbData->pred_curr[0][2][0] = pgMbData->pred_curr[0][3][1] = (P_K + 2*P_J + P_I + 2) / 4; pgMbData->pred_curr[0][1][0] = pgMbData->pred_curr[0][2][1] = pgMbData->pred_curr[0][3][2] = (P_J + 2*P_I + P_X + 2) / 4; pgMbData->pred_curr[0][0][0] = pgMbData->pred_curr[0][1][1] = pgMbData->pred_curr[0][2][2] = pgMbData->pred_curr[0][3][3] = (P_I + 2*P_X + P_A + 2) / 4; pgMbData->pred_curr[0][0][1] = pgMbData->pred_curr[0][1][2] = pgMbData->pred_curr[0][2][3] = (P_X + 2*P_A + P_B + 2) / 4; pgMbData->pred_curr[0][0][2] = pgMbData->pred_curr[0][1][3] = (P_A + 2*P_B + P_C + 2) / 4; pgMbData->pred_curr[0][0][3] = (P_B + 2*P_C + P_D + 2) / 4; } else return 0; break; // Mode DOWN_LEFT_PRED case DOWN_LEFT_PRED: if(block_available_left&&block_available_up) { pgMbData->pred_curr[0][0][0] = (P_A + P_C + P_I + P_K + 2*(P_B + P_J) + 4) / 8; pgMbData->pred_curr[0][0][1] = pgMbData->pred_curr[0][1][0] = (P_B + P_D + P_J + P_L + 2*(P_C + P_K) + 4) / 8; pgMbData->pred_curr[0][0][2] = pgMbData->pred_curr[0][1][1] = pgMbData->pred_curr[0][2][0] = (P_C + P_E + P_K + P_M + 2*(P_D + P_L) + 4) / 8; pgMbData->pred_curr[0][0][3] = pgMbData->pred_curr[0][1][2] = pgMbData->pred_curr[0][2][1] = pgMbData->pred_curr[0][3][0] = (P_D + P_F + P_L + P_N + 2*(P_E + P_M) + 4) / 8; pgMbData->pred_curr[0][1][3] = pgMbData->pred_curr[0][2][2] = pgMbData->pred_curr[0][3][1] = (P_E + P_G + P_M + P_O + 2*(P_F + P_N) + 4) / 8; pgMbData->pred_curr[0][2][3] = pgMbData->pred_curr[0][3][2] = (P_F + P_H + P_N + P_P + 2*(P_G + P_O) + 4) / 8; pgMbData->pred_curr[0][3][3] = (P_G + P_O + P_H + P_P + 2) / 4; } else return 0; break; /**************** for intra 9 modes by jx *****************/ case VERT_RIGHT_PRED: // 5 make VERT_RIGHT_PRED Prediction if(block_available_left && block_available_up ) { pgMbData->pred_curr[0][0][0] = pgMbData->pred_curr[0][2][1] = (P_X + P_A + 1) / 2; pgMbData->pred_curr[0][0][1] = pgMbData->pred_curr[0][2][2] = (P_A + P_B + 1) / 2; pgMbData->pred_curr[0][0][2] = pgMbData->pred_curr[0][2][3] = (P_B + P_C + 1) / 2; pgMbData->pred_curr[0][0][3] = (P_C + P_D + 1) / 2; pgMbData->pred_curr[0][1][0] = pgMbData->pred_curr[0][3][1] = (P_I + 2*P_X + P_A + 2) / 4; pgMbData->pred_curr[0][1][1] = pgMbData->pred_curr[0][3][2] = (P_X + 2*P_A + P_B + 2) / 4; pgMbData->pred_curr[0][1][2] = pgMbData->pred_curr[0][3][3] = (P_A + 2*P_B + P_C + 2) / 4; pgMbData->pred_curr[0][1][3] = (P_B + 2*P_C + P_D + 2) / 4; pgMbData->pred_curr[0][2][0] = (P_X + 2*P_I + P_J + 2) / 4; pgMbData->pred_curr[0][3][0] = (P_I + 2*P_J + P_K + 2) / 4; } else return 0; break; // end VERT_RIGHT_PRED case HOR_DOWN_PRED: // 6 make HOR_DOWN_PRED Prediction if(block_available_left && block_available_up) { pgMbData->pred_curr[0][0][0] = pgMbData->pred_curr[0][1][2] = (P_X + P_I + 1) / 2; pgMbData->pred_curr[0][0][1] = pgMbData->pred_curr[0][1][3] = (P_I + 2*P_X + P_A + 2) / 4; pgMbData->pred_curr[0][0][2] = (P_X + 2*P_A + P_B + 2) / 4; pgMbData->pred_curr[0][0][3] = (P_A + 2*P_B + P_C + 2) / 4; pgMbData->pred_curr[0][1][0] = pgMbData->pred_curr[0][2][2] = (P_I + P_J + 1) / 2; pgMbData->pred_curr[0][1][1] = pgMbData->pred_curr[0][2][3] = (P_X + 2*P_I + P_J + 2) / 4; pgMbData->pred_curr[0][2][0] = pgMbData->pred_curr[0][3][2] = (P_J + P_K + 1) / 2; pgMbData->pred_curr[0][2][1] = pgMbData->pred_curr[0][3][3] = (P_I + 2*P_J + P_K + 2) / 4; pgMbData->pred_curr[0][3][0] = (P_K + P_L + 1) / 2; pgMbData->pred_curr[0][3][1] = (P_J + 2*P_K + P_L + 2) / 4; } else return 0; break; // end HOR_DOWN_PRED case VERT_LEFT_PRED: // 7 make VERT_LEFT_PRED Prediction if(block_available_up) //dsk { pgMbData->pred_curr[0][0][0] = (P_A + P_B + 1) / 2; pgMbData->pred_curr[0][0][1] = pgMbData->pred_curr[0][2][0] = (P_B + P_C + 1) / 2; pgMbData->pred_curr[0][0][2] = pgMbData->pred_curr[0][2][1] = (P_C + P_D + 1) / 2; pgMbData->pred_curr[0][0][3] = pgMbData->pred_curr[0][2][2] = (P_D + P_E + 1) / 2; pgMbData->pred_curr[0][2][3] = (P_E + P_F + 1) / 2; pgMbData->pred_curr[0][1][0] = (P_A + 2*P_B + P_C + 2) / 4; pgMbData->pred_curr[0][1][1] = pgMbData->pred_curr[0][3][0] = (P_B + 2*P_C + P_D + 2) / 4; pgMbData->pred_curr[0][1][2] = pgMbData->pred_curr[0][3][1] = (P_C + 2*P_D + P_E + 2) / 4; pgMbData->pred_curr[0][1][3] = pgMbData->pred_curr[0][3][2] = (P_D + 2*P_E + P_F + 2) / 4; pgMbData->pred_curr[0][3][3] = (P_E + 2*P_F + P_G + 2) / 4; } else return 0; break; // end VERT_LEFT_PRED case HOR_UP_PRED: // 8 make HOR_UP_PRED Prediction if(block_available_left) { pgMbData->pred_curr[0][0][0] = (P_I + P_J + 1) / 2; pgMbData->pred_curr[0][0][1] = (P_I + 2*P_J + P_K + 2) / 4; pgMbData->pred_curr[0][0][2] = pgMbData->pred_curr[0][1][0] = (P_J + P_K + 1) / 2; pgMbData->pred_curr[0][0][3] = pgMbData->pred_curr[0][1][1] = (P_J + 2*P_K + P_L + 2) / 4; pgMbData->pred_curr[0][1][2] = pgMbData->pred_curr[0][2][0] = (P_K + P_L + 1) / 2; pgMbData->pred_curr[0][1][3] = pgMbData->pred_curr[0][2][1] = (P_K + 2*P_L + P_M + 2) / 4; pgMbData->pred_curr[0][3][0] = pgMbData->pred_curr[0][2][2] = pgMbData->pred_curr[0][2][3] = pgMbData->pred_curr[0][3][1] = pgMbData->pred_curr[0][3][2] = pgMbData->pred_curr[0][3][3] = P_L; } else return 0; break; // end HOR_UP_PRED /****************************************************/ default: fprintf(stderr,"Error in intrapred_luma"); break; } return 1; } /*! ************************************************************************ * \brief * Make intra 4x4 prediction according to all 9 prediction modes. * The routine uses left and upper neighbouring points from * previous coded blocks to do this (if available). Notice that * inaccessible neighbouring points are signalled with a negative * value in the predmode array . * * \para Input: * Starting point of current 4x4 block image posision * * \para Output: * none ************************************************************************ */ int Intra_Luma_Prediction (int * min_cost) //qwang 2004-3-5 { int b8, b4, cost4x4; int dummy; //WJP FOR I_DIRECT int i,j; int block_x, block_y; int pic_pix_x; int pic_pix_y; int pic_block_x; int pic_block_y; int dir_abort=0; int intra_cost = 0; int I_direct_cost = 0; short tmp_cbp,tmp_cbp_4x4[6]; int tmp_ipmode[4][4]; int tmp_cofAC[4][4][2][18]; unsigned char tmp_Y[4][4][4][4]; pgMbHeader->I_MODE = 1/*0 dongjie(check) */; //WJP END //GET THE I4X4 COST for (b8=0; b8<4; b8++) { for (b4=0; b4<4; b4++) { Mode_Decision_for_4x4IntraBlocks_luma (b8, b4, &cost4x4, &dummy); intra_cost += cost4x4; } // dongjie if(pgMbHeader->cbp_4x4[b8]==0) pgMbHeader->cbp &= (~(1< cbp |= (1< picture_code_type == INTRA_IMG) { //save the data for intra4x4 tmp_cbp = pgMbHeader->cbp; // dongjie pgMbHeader->cbp = 0; for(i=0;i<6;i++) { tmp_cbp_4x4[i] = pgMbHeader->cbp_4x4[i]; pgMbHeader->cbp_4x4[i] = 0; } // end for (b8=0; b8<4; b8++) { for (b4=0; b4<4; b4++) { block_x =(((b8 &1)<<3)+((b4 &1)<<2)); block_y =(((b8>>1)<<3)+((b4>>1)<<2)); pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); pic_pix_x = (pic_block_x<<2); pic_pix_y = (pic_block_y<<2); tmp_ipmode[b8][b4] = ipredmode[pic_block_x+1][pic_block_y+1]; for(j=0;j<4;j++) for(i=0;i<4;i++) tmp_Y[b8][b4][j][i] = pgMbData->pred_sample[b8][b4][j][i]; for(j=0;j<2;j++) for(i=0;i<18;i++) tmp_cofAC[b8][b4][j][i] = cofAC[b8][b4][j][i]; } } //GET THE I_direct COST for (b8=0; b8<4 && dir_abort==0; b8++) { for (b4=0; b4<4 && dir_abort==0; b4++) { RD_cost_for_4x4_dir_IntraBlocks_luma (b8, b4, &cost4x4, &dir_abort); I_direct_cost += cost4x4; } // dongjie if(pgMbHeader->cbp_4x4[b8]==0) pgMbHeader->cbp &= (~(1< cbp |= (1< I_MODE = 1/*0 dongjie(check) */; pgMbHeader->cbp = tmp_cbp; // dongjie for(i=0;i<6;i++) { pgMbHeader->cbp_4x4[i] = tmp_cbp_4x4[i]; } // end for (b8=0; b8<4; b8++) { for (b4=0; b4<4; b4++) { block_x =(((b8 &1)<<3)+((b4 &1)<<2)); block_y =(((b8>>1)<<3)+((b4>>1)<<2)); pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); pic_pix_x = (pic_block_x<<2); pic_pix_y = (pic_block_y<<2); ipredmode[pic_block_x+1][pic_block_y+1] = tmp_ipmode[b8][b4]; for(j=0;j<4;j++) for(i=0;i<4;i++) pgMbData->pred_sample[b8][b4][j][i] = tmp_Y[b8][b4][j][i]; for(j=0;j<2;j++) for(i=0;i<18;i++) cofAC[b8][b4][j][i] = tmp_cofAC[b8][b4][j][i]; } } } else { *min_cost = I_direct_cost; pgMbHeader->I_MODE = 0/*1 dongjie(check) */; } } return *min_cost; } /* ************************************************************************* * Function:Mode Decision for AVS intra blocks This might also be placed in rdopt.c behind Mode_Decision_for_4x4IntraBlocks(). * Input: * Output: * Return: * Attention: ************************************************************************* */ //added by MAZHAN mpm[9][9] = { {0, 0, 2, 0, 0, 0, 2, 0, 2}, {2, 1, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2, 2}, {2, 1, 2, 3, 4, 5, 2, 7, 2}, {4, 4, 2, 4, 4, 4, 6, 4, 4}, {5, 5, 2, 5, 5, 5, 6, 5, 5}, {6, 6, 6, 6, 6, 6, 6, 6, 6}, {7, 7, 2, 7, 7, 7, 6, 7, 7}, {0, 1, 2, 3, 4, 5, 6, 7, 8} }; int Mode_Decision_for_4x4IntraBlocks_luma(int b8, int b4, int *min_cost, int* coeff_cost) //qwang 2004-3-5 { int ipmode,best_ipmode,i,j; int block_x; int block_y; int pic_pix_x; int pic_pix_y; int pic_block_x; int pic_block_y; int upMode; int leftMode; int mostProbableMode; int lambda = pgMbData->lambda; double lamda_mode = pgMbData->lamda_mode; unsigned short cost; int rate; double rdcost, distortion; int best_pred_sample[8][8]; int diff_pix; block_x =(((b8 &1)<<3)+((b4 &1)<<2)); block_y =(((b8>>1)<<3)+((b4>>1)<<2)); pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); pic_pix_x = (pic_block_x<<2); pic_pix_y = (pic_block_y<<2); *min_cost = (1<<20); //MZ upMode = ((ipredmode[pic_block_x+1][pic_block_y] == 10) ? -1 : ipredmode[pic_block_x+1][pic_block_y]); leftMode = ((ipredmode[pic_block_x][pic_block_y+1] == 10) ? -1 : ipredmode[pic_block_x][pic_block_y+1]); mostProbableMode = (upMode < 0 || leftMode < 0) ? DC_PRED : mpm[leftMode][upMode]; //MAZHAN //listing all the INTRA4x4 MODE for (ipmode=0;ipmode org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i];//imgY_org[pic_pix_y+j][pic_pix_x+i] - up_row_v; cost += absm(diff_pix); // bug fix: index of diff was flipped. mwi 020701 } if (cost < *min_cost) { best_ipmode = ipmode; *min_cost = cost; for (j=0;j<4; j++) for (i=0;i<4; i++) { best_pred_sample[j][i] = pgMbData->pred_curr[0][j][i]; } } } else //RDO { // reconstruct // original frame subtract pgMbData->pred_curr(curr_block's predicted values : performance in intrapred_luma()) for (j=0;j<4; j++) for (i=0;i<4; i++) { pgMbHeader->pred_residual[b8][b4][j][i] = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i]; } // save the predicted values into pgMbData->pred_sample for (j=0;j<4; j++) for (i=0;i<4; i++) { pgMbData->pred_sample[b8][b4][j][i] = pgMbData->pred_curr[0][j][i]; } Transform_B4(b8, b4); //based on residual data Quant_B4(pgMbData->qp_mb, b8, b4, coeff_cost); Save_RD_State(); rate = (ipmode == mostProbableMode) ? 1 : 3; if(pgMbHeader->cbp_4x4[b8] & (1< byte_pos - pgRDStream->byte_pos)*8 + (pgRDStream->bits_to_go - pgcurrBitStream->bits_to_go); Restore_RD_State(); Dequant_B4(pgMbData->qp_mb,b8, b4); Inv_Transform_B4(b8, b4); Recon_B4(b8, b4, 0); //Rec B4 for(j=0; j<4; j++) for(i=0; i<4; i++) { imgY[pic_pix_y+j][pic_pix_x+i] = imgY1[j][i]; } //===== get distortion (SSD) of 4x4 block ===== distortion = 0; for (j=0; j<4; j++) for (i=0; i<4; i++) distortion += quadarr [original_frame[0][pic_pix_y+j][pic_pix_x+i] - imgY[pic_pix_y+j][pic_pix_x+i]]; rdcost = (double)distortion + lamda_mode*(double)rate; if(rdcost < *min_cost) { best_ipmode = ipmode; pgMbHeader->luma_ipred_mode[b8][b4] = mostProbableMode == best_ipmode ? -1 : best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1; pgMbHeader->luma_pred_mode_flag[b8][b4] = mostProbableMode == best_ipmode; *min_cost = (int) rdcost; for (j=0; j<4; j++) for (i=0; i<4; i++) best_pred_sample[j][i] = pgMbData->pred_curr[0][j][i]; } } } } //===== set intra mode prediction ===== //? ipredmode[pic_block_x+1][pic_block_y+1] = best_ipmode;//zhangnan pgMbHeader->luma_ipred_mode[b8][b4] = mostProbableMode == best_ipmode ? -1 : best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1; pgMbHeader->luma_pred_mode_flag[b8][b4] = mostProbableMode == best_ipmode; for (j=0; j<4; j++) for (i=0; i<4; i++) pgMbData->pred_sample[b8][b4][j][i] = best_pred_sample[j][i]; // reconstruct for (j=0;j<4; j++) for (i=0;i<4; i++) { pgMbHeader->pred_residual[b8][b4][j][i] = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_sample[b8][b4][j][i]; } Transform_B4(b8, b4); Quant_B4(pgMbData->qp_mb, b8, b4, coeff_cost); Dequant_B4(pgMbData->qp_mb, b8, b4); Inv_Transform_B4(b8, b4); Recon_B4(b8, b4, 0); for(j=0; j<4; j++) for(i=0; i<4; i++) { imgY[(pgMbData->mb_y<<4) + (b8/2)*8+(b4/2)*4+j][(pgMbData->mb_x<<4) + (b8%2)*8+(b4%2)*4+i] = imgY1[j][i]; //ÖØ½¨Öµ } return 1; } /* ************************************************************************* * Function:calculate the RD_cost for intra direct mode. * Input: * Output: * Return: * Author: wjp ************************************************************************* */ int RD_cost_for_4x4_dir_IntraBlocks_luma(int b8, int b4, int *min_cost, int *dir_abort) //qwang 2004-3-5 { int coeff_cost; int i,j; int block_x; int block_y; int pic_pix_x; int pic_pix_y; int pic_block_x; int pic_block_y; int upMode; int leftMode; int mostProbableMode; int lambda = pgMbData->lambda; double lamda_mode = pgMbData->lamda_mode; unsigned short cost; int rate; double rdcost, distortion; int diff_pix; block_x =(((b8 &1)<<3)+((b4 &1)<<2)); block_y =(((b8>>1)<<3)+((b4>>1)<<2)); pic_block_x=((pgMbData->mb_x<<2) + ((b8 &1)<<1) + (b4 &1)); pic_block_y=((pgMbData->mb_y<<2) + ((b8>>1)<<1) + (b4>>1)); pic_pix_x = (pic_block_x<<2); pic_pix_y = (pic_block_y<<2); //MZ upMode = ((ipredmode[pic_block_x+1][pic_block_y] == 10) ? -1 : ipredmode[pic_block_x+1][pic_block_y]); leftMode = ((ipredmode[pic_block_x][pic_block_y+1] == 10) ? -1 : ipredmode[pic_block_x][pic_block_y+1]); //upMode = ipredmode[pic_block_x+1][pic_block_y]; //leftMode = ipredmode[pic_block_x ][pic_block_y+1]; //*/ dsk 2004.6.15 //mostProbableMode = (upMode < 0 || leftMode < 0) ? DC_PRED : (upMode < leftMode ? upMode : leftMode); mostProbableMode = (upMode < 0 || leftMode < 0) ? DC_PRED : mpm[leftMode][upMode]; ipredmode[pic_block_x+1][pic_block_y+1] = mostProbableMode; //===== INTRA PREDICTION FOR 4x4 BLOCK ===== if(intrapred_luma(pic_pix_x,pic_pix_y,mostProbableMode)) { // reconstruct for (j=0;j<4; j++) for (i=0;i<4; i++) { pgMbHeader->pred_residual[b8][b4][j][i] = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i]; } for (j=0;j<4; j++) for (i=0;i<4; i++) { pgMbData->pred_sample[b8][b4][j][i] = pgMbData->pred_curr[0][j][i]; } Transform_B4(b8, b4); Quant_B4(pgMbData->qp_mb, b8, b4, &coeff_cost); Dequant_B4(pgMbData->qp_mb,b8, b4); Inv_Transform_B4(b8, b4); Recon_B4(b8, b4, 0); for(j=0; j<4; j++) for(i=0; i<4; i++) { imgY[pic_pix_y+j][pic_pix_x+i] = imgY1[j][i]; } if(!input.rdopt) { cost = 0; for (j=0;j<4;j++) for (i=0;i<4;i++) { diff_pix = pgMbData->org_luma[block_y+j][block_x+i] - pgMbData->pred_curr[0][j][i];//imgY_org[pic_pix_y+j][pic_pix_x+i] - up_row_v; cost += absm(diff_pix); // bug fix: index of diff was flipped. mwi 020701 } *min_cost = cost; } else { //get the rate Save_RD_State(); rate = 0; if(pgMbHeader->cbp_4x4[b8] & (1< byte_pos - pgRDStream->byte_pos)*8 + (pgRDStream->bits_to_go - pgcurrBitStream->bits_to_go); Restore_RD_State(); //===== get distortion (SSD) of 4x4 block ===== distortion = 0; for (j=0; j<4; j++) for (i=0; i<4; i++) distortion += quadarr [original_frame[0][pic_pix_y+j][pic_pix_x+i] - imgY[pic_pix_y+j][pic_pix_x+i]]; rdcost = (double)distortion + lamda_mode*rate; *min_cost = (int) rdcost; } } else { *dir_abort = 1; } return 1; } /* ************************************************************************* * Function: Select best Intra chroma prediction mode for a 8x8 block * Input: * Output: * Return: * Attention: ************************************************************************* */ void IntraChromaPrediction8x8(int *mb_up,int *mb_left,int *mb_up_left) { int mode; int i,j; int best_mode; double min_cost; int img_cx = (pgMbData->mb_x<<3); int img_cy = (pgMbData->mb_y<<3); // WJP FOR INTRA_CHROMA_S 050321 //MZ int mb_available_up = (ipredmode[(pgMbData->mb_x << 2)+1][(pgMbData->mb_y << 2)] >=0); int mb_available_left = (ipredmode[(pgMbData->mb_x << 2)][(pgMbData->mb_y << 2)+1] >=0); int mb_available_up_left = (ipredmode[(pgMbData->mb_x << 2)][(pgMbData->mb_y << 2)] >=0); /* int mb_width = pgImage->img_width/16; int mb_available_up = (pgMbData->mb_y == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width].slice_nr); int mb_available_left = (pgMbData->mb_x == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr); int mb_available_up_left = (pgMbData->mb_y == 0 || pgMbData->mb_x == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width-1].slice_nr); // WJP END */ int best_pred_sample[2][8][8]; int rate; int dummy; int cost; int bx ,by; double distortion; double rdcost; int b8,b4; int uv; #ifdef _ISOLATED_REGION_ //added by cbzhu, 2004.12.4 if (input.IREGEnable) { if (pgImage->type == INTER_IMG) { if (mb_available_up != 0) { if (pCurrFrmIREGMap[pgImage->mb_y - 1][pgImage->mb_x] != 2) { mb_available_up = 0; } } if (mb_available_left != 0) { if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x - 1] != 2) { mb_available_left = 0; } } if (mb_available_up_left != 0) { if (pCurrFrmIREGMap[pgImage->mb_y - 1][pgImage->mb_x - 1] != 2) { mb_available_up_left = 0; } } } } #endif // _ISOLATED_REGION_ if (mb_up) *mb_up = mb_available_up; if (mb_left) *mb_left = mb_available_left; if (mb_up_left ) *mb_up_left = mb_available_up_left; best_mode = DC_PRED_8; //0 min_cost = 1<<20; for (mode = DC_PRED_8; mode <= VERT_PRED_8; mode++) { cost = 0; if ((mode == VERT_PRED_8 && !mb_available_up) || (mode == HOR_PRED_8 && !mb_available_left)) //(mode == PLANE_8 && (!mb_available_left || !mb_available_up || !mb_available_up_left)) { continue; } for (b4 = 0; b4 < 4; b4++) { intrapred_chroma_4x4(pgMbData->mb_x,pgMbData->mb_y,b4,mode); bx = (b4 &1)<<2; by = (b4>>1)<<2; for (uv=0; uv<2;uv++) { for(j=0;j<4;j++) //y { for(i=0;i<4;i++) //x { pgMbHeader->pred_residual[4+uv][b4][j][i] = pgMbData->org_chroma[uv][by+j][bx+i] - pgMbData->pred_curr[uv][by+j][bx+i]; pgMbData->pred_sample[4+uv][b4][j][i] = pgMbData->pred_curr[uv][by+j][bx+i]; } } Transform_B4(4+uv, b4); Quant_B4(pgMbData->qp_mb, 4+uv, b4, &dummy); Dequant_B4(pgMbData->qp_mb, 4+uv, b4); Inv_Transform_B4(4+uv, b4); Recon_B4(4+uv, b4, 0); for(j=0; j<4; j++) //y { for(i=0; i<4; i++) //x { imgUV[uv][(pgMbData->mb_y<<3) + (b4/2)*4+j][(pgMbData->mb_x<<3) +(b4%2)*4+ i] = imgUV1[uv][j][i]; } } } } if(!input.rdopt) // NO RD optimization { for (uv=0; uv<2;uv++) { for (j=0;j<8;j++)//y { for(i=0;i<8;i++)//x { cost += absm(pgMbData->org_chroma[uv][j][i] - pgMbData->pred_curr[uv][j][i]); } } } if (cost < min_cost) { best_mode = mode; min_cost = cost; for (uv=0; uv<2;uv++) { for (j=0; j<8; j++) { for (i=0; i<8; i++) { best_pred_sample[uv][j][i] = pgMbData->pred_curr[uv][j][i]; } } } } } else // RD OPT { Save_RD_State(); ue_linfo(mode); for (b8=4; b8<6; b8++) { for (b4=0; b4<4; b4++) { if(pgMbHeader->cbp_4x4[b8] & (1< byte_pos - pgRDStream->byte_pos)*8 + (pgRDStream->bits_to_go-pgcurrBitStream->bits_to_go); Restore_RD_State();//qwang 2004-3-15 distortion = 0; for(uv=0; uv<2; uv++) { for(j=0; j<8; j++) { for(i=0; i<8; i++) { distortion += quadarr[pgMbData->org_chroma[uv][j][i]-imgUV[uv][img_cy+j][img_cx+i]]; } } } rdcost = distortion + pgMbData->lamda_mode*rate; if(rdcost pred_curr[uv][j][i]; } } } }//end if(rdcost mb_x+1][pgMbData->mb_y+1] = best_mode; pgMbHeader->chroma_ipred_mode = best_mode; for(uv=0;uv<2;uv++) // zhangnan for (j=0; j<8; j++) for (i=0; i<8; i++) { pgMbHeader->pred_residual[4+uv][i/4+(j/4)*2][j%4][i%4] = pgMbData->org_chroma[uv][j][i] - best_pred_sample[uv][j][i]; pgMbData->pred_sample[4+uv][i/4+(j/4)*2][j%4][i%4] = best_pred_sample[uv][j][i]; } } /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ void intrapred_chroma_4x4( int mb_x, // mb x-pos in mb unit int mb_y, // mb y-pos in mb unit int b4, // subblock number int mode) // chroma pred mode { #define CBS 4 // chroma block size unsigned char edgepixu[20]; #define EU (edgepixu + 10) unsigned char edgepixv[20]; #define EV (edgepixv + 10) int hlineU[CBS],vlineU[CBS]; int hlineV[CBS],vlineV[CBS]; int x,y; int uv; int u0,v0; int bx = (b4 &1)<<2; int by = (b4>>1)<<2; int img_cx = (mb_x << 3) + bx; // block pel x int img_cy = (mb_y << 3) + by; // block pel y //MZ int mb_available_up = (ipredmode[(mb_x << 2)+1][(mb_y << 2)] >=0); int mb_available_left = (ipredmode[(mb_x << 2)][(mb_y << 2)+1] >=0); int mb_available_up_left = (ipredmode[(mb_x << 2)][(mb_y << 2)] >=0); /* int mb_width = pgImage->img_width/16; int mb_available_up = (pgMbData->mb_y == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width].slice_nr); int mb_available_left = (pgMbData->mb_x == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr); int mb_available_up_left = (pgMbData->mb_x == 0 || pgMbData->mb_y == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width-1].slice_nr); */ // int block_available_up = (b4 == 0||b4 == 1)?mb_available_up:1; int block_available_left = (b4 == 0||b4 == 2)?mb_available_left:1; int block_available_up_left = ((b4==0) ? mb_available_up_left : ((b4==1) ? mb_available_up : ((b4==2) ? mb_available_left : 1 ))); assert(b4>=0 && b4 <=3); uv = 0; if (block_available_up) { for(x=0;x pred_curr[0][by+y][bx+x] = u0; pgMbData->pred_curr[1][by+y][bx+x] = v0; } } break; case HOR_PRED_8: if (block_available_left) { for (y=0;y pred_curr[0][by+y][bx+x] = vlineU[y]; pgMbData->pred_curr[1][by+y][bx+x] = vlineV[y]; } } } break; case VERT_PRED_8: if (block_available_up) { for (x=0;x pred_curr[0][by+y][bx+x] = hlineU[x]; pgMbData->pred_curr[1][by+y][bx+x] = hlineV[x]; } } } break; default: fprintf(stderr,"Error in intrapred_chroma\n"); break; } } /* ************************************************************************* * Function:Intra chroma prediction for every 8x8 block * Input: * Output: * Return: * Attention: ************************************************************************* */ int Intra_Chroma_Prediction (int * min_cost) //zhangnan { int b8,b4,i,j; int dummy; IntraChromaPrediction8x8(NULL, NULL, NULL); //sw Chroma DC for (b8=4; b8<6; b8++) { for (b4=0; b4<4; b4++) { Transform_B4(b8, b4); } //TranformChromaDC(b8); for (b4=0; b4<4; b4++) { Quant_B4(pgMbData->qp_mb, b8, b4, &dummy); } // dongjie if(pgMbHeader->cbp_4x4[b8]==0) pgMbHeader->cbp &= (~(1< cbp |= (1< qp_mb, b8, b4); } //InvTransformChromaDC(b8); for (b4=0; b4<4; b4++) { Inv_Transform_B4(b8, b4); Recon_B4(b8, b4, 0); for(j=0; j<4; j++) for(i=0; i<4; i++) { imgUV[b8-4][(pgMbData->mb_y<<3) + (b4/2)*4+j][(pgMbData->mb_x<<3) +(b4%2)*4+ i] = imgUV1[b8-4][j][i]; } } } return 1; }