www.pudn.com > rm52c.rar > macroblock.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: macroblock.c * Function: Decode a Macroblock * ************************************************************************************* */ #include "contributors.h" #include#include #include #include #include "global.h" #include "mbuffer.h" #include "elements.h" #include "macroblock.h" #include "vlc.h" #include "defines.h" #include "block.h" void readReferenceIndex(struct img_par *img, struct inp_par *inp); void readMotionVector(struct img_par *img, struct inp_par *inp); //#define ZERO_P8x8 (mbmode==5) //xfwang delete 2004.7.29 #define MODE_IS_P8x8 (mbmode==4) #define MODE_IS_I4x4 (mbmode==5) //xfwang modify 2004.7.29 #define I16OFFSET (mbmode-7) #define fwd_ref_idx_to_refframe(idx) ((idx)+fwd_refframe_offset) #define bwd_ref_idx_to_refframe(idx) ((idx)+bwd_refframe_offset) /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ static void SetMotionVectorPredictor (struct img_par *img, int *pmv_x, int *pmv_y, int ref_frame, int **refFrArr, int ***tmp_mv, int block_x, int block_y, int blockshape_x, int blockshape_y, int ref, int direct_mv);//Lou 1016 /* ************************************************************************* * Function:Checks the availability of neighboring macroblocks of the current macroblock for prediction and context determination; marks the unavailable MBs for intra prediction in the ipredmode-array by -1. Only neighboring MBs in the causal past of the current MB are checked. * Input: * Output: * Return: * Attention: ************************************************************************* */ void CheckAvailabilityOfNeighbors(struct img_par *img) { int i,j; const int mb_width = img->width/MB_BLOCK_SIZE; const int mb_nr = img->current_mb_nr; Macroblock *currMB = &mb_data[mb_nr]; int check_value; // mark all neighbors as unavailable for (i=0; i<3; i++) for (j=0; j<3; j++) mb_data[mb_nr].mb_available[i][j]=NULL; mb_data[mb_nr].mb_available[1][1]=currMB; // current MB // Check MB to the left if(img->pix_x >= MB_BLOCK_SIZE) { int remove_prediction = currMB->slice_nr != mb_data[mb_nr-1].slice_nr; // upper blocks if (remove_prediction) { img->ipredmode[img->block_x][img->block_y+1] = -1; img->ipredmode[img->block_x][img->block_y+2] = -1; } if (!remove_prediction) { currMB->mb_available[1][0]=&(mb_data[mb_nr-1]); } } // Check MB above check_value = (img->pix_y >= MB_BLOCK_SIZE); if(check_value) { int remove_prediction = currMB->slice_nr != mb_data[mb_nr-mb_width].slice_nr; // upper blocks if (remove_prediction) { img->ipredmode[img->block_x+1][img->block_y] = -1; img->ipredmode[img->block_x+2][img->block_y] = -1; } if (!remove_prediction) { currMB->mb_available[0][1]=&(mb_data[mb_nr-mb_width]); } } // Check MB left above if(img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) { int remove_prediction = currMB->slice_nr != mb_data[mb_nr-mb_width-1].slice_nr; if (remove_prediction) { img->ipredmode[img->block_x][img->block_y] = -1; } if (!remove_prediction) { currMB->mb_available[0][0]=&(mb_data[mb_nr-mb_width-1]); } } // Check MB right above if(img->pix_y >= MB_BLOCK_SIZE && img->pix_x < (img->width-MB_BLOCK_SIZE )) { if(currMB->slice_nr == mb_data[mb_nr-mb_width+1].slice_nr) currMB->mb_available[0][2]=&(mb_data[mb_nr-mb_width+1]); } } void set_MB_parameters (struct img_par *img,struct inp_par *inp, int mb) { const int number_mb_per_row = img->width / MB_BLOCK_SIZE ; const int mb_nr = img->current_mb_nr; Macroblock *currMB = &mb_data[mb_nr]; img->mb_x = mb % number_mb_per_row; img->mb_y = mb / number_mb_per_row; // Define vertical positions img->block8_y= img->mb_y * BLOCK_SIZE/2; img->block_y = img->mb_y * BLOCK_SIZE/2; // vertical luma block position img->pix_y = img->mb_y * MB_BLOCK_SIZE; // vertical luma macroblock position img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; // vertical chroma macroblock position // Define horizontal positions img->block8_x= img->mb_x * BLOCK_SIZE/2; img->block_x = img->mb_x * BLOCK_SIZE/2; // luma block img->pix_x = img->mb_x * MB_BLOCK_SIZE; // luma pixel img->pix_c_x = img->mb_x * MB_BLOCK_SIZE/2; // chroma pixel } /* ************************************************************************* * Function:initializes the current macroblock * Input: * Output: * Return: * Attention: ************************************************************************* */ void start_macroblock(struct img_par *img,struct inp_par *inp) { int i,j,k,l; Macroblock *currMB; // intialization code deleted, see below, StW assert (img->current_mb_nr >=0 && img->current_mb_nr < img->max_mb_nr); currMB = &mb_data[img->current_mb_nr];//GB /* Update coordinates of the current macroblock */ img->mb_x = (img->current_mb_nr)%(img->width/MB_BLOCK_SIZE); img->mb_y = (img->current_mb_nr)/(img->width/MB_BLOCK_SIZE); /* Define vertical positions */ img->block_y = img->mb_y * BLOCK_SIZE/2; /* luma block position */ img->block8_y = img->mb_y * BLOCK_SIZE/2; img->pix_y = img->mb_y * MB_BLOCK_SIZE; /* luma macroblock position */ img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; /* chroma macroblock position */ /* Define horizontal positions */ img->block_x = img->mb_x * BLOCK_SIZE/2; /* luma block position */ img->block8_x = img->mb_x * BLOCK_SIZE/2; img->pix_x = img->mb_x * MB_BLOCK_SIZE; /* luma pixel position */ img->pix_c_x = img->mb_x * MB_BLOCK_SIZE/2; /* chroma pixel position */ // If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction CheckAvailabilityOfNeighbors(img); // support only slice mode 0 in MBINTLC1 at this time // Reset syntax element entries in MB struct currMB->qp = img->qp ; currMB->mb_type = 0; currMB->delta_quant = 0; currMB->cbp = 0; currMB->cbp_blk = 0; currMB->c_ipred_mode= DC_PRED_8; //GB for (l=0; l < 2; l++) for (j=0; j < BLOCK_MULTIPLE; j++) for (i=0; i < BLOCK_MULTIPLE; i++) for (k=0; k < 2; k++) currMB->mvd[l][j][i][k] = 0; currMB->cbp_bits = 0; // initialize img->m7 for ABT//Lou for (j=0; j m7[i][j] = 0; for (j=0; j m8[0][i][j] = 0; img->m8[1][i][j] = 0; } // currMB->lf_disable = inp->LFParametersFlag; jlzheng 7.8 currMB->lf_disable = loop_filter_disable; } /* ************************************************************************* * Function:Interpret the mb mode for P-Frames * Input: * Output: * Return: * Attention: ************************************************************************* */ void interpret_mb_mode_P(struct img_par *img) { int i; const int ICBPTAB[6] = {0,16,32,15,31,47}; Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; int mbmode = currMB->mb_type; if(mbmode <4) { currMB->mb_type = mbmode; for (i=0;i<4;i++) { currMB->b8mode[i] = mbmode; currMB->b8pdir[i] = 0; } } else if(MODE_IS_P8x8) { currMB->mb_type = P8x8; //img->allrefzero = ZERO_P8x8; //delete by xfwang 2004.7.29 } else if(/* MODE_IS_I4x4 qhg */mbmode>=5)//modefy by xfwang 2004.7.29 { currMB->cbp=NCBP[currMB->mb_type-5][0]; // qhg //modefy by xfwang 2004.7.29 currMB->mb_type = I4MB; for (i=0;i<4;i++) { currMB->b8mode[i] = IBLOCK; currMB->b8pdir[i] = -1; } } else { currMB->mb_type = I16MB; for (i=0;i<4;i++) {currMB->b8mode[i]=0; currMB->b8pdir[i]=-1; } currMB->cbp= ICBPTAB[(I16OFFSET)>>2]; } } /* ************************************************************************* * Function:Interpret the mb mode for I-Frames * Input: * Output: * Return: * Attention: ************************************************************************* */ void interpret_mb_mode_I(struct img_par *img) { int i; const int ICBPTAB[6] = {0,16,32,15,31,47}; Macroblock *currMB = &mb_data[img->current_mb_nr]; int num =4; currMB->mb_type = I4MB; for (i=0;i<4;i++) { currMB->b8mode[i]=IBLOCK; currMB->b8pdir[i]=-1; } for (i=num;i<4;i++) {currMB->b8mode[i]=currMB->mb_type_2==P8x8? 4 : currMB->mb_type_2; currMB->b8pdir[i]=0; } } /* ************************************************************************* * Function:Interpret the mb mode for B-Frames * Input: * Output: * Return: * Attention: ************************************************************************* */ void interpret_mb_mode_B(struct img_par *img) { static const int offset2pdir16x16[12] = {0, 0, 1, 2, 0,0,0,0,0,0,0,0}; static const int offset2pdir16x8[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},{1,0}, {0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2},{0,0}}; static const int offset2pdir8x16[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0}, {1,0},{0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2}}; const int ICBPTAB[6] = {0,16,32,15,31,47}; Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; int i, mbmode; int mbtype = currMB->mb_type; int *b8mode = currMB->b8mode; int *b8pdir = currMB->b8pdir; //--- set mbtype, b8type, and b8pdir --- if (mbtype==0) // direct { mbmode=0; for(i=0;i<4;i++) {b8mode[i]=0; b8pdir[i]=2; } } else if (/*mbtype==23 qhg */ mbtype>=23) // intra4x4 { currMB->cbp=NCBP[mbtype-23][0]; // qhg mbmode=I4MB; for(i=0;i<4;i++) {b8mode[i]=IBLOCK; b8pdir[i]=-1; } } else if (mbtype==22) // 8x8(+split) { mbmode=P8x8; // b8mode and pdir is transmitted in additional codewords } else if (mbtype<4) // 16x16 { mbmode=1; for(i=0;i<4;i++) {b8mode[i]=1; b8pdir[i]=offset2pdir16x16[mbtype]; } } else if (mbtype%2==0) // 16x8 { mbmode=2; for(i=0;i<4;i++) {b8mode[i]=2; b8pdir[i]=offset2pdir16x8 [mbtype][i/2]; } } else { mbmode=3; for(i=0;i<4;i++) {b8mode[i]=3; b8pdir[i]=offset2pdir8x16 [mbtype][i%2]; } } currMB->mb_type = mbmode; } /* ************************************************************************* * Function:init macroblock I and P frames * Input: * Output: * Return: * Attention: ************************************************************************* */ void init_macroblock(struct img_par *img) { int i,j; Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; img->mv[img->block_x+4][img->block_y][2]=img->number; for (i=0;i<2;i++) { // reset vectors and pred. modes for(j=0;j<2;j++) { img->mv[img->block_x+i+4][img->block_y+j][0] = 0; img->mv[img->block_x+i+4][img->block_y+j][1] = 0; } } for (i=0;i<2;i++) { // reset vectors and pred. modes for(j=0;j<2;j++) { img->ipredmode[img->block_x+i+1][img->block_y+j+1] = DC_PRED; } } // Set the reference frame information for motion vector prediction if (IS_INTRA (currMB)) { for (j=0; j<2; j++) for (i=0; i<2; i++) { refFrArr[img->block_y+j][img->block_x+i] = -1; } } else if (!IS_P8x8 (currMB)) { for (j=0; j<2; j++) for (i=0; i<2; i++) { refFrArr[img->block_y+j][img->block_x+i] = 0; } } else { for (j=0; j<2; j++) for (i=0; i<2; i++) { refFrArr[img->block_y+j][img->block_x+i] = (currMB->b8mode[2*j+i]==IBLOCK ? -1 : 0); } } } /* ************************************************************************* * Function:Sets mode for 8x8 block * Input: * Output: * Return: * Attention: ************************************************************************* */ void SetB8Mode (struct img_par* img, Macroblock* currMB, int value, int i) { static const int p_v2b8 [ 5] = {4, 5, 6, 7, IBLOCK}; static const int p_v2pd [ 5] = {0, 0, 0, 0, -1}; static const int b_v2b8 [14] = {0, 4, 4, 4, 5, 6, 5, 6, 5, 6, 7, 7, 7, IBLOCK}; static const int b_v2pd [14] = {2, 0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2, -1}; if (img->type==B_IMG) { currMB->b8mode[i] = b_v2b8[value]; currMB->b8pdir[i] = b_v2pd[value]; } else { currMB->b8mode[i] = p_v2b8[value]; currMB->b8pdir[i] = p_v2pd[value]; } } /* ************************************************************************* * Function:Get the syntax elements from the NAL * Input: * Output: * Return: * Attention: ************************************************************************* */ int read_one_macroblock(struct img_par *img,struct inp_par *inp) { int i,j; SyntaxElement currSE; Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; int img_block_y; int real_mb_type; //img->allrefzero = 0; //delete by xfwang 2004.7.29 for(i=0;i<8;i++) for(j=0;j<8;j++) { img->m8[0][i][j]=0; img->m8[1][i][j]=0; } currMB->qp = img->qp ; currSE.type = SE_MBTYPE; currSE.mapping = linfo_ue; currMB->mb_type_2= 0; if(img->type == I_IMG) { currMB->mb_type = 0; } else if(skip_mode_flag) { if(img->cod_counter == -1) { #if TRACE strncpy(currSE.tracestring, "MB runlength", TRACESTRING_SIZE); #endif readSyntaxElement_UVLC(&currSE,inp); img->cod_counter = currSE.value1; } if (img->cod_counter==0) { #if TRACE strncpy(currSE.tracestring, "MB Type", TRACESTRING_SIZE); #endif readSyntaxElement_UVLC(&currSE,inp); if(img->type == P_IMG) currSE.value1++; currMB->mb_type = currSE.value1; img->cod_counter--; } else { img->cod_counter--; currMB->mb_type = 0; // !! skip mode shenyanfei } }else { #if TRACE strncpy(currSE.tracestring, "MB Type", TRACESTRING_SIZE); #endif readSyntaxElement_UVLC(&currSE,inp); if(img->type == P_IMG) currSE.value1++; currSE.value1--; real_mb_type = currSE.value1; if(currSE.value1<0) currSE.value1 = 0; currMB->mb_type = currSE.value1; img->cod_counter--; } if ((img->type==P_IMG )) // inter frame interpret_mb_mode_P(img); else if (img->type==I_IMG) // intra frame interpret_mb_mode_I(img); else if ((img->type==B_IMG)) // B frame interpret_mb_mode_B(img); //====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ====== if (IS_P8x8 (currMB)) { currSE.type = SE_MBTYPE; if(img->type!=P_IMG) { for (i=0; i<4; i++) { currSE.mapping = linfo_ue; #if TRACE strncpy(currSE.tracestring, "8x8 mode", TRACESTRING_SIZE); #endif //mb_part_type is fix length coding(fix length equal 2)!! jlzheng 7.22 assert (currStream->streamBuffer != NULL); currSE.len = 2; readSyntaxElement_FLC (&currSE); // END SetB8Mode (img, currMB, currSE.value1, i); } } else { currSE.value1 = 0; for (i=0; i<4; i++) { SetB8Mode (img, currMB, currSE.value1, i); } } } //! TO for Error Concelament //! If we have an INTRA Macroblock and we lost the partition //! which contains the intra coefficients Copy MB would be better //! than just a grey block. //! Seems to be a bit at the wrong place to do this right here, but for this case //! up to now there is no other way.//Lou //--- init macroblock data --- if (img->type==B_IMG) init_macroblock_Bframe(img); else init_macroblock (img); if (IS_INTRA(currMB)) { for (i=0;i<5;i++) read_ipred_block_modes(img,inp,i); } if (skip_mode_flag) { if (IS_DIRECT (currMB) && img->cod_counter >= 0) { int i, j, iii, jjj; currMB->cbp = 0; for (i=0;i cof[i][j][iii][jjj]=0; } for (j=4;j<6;j++) { // reset chroma coeffs for (i=0;i<4;i++) for (iii=0;iii<4;iii++) for (jjj=0;jjj<4;jjj++) img->cof[i][j][iii][jjj]=0; } return DECODE_MB; } }else { if (img->type==B_IMG&& real_mb_type<0) { int i, j, iii, jjj; currMB->cbp = 0; for (i=0;i cof[i][j][iii][jjj]=0; } for (j=4;j<6;j++) { // reset chroma coeffs for (i=0;i<4;i++) for (iii=0;iii<4;iii++) for (jjj=0;jjj<4;jjj++) img->cof[i][j][iii][jjj]=0; } return DECODE_MB; } } if (IS_COPY (currMB)) //keep last macroblock { int i, j, iii, jjj, pmv[2]; int ***tmp_mv = img->mv; int mb_available_up = (img->mb_y == 0) ? 0 : (currMB->slice_nr == mb_data[img->current_mb_nr-img->width/16].slice_nr); int mb_available_left = (img->mb_x == 0) ? 0 : (currMB->slice_nr == mb_data[img->current_mb_nr-1].slice_nr); int zeroMotionAbove = !mb_available_up ? 1 : refFrArr[img->block_y-1][img->block_x] == 0 && tmp_mv[4+img->block_x ][img->block_y-1][0] == 0 && tmp_mv[4+img->block_x ][img->block_y-1][1] == 0 ? 1 : 0; int zeroMotionLeft = !mb_available_left? 1 : refFrArr[img->block_y][img->block_x-1] == 0 && tmp_mv[4+img->block_x-1][img->block_y ][0] == 0 && tmp_mv[4+img->block_x-1][img->block_y ][1] == 0 ? 1 : 0; currMB->cbp = 0; for (i=0;i cof[i][j][iii][jjj]=0; } for (j=4;j<6;j++) { // reset chroma coeffs for (i=0;i<4;i++) for (iii=0;iii<4;iii++) for (jjj=0;jjj<4;jjj++) img->cof[i][j][iii][jjj]=0; } img_block_y = img->block_y; if (zeroMotionAbove || zeroMotionLeft) { for(i=0;i<2;i++) for(j=0;j<2;j++) { img->mv[img->block_x+i+BLOCK_SIZE][img->block_y+j][0] = 0; img->mv[img->block_x+i+BLOCK_SIZE][img->block_y+j][1] = 0; } } else { //SetMotionVectorPredictor (img, pmv, pmv+1, 0, refFrArr, img->mv, 0, 0, 16, 16); SetMotionVectorPredictor (img, pmv, pmv+1, 0, refFrArr, img->mv, 0, 0, 16, 16, 0, 0);//Lou 1016 for(i=0;i<2;i++) for(j=0;j<2;j++) { img->mv[img->block_x+i+BLOCK_SIZE][img_block_y+j][0] = pmv[0]; img->mv[img->block_x+i+BLOCK_SIZE][img_block_y+j][1] = pmv[1]; } } for (j=0; j<2;j++) for (i=0; i<2;i++) { refFrArr_frm[img->block_y+j][img->block_x+i] = 0; } return DECODE_MB; } readReferenceIndex(img, inp); readMotionVector (img, inp); // !! start shenyanfei if((!IS_INTRA(currMB)) && (img->picture_weighting_flag == 1) && (img->allframeweight == 0)){ img->mbweightflag = u_v(1,"mb weighting flag"); } // !! end shenyanfei // read CBP if not new intra mode if (!(IS_COPY (currMB) || (IS_DIRECT (currMB) && img->cod_counter >= 0))) { if (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB ) currSE.type = SE_CBP_INTRA; else currSE.type = SE_CBP_INTER; if (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB) currSE.mapping = linfo_cbp_intra; else currSE.mapping = linfo_cbp_inter; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "CBP"); #endif if(img->type==I_IMG||IS_INTER(currMB)) // qhg { currSE.golomb_maxlevels = 0; readSyntaxElement_UVLC(&currSE,inp); currMB->cbp = currSE.value1; } // Delta quant only if nonzero coeffs if (!fixed_picture_qp&&currMB->cbp !=0) { if (IS_INTER (currMB)) currSE.type = SE_DELTA_QUANT_INTER; else currSE.type = SE_DELTA_QUANT_INTRA; currSE.mapping = linfo_se; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "Delta quant "); #endif readSyntaxElement_UVLC(&currSE,inp); currMB->delta_quant = currSE.value1; img->qp= (img->qp-MIN_QP+currMB->delta_quant+(MAX_QP-MIN_QP+1))%(MAX_QP-MIN_QP+1)+MIN_QP; } if (fixed_picture_qp) { currMB->delta_quant = 0; img->qp= (img->qp-MIN_QP+currMB->delta_quant+(MAX_QP-MIN_QP+1))%(MAX_QP-MIN_QP+1)+MIN_QP; } } // read CBP and Coeffs *************************************************************** readCBPandCoeffsFromNAL (img,inp); return DECODE_MB; } void read_ipred_block_modes(struct img_par *img,struct inp_par *inp,int b8) { int bi,bj,dec; SyntaxElement currSE; Macroblock *currMB; int j2; int mostProbableIntraPredMode; int upIntraPredMode; int leftIntraPredMode; int IntraChromaPredModeFlag; int MBRowSize = img->width / MB_BLOCK_SIZE; currMB=mb_data+img->current_mb_nr;//current_mb_nr; IntraChromaPredModeFlag = IS_INTRA(currMB); currSE.type = SE_INTRAPREDMODE; #if TRACE strncpy(currSE.tracestring, "Ipred Mode", TRACESTRING_SIZE); #endif if(b8<4) { if( currMB->b8mode[b8]==IBLOCK ) { IntraChromaPredModeFlag = 1; //get from stream readSyntaxElement_Intra8x8PredictionMode(&currSE); //get from array and decode bi = img->block_x + (b8&1); bj = img->block_y + (b8/2); upIntraPredMode = img->ipredmode[bi+1][bj]; leftIntraPredMode = img->ipredmode[bi][bj+1]; mostProbableIntraPredMode = (upIntraPredMode < 0 || leftIntraPredMode < 0) ? DC_PRED : upIntraPredMode < leftIntraPredMode ? upIntraPredMode : leftIntraPredMode; dec = (currSE.value1 == -1) ? mostProbableIntraPredMode : currSE.value1 + (currSE.value1 >= mostProbableIntraPredMode); //set img->ipredmode[1+bi][1+bj]=dec; j2 = bj; } } else if( b8==4&&currMB->b8mode[b8-3]==IBLOCK) { currSE.type = SE_INTRAPREDMODE; #if TRACE strncpy(currSE.tracestring, "Chroma intra pred mode", TRACESTRING_SIZE); #endif currSE.mapping = linfo_ue; readSyntaxElement_UVLC(&currSE,inp); currMB->c_ipred_mode = currSE.value1; if (currSE.value1 < DC_PRED_8 || currSE.value1 > PLANE_8) { printf("%d\n", img->current_mb_nr); error("illegal chroma intra pred mode!\n", 600); } } } /* ****************************************************************************** * Function: calculated field or frame distance between current field(frame) * and the reference field(frame). * Input: * Output: * Return: * Attention: * Author: Yulejun // 2004.07.14 ****************************************************************************** */ int calculate_distance(int blkref, int fw_bw ) //fw_bw>=0: forward ; fw_bw<0: backward { int distance; if( img->picture_structure == 1 ) { if ( img->type==P_IMG ) // P img { if(blkref==0) distance = img->tr*2 - img->imgtr_last_P*2; else if(blkref==1) distance = img->tr*2 - img->imgtr_last_prev_P*2; else { assert(0); //only two reference pictures for P frame } } else //B_IMG { if (fw_bw >=0 ) //forward distance = img->tr*2 - img->imgtr_last_P*2; else distance = img->imgtr_next_P*2 - img->tr*2; } } else if( ! img->picture_structure ) { if(img->type==P_IMG) { if(img->top_bot==0) //top field { switch ( blkref ) { case 0: distance = img->tr*2 - img->imgtr_last_P*2 - 1 ; break; case 1: distance = img->tr*2 - img->imgtr_last_P*2 ; break; case 2: distance = img->tr*2 - img->imgtr_last_prev_P*2 - 1; break; case 3: distance = img->tr*2 - img->imgtr_last_prev_P*2 ; break; } } else if(img->top_bot==1) // bottom field. { switch ( blkref ) { case 0: distance = 1 ; break; case 1: distance = img->tr*2 - img->imgtr_last_P*2 ; break; case 2: distance = img->tr*2 - img->imgtr_last_P*2 + 1; break; case 3: distance = img->tr*2 - img->imgtr_last_prev_P*2 ; break; } } else { printf("Error. frame picture should not run into this branch."); exit(-1); } } else if(img->type==B_IMG) { assert(blkref==0 || blkref == 1); if (fw_bw >= 0 ) //forward { if(img->top_bot==0) //top field { switch ( blkref ) { case 0: distance = img->tr*2 - img->imgtr_last_P*2 - 1 ; break; case 1: distance = img->tr*2 - img->imgtr_last_P*2; break; } } else if(img->top_bot==1) // bottom field. { switch ( blkref ) { case 0: distance = img->tr*2 - img->imgtr_last_P*2 ; break; case 1: distance = img->tr*2 - img->imgtr_last_P*2 + 1; break; } } else { printf("Error. frame picture should not run into this branch."); exit(-1); } } else // backward { if(img->top_bot==0) //top field { switch ( blkref ) { case 0: distance = img->imgtr_next_P*2 - img->tr*2; break; case 1: distance = img->imgtr_next_P*2 - img->tr*2 + 1; break; } } else if(img->top_bot==1) // bottom field. { switch ( blkref ) { case 0: distance = img->imgtr_next_P*2 - img->tr*2 - 1; break; case 1: distance = img->imgtr_next_P*2 - img->tr*2 ; break; } } else { printf("Error. frame picture should not run into this branch."); exit(-1); } } } } return distance; } /*Lou 1016 Start*/ //The unit of time distance is calculated by field time /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ int scale_motion_vector(int motion_vector, int currblkref, int neighbourblkref, int currsmbtype, int neighboursmbtype, int block_y_pos, int curr_block_y, int ref, int direct_mv) { int neighbour_coding_stage = -2; int current_coding_stage = -2; int sign = (motion_vector>0?1:-1); int mult_distance; int devide_distance; //jhzheng 20040823 // if(!direct_mv) motion_vector = abs(motion_vector); if(motion_vector == 0) return 0; mult_distance = calculate_distance( currblkref, ref ); devide_distance = calculate_distance(neighbourblkref, ref); //jhzheng 20040823 // if(!direct_mv) // motion_vector = sign*((motion_vector*mult_distance*(512/devide_distance)+256)>>9); // else // motion_vector = ((motion_vector * mult_distance * (512 / devide_distance) + 256 ) >>9 ); motion_vector = sign*((motion_vector*mult_distance*(512/devide_distance)+256)>>9); return motion_vector; } /*Lou 1016 End*/ /* ************************************************************************* * Function:Set motion vector predictor * Input: * Output: * Return: * Attention: ************************************************************************* */ static void SetMotionVectorPredictor (struct img_par *img, int *pmv_x, int *pmv_y, int ref_frame, int **refFrArr, int ***tmp_mv, int block_x, int block_y, int blockshape_x, int blockshape_y, int ref, int direct_mv)//Lou 1016 { int mb_x = 8*block_x; int mb_y = 8*block_y; int pic_block_x = img->block_x + block_x; int pic_block_y = img->block_y + block_y; int mb_width = img->width/16; int mb_nr = img->current_mb_nr; int mb_available_up = (img->mb_y == 0 ) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width ].slice_nr); // jlzheng 6.23 int mb_available_left = (img->mb_x == 0 ) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-1 ].slice_nr); // jlzheng 6.23 int mb_available_upleft = (img->mb_x == 0) ? 0 : ((img->mb_y == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width-1].slice_nr)); int mb_available_upright = (img->mb_y == 0) ? 0 : ((img->mb_x >= (mb_width-1)) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width+1].slice_nr)); int block_available_up, block_available_left, block_available_upright, block_available_upleft; int mv_a, mv_b, mv_c, mv_d, pred_vec=0; int mvPredType, rFrameL, rFrameU, rFrameUR; int hv; int mva[3] , mvb[3],mvc[3]; int y_up = 1,y_upright=1,y_upleft=1,off_y=0; /*Lou 1016 Start*/ int rFrameUL; Macroblock* currMB = &mb_data[img->current_mb_nr]; int smbtypecurr, smbtypeL, smbtypeU, smbtypeUL, smbtypeUR; smbtypecurr = -2; smbtypeL = -2; smbtypeU = -2; smbtypeUL = -2; smbtypeUR = -2; /*Lou 1016 End*/ /* D B C */ /* A X */ /* 1 A, B, D are set to 0 if unavailable */ /* 2 If C is not available it is replaced by D */ block_available_up = mb_available_up || (mb_y > 0); block_available_left = mb_available_left || (mb_x > 0); if (mb_y > 0) { if (mb_x < 8) // first column of 8x8 blocks { if (mb_y==8) { if (blockshape_x == 16) block_available_upright = 0; else block_available_upright = 1; } else { if (mb_x+blockshape_x != 8) block_available_upright = 1; else block_available_upright = 0; } } else { if (mb_x+blockshape_x != 16) block_available_upright = 1; else block_available_upright = 0; } } else if (mb_x+blockshape_x != MB_BLOCK_SIZE) { block_available_upright = block_available_up; } else { block_available_upright = mb_available_upright; } if (mb_x > 0) { block_available_upleft = (mb_y > 0 ? 1 : mb_available_up); } else if (mb_y > 0) { block_available_upleft = mb_available_left; } else { block_available_upleft = mb_available_upleft; } smbtypecurr = -2; smbtypeL = -2; smbtypeU = -2; smbtypeUL = -2; smbtypeUR = -2; mvPredType = MVPRED_MEDIAN; rFrameL = block_available_left ? refFrArr[pic_block_y] [pic_block_x-1] : -1; rFrameU = block_available_up ? refFrArr[pic_block_y-1][pic_block_x] : -1; rFrameUR = block_available_upright ? refFrArr[pic_block_y-1][pic_block_x+blockshape_x/8] : block_available_upleft ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; rFrameUL = block_available_upleft ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; if((rFrameL != -1)&&(rFrameU == -1)&&(rFrameUR == -1)) mvPredType = MVPRED_L; else if((rFrameL == -1)&&(rFrameU != -1)&&(rFrameUR == -1)) mvPredType = MVPRED_U; else if((rFrameL == -1)&&(rFrameU == -1)&&(rFrameUR != -1)) mvPredType = MVPRED_UR; /*Lou 1016 End*/ // Directional predictions else if(blockshape_x == 8 && blockshape_y == 16) { if(mb_x == 0) { if(rFrameL == ref_frame) mvPredType = MVPRED_L; } else { if( rFrameUR == ref_frame) mvPredType = MVPRED_UR; } } else if(blockshape_x == 16 && blockshape_y == 8) { if(mb_y == 0) { if(rFrameU == ref_frame) mvPredType = MVPRED_U; } else { if(rFrameL == ref_frame) mvPredType = MVPRED_L; } } // #define MEDIAN(a,b,c) (a>b?a>c?b>c?b:c:a:b>c?a>c?a:c:b) #define MEDIAN(a,b,c) (a + b + c - min(a, min(b, c)) - max(a, max(b, c))); for (hv=0; hv < 2; hv++) { mva[hv] = mv_a = block_available_left ? tmp_mv[4+pic_block_x-1 ][pic_block_y][hv] : 0; mvb[hv] = mv_b = block_available_up ? tmp_mv[4+pic_block_x ][pic_block_y-1][hv] : 0; mv_d = block_available_upleft ? tmp_mv[4+pic_block_x-1][pic_block_y-1][hv] : 0; mvc[hv] = mv_c = block_available_upright ? tmp_mv[4+pic_block_x+blockshape_x/8][pic_block_y-1][hv] : mv_d; //--- Yulj 2004.07.14 // mv_a, mv_b... are not scaled. mva[hv] = scale_motion_vector(mva[hv], ref_frame, rFrameL, smbtypecurr, smbtypeL, pic_block_y-off_y, pic_block_y, ref, direct_mv); mvb[hv] = scale_motion_vector(mvb[hv], ref_frame, rFrameU, smbtypecurr, smbtypeU, pic_block_y-y_up, pic_block_y, ref, direct_mv); mv_d = scale_motion_vector(mv_d, ref_frame, rFrameUL, smbtypecurr, smbtypeUL, pic_block_y-y_upleft, pic_block_y, ref, direct_mv); mvc[hv] = block_available_upright ? scale_motion_vector(mvc[hv], ref_frame, rFrameUR, smbtypecurr, smbtypeUR, pic_block_y-y_upright, pic_block_y, ref, direct_mv): mv_d; switch (mvPredType) { case MVPRED_MEDIAN: if(hv == 1){ // jlzheng 7.2 // !! for A mva[2] = abs(mva[0] - mvb[0]) + abs(mva[1] - mvb[1]); // !! for B mvb[2] = abs(mvb[0] - mvc[0]) + abs(mvb[1] - mvc[1]); // !! for C mvc[2] = abs(mvc[0] - mva[0]) + abs(mvc[1] - mva[1]); pred_vec = MEDIAN(mva[2],mvb[2],mvc[2]); if(pred_vec == mva[2]){ *pmv_x = mvc[0]; *pmv_y = mvc[1]; } else if(pred_vec == mvb[2]){ *pmv_x = mva[0]; *pmv_y = mva[1]; } else{ *pmv_x = mvb[0]; *pmv_y = mvb[1]; } // END } break; case MVPRED_L: pred_vec = mv_a; break; case MVPRED_U: pred_vec = mv_b; break; case MVPRED_UR: pred_vec = mv_c; break; default: break; } if(mvPredType != MVPRED_MEDIAN){ if (hv==0) *pmv_x = pred_vec; else *pmv_y = pred_vec; } } #undef MEDIAN } /* ************************************************************************* * Function:Set context for reference frames * Input: * Output: * Return: * Attention: ************************************************************************* */ int BType2CtxRef (int btype) { if (btype<4) return 0; else return 1; } /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ void readReferenceIndex(struct img_par *img, struct inp_par *inp) { int i,j,k; // int mb_nr = img->current_mb_nr; //GB Falsch Macroblock *currMB = &mb_data[img->current_mb_nr]; SyntaxElement currSE; int bframe = (img->type==B_IMG); int partmode = (IS_P8x8(currMB)?4:currMB->mb_type); int step_h0 = BLOCK_STEP [partmode][0]; int step_v0 = BLOCK_STEP [partmode][1]; int i0, j0, refframe; int **fwRefFrArr = img->fw_refFrArr; int **bwRefFrArr = img->bw_refFrArr; int ***fw_mv = img->fw_mv; int ***bw_mv = img->bw_mv; //int **moving_block_dir = moving_block; int flag_mode; // If multiple ref. frames, read reference frame for the MB ********************************* flag_mode = 0; currSE.type = SE_REFFRAME; currSE.mapping = linfo_ue; if(currMB->mb_type!=I4MB) { step_h0 = (BLOCK_STEP[IS_P8x8(currMB) ? 4 : currMB->mb_type][0]); step_v0 = (BLOCK_STEP[IS_P8x8(currMB) ? 4 : currMB->mb_type][1]); } // !! shenyanfei for (j0=0; j0<2; ) { if((currMB->mb_type==I4MB&&j0==0)) { j0 += 1; continue;} for (i0=0; i0<2; ) { k=2*j0+i0; if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0) { img->subblock_x = i0; img->subblock_y = j0; if ((!picture_reference_flag&&img->type==P_IMG && img->types!=I_IMG) || (/*modifyby xfwang 2004.7.29*/!picture_reference_flag&&!img->picture_structure && img->types!=I_IMG)) //&&!img->allrefzero)//del by xfwang 2004.7.29 { #if TRACE strncpy(currSE.tracestring, "Fwd ref frame no ", TRACESTRING_SIZE); #endif currSE.context = BType2CtxRef (currMB->b8mode[k]); if(img->picture_structure || bframe) currSE.len = 1; else currSE.len = 2; readSyntaxElement_FLC(&currSE); refframe = currSE.value1; } else { refframe = 0; } if (!bframe) { for (j=j0; j block_y+j][img->block_x+i] = refframe; } else // !! for B frame shenyanfei { for (j=j0; j fw_refFrArr[img->block_y+j][img->block_x+i] = refframe; if (currMB->b8pdir[k]==2 && !img->picture_structure) { for (j=j0; j bw_refFrArr[img->block_y+j][img->block_x+i] = 1-refframe; } } } i0+=max(1,step_h0); } j0+=max(1,step_v0); } for (j0=0; j0<2; ) { if((currMB->mb_type==I4MB&&j0==0)) { j0 += 1; continue;} for (i0=0; i0<2; ) { k=2*j0+i0; if ((currMB->b8pdir[k]==1) && currMB->b8mode[k]!=0) { img->subblock_x = i0; img->subblock_y = j0; if (img->type==B_IMG && !img->picture_structure&&/*modifyby xfwang 2004.7.29*/!picture_reference_flag) //&&!img->allrefzero)//del by xfwang 2004.7.29 { #if TRACE strncpy(currSE.tracestring, "Bwd ref frame no ", TRACESTRING_SIZE); #endif currSE.context = BType2CtxRef (currMB->b8mode[k]); if(img->picture_structure || bframe) currSE.len = 1; else currSE.len = 2; readSyntaxElement_FLC(&currSE); refframe = currSE.value1; } else { refframe = 0; } for (j=j0; j bw_refFrArr[img->block_y+j][img->block_x+i] = refframe; } i0+=max(1,step_h0); } j0+=max(1,step_v0); } } /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ void readMotionVector(struct img_par *img, struct inp_par *inp) { int i,j,k,l,m,n; int step_h,step_v; int curr_mvd; // int mb_nr = img->current_mb_nr; //GB Falsch Macroblock *currMB = &mb_data[img->current_mb_nr]; SyntaxElement currSE; int bframe = (img->type==B_IMG); int partmode = (IS_P8x8(currMB)?4:currMB->mb_type); int step_h0 = BLOCK_STEP [partmode][0]; int step_v0 = BLOCK_STEP [partmode][1]; int mv_mode, i0, j0, refframe; int pmv[2]; int j4, i4, ii,jj; int vec; int iTRb,iTRp,iTRd; int mv_scale; int frame_no_next_P, frame_no_B, delta_P; int ref; int img_block_y; int use_scaled_mv; int fw_refframe,current_tr; int **fwRefFrArr = img->fw_refFrArr; int **bwRefFrArr = img->bw_refFrArr; int ***fw_mv = img->fw_mv; int ***bw_mv = img->bw_mv; int scale_refframe,iTRp1,bw_ref; if (bframe && IS_P8x8 (currMB)) { for (i=0;i<4;i++) { if (currMB->b8mode[i] == 0) { for(j=i/2;jfw_refFrArr[img->block_y + j][img->block_x + k] = 0; img->bw_refFrArr[img->block_y + j][img->block_x + k] = 0; } } } } } //===== READ FORWARD MOTION VECTORS ===== currSE.type = SE_MVD; currSE.mapping = linfo_se; for (j0=0; j0<2; ) { if(currMB->mb_type!=I4MB) { step_h0 = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][0]); step_v0 = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][1]); } if((currMB->mb_type==I4MB&&j0==0)) // for by jhzheng [2004/08/02] { j0 += 1; continue;} //{break;} for (i0=0; i0<2; ) { k=2*j0+i0; if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && (currMB->b8mode[k] !=0))//has forward vector { mv_mode = currMB->b8mode[k]; step_h = BLOCK_STEP [mv_mode][0]; step_v = BLOCK_STEP [mv_mode][1]; if (!bframe) refframe = refFrArr [img->block_y+j0][img->block_x+i0]; else refframe = img->fw_refFrArr[img->block_y+j0][img->block_x+i0]; for (j=j0; j block_y+j; i4 = img->block_x+i; // first make mv-prediction if (!bframe) SetMotionVectorPredictor (img, pmv, pmv+1, refframe, refFrArr, img->mv, i, j, 8*step_h, 8*step_v, 0, 0);//Lou 1016 else SetMotionVectorPredictor (img, pmv, pmv+1, refframe, img->fw_refFrArr, img->fw_mv, i, j, 8*step_h, 8*step_v, 0, 0);//Lou 1016 for (n=0; n < 2; n++) { #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "FMVD (pred %d)",pmv[n]); #endif img->subblock_x = i; // position used for context determination img->subblock_y = j; // position used for context determination currSE.value2 = (!bframe ? n : 2*n); // identifies the component; only used for context determination readSyntaxElement_UVLC(&currSE,inp); curr_mvd = currSE.value1; vec=curr_mvd+pmv[n]; /* find motion vector */ // need B support if (!bframe) { for(ii=0;ii mv[i4+ii+BLOCK_SIZE][j4+jj][n]=vec; } else // B frame { for(ii=0;ii fw_mv[i4+ii+BLOCK_SIZE][j4+jj][n]=vec; } /* store (oversampled) mvd */ for (l=0; l < step_v; l++) for (m=0; m < step_h; m++) currMB->mvd[0][j+l][i+m][n] = curr_mvd; } } } else if (currMB->b8mode[k=2*j0+i0]==0) {// direct mode // by Junhao Zheng 2004-08-04 22:00:51 //step_v0 = step_h0 = 1; for (j=j0; j block_y+j][img->block_x+i]; img_block_y = (img->current_mb_nr%2) ? (img->block_y-4)/2:img->block_y/2; if(ref == -1) { // for by jhzheng [2004/08/03] #if TRACE_PREMV g_is_spatial_direct[k] = 1; #endif //sw img->fw_refFrArr[img->block_y+j][img->block_x+i]=0; img->bw_refFrArr[img->block_y+j][img->block_x+i]=0; j4 = img->block_y+j; i4 = img->block_x+i; for (ii=0; ii < 2; ii++) { img->fw_mv[i4+BLOCK_SIZE][j4][ii]=0; img->bw_mv[i4+BLOCK_SIZE][j4][ii]=0; } SetMotionVectorPredictor(img,&(img->fw_mv[i4+BLOCK_SIZE][j4][0]), &(img->fw_mv[i4+BLOCK_SIZE][j4][1]),0,img->fw_refFrArr, img->fw_mv,0,0,16,16, 0, 1); SetMotionVectorPredictor(img,&(img->bw_mv[i4+BLOCK_SIZE][j4][0]), &(img->bw_mv[i4+BLOCK_SIZE][j4][1]),0,img->bw_refFrArr, img->bw_mv,0,0,16,16, -1, 1); } else { frame_no_next_P =2*img->imgtr_next_P; frame_no_B = 2*img->tr; delta_P = 2* (img->imgtr_next_P - img->imgtr_last_P); if(!img->picture_structure) { if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field scale_refframe = ref == 0 ? 0 : 1; else scale_refframe = ref == 1 ? 1 : 2; } else scale_refframe = 0; if(img->picture_structure) { iTRp = (ref+1)*delta_P; iTRp1 = (scale_refframe+1)*delta_P; }else { if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field { iTRp = delta_P*(ref/2+1)-(ref+1)%2; //the lates backward reference iTRp1 = delta_P*(scale_refframe/2+1)-(scale_refframe+1)%2; //the lates backward reference bw_ref = 0; } else { iTRp = 1 + delta_P*((ref+1)/2)-ref%2; iTRp1 = 1 + delta_P*((scale_refframe+1)/2)-scale_refframe%2; bw_ref = 1; } } iTRd = frame_no_next_P - frame_no_B; iTRb = iTRp1 - iTRd; if(!img->picture_structure) { if (img->current_mb_nr_fld >= img->PicSizeInMbs) scale_refframe --; img->fw_refFrArr[img->block_y+j][img->block_x+i]=scale_refframe; // PLUS2, Krit, 7/06 (used to be + 1) img->bw_refFrArr[img->block_y+j][img->block_x+i]=bw_ref; } else { img->fw_refFrArr[img->block_y+j][img->block_x+i]=0; // PLUS2, Krit, 7/06 (used to be + 1) // by Junhao Zheng 2004-08-04 21:50:38 //img->bw_refFrArr[img->block_y+j][img->block_x+i]=1; img->bw_refFrArr[img->block_y+j][img->block_x+i]=0; } j4 = img->block_y+j; i4 = img->block_x+i; for (ii=0; ii < 2; ii++) { if(img->mv[img->block_x+i+4][img->block_y+j][ii] < 0) { img->fw_mv[i4+BLOCK_SIZE][j4][ii] = -(((16384/iTRp)*(1-iTRb*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14); img->bw_mv[i4+BLOCK_SIZE][j4][ii] = ((16384/iTRp)*(1-iTRd*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14; } else { img->fw_mv[i4+BLOCK_SIZE][j4][ii] = ((16384/iTRp)*(1+iTRb*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14; img->bw_mv[i4+BLOCK_SIZE][j4][ii] = -(((16384/iTRp)*(1+iTRd*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14); } } } } } img_block_y = img->block_y; i0+=max(1,step_h0); } j0+=max(1,step_v0); } //===== READ BACKWARD MOTION VECTORS ===== currSE.type = SE_MVD; currSE.mapping = linfo_se; img_block_y = img->block_y; for (j0=0; j0<2; ) { if(currMB->mb_type!=I4MB) { step_h0 = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][0]); step_v0 = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][1]); } if((currMB->mb_type==I4MB&&j0==0)) { j0 += 1; continue;} for (i0=0; i0<2; ) { k=2*j0+i0; if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && (currMB->b8mode[k]!=0))//has backward vector { mv_mode = currMB->b8mode[k]; step_h = BLOCK_STEP [mv_mode][0]; step_v = BLOCK_STEP [mv_mode][1]; refframe = img->bw_refFrArr[img->block_y+j0][img->block_x+i0]; // always 0 use_scaled_mv = 0; if(currMB->b8pdir[k]==2) { fw_refframe = img->fw_refFrArr[img->block_y+j0][img->block_x+i0]; current_tr = 2*img->tr_frm; if((current_tr >= img->imgtr_next_P) && (current_tr >= img->imgtr_last_P)) { use_scaled_mv = 1; mv_scale = ((refframe+1)*256)/(fw_refframe+1); } } for (j=j0; j block_y+j; i4 = img->block_x+i; // first make mv-prediction if(use_scaled_mv) { pmv[0] = (mv_scale*img->fw_mv[i4+BLOCK_SIZE][j4][0]+128)>>8; pmv[1] = (mv_scale*img->fw_mv[i4+BLOCK_SIZE][j4][1]+128)>>8; } else SetMotionVectorPredictor (img, pmv, pmv+1, refframe, img->bw_refFrArr, img->bw_mv, i, j, 8*step_h, 8*step_v, -1, 0);//Lou 1016 for (k=0; k < 2; k++) { #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "BMVD (pred %d)",pmv[k]); #endif img->subblock_x = i; // position used for context determination img->subblock_y = j; // position used for context determination currSE.value2 = 2*k+1; // identifies the component; only used for context determination if(currMB->b8pdir[2*j0+i0] == 2) { int delta_P,iTRp,DistanceIndexFw,DistanceIndexBw,refframe,delta_PB; refframe = fw_refframe; delta_P = 2*(img->imgtr_next_P - img->imgtr_last_P); if(img->picture_structure) iTRp = (refframe+1)*delta_P; //the lates backward reference else { iTRp = delta_P;//refframe == 0 ? delta_P-1 : delta_P+1; } delta_PB = 2*(img->tr - img->imgtr_last_P); if(!img->picture_structure) { if(img->current_mb_nr_fld < img->PicSizeInMbs) //top field DistanceIndexFw = refframe == 0 ? delta_PB-1:delta_PB; else DistanceIndexFw = refframe == 0 ? delta_PB:delta_PB+1; } else DistanceIndexFw = delta_PB; DistanceIndexBw = iTRp - DistanceIndexFw; curr_mvd = - ((img->fw_mv[i4+BLOCK_SIZE][j4][k]*DistanceIndexBw*(256/DistanceIndexFw)+128)>>8); vec=curr_mvd; /* find motion vector */ } else { readSyntaxElement_UVLC(&currSE,inp); curr_mvd = currSE.value1; vec=curr_mvd+pmv[k]; /* find motion vector */ } for(ii=0;ii bw_mv[i4+ii+BLOCK_SIZE][j4+jj][k]=vec; /* store (oversampled) mvd */ for (l=0; l < step_v; l++) for (m=0; m < step_h; m++) currMB->mvd[1][j+l][i+m][k] = curr_mvd; } } } i0+=max(1,step_h0); } j0+=max(1,step_v0); } } /* ************************************************************************* * Function:Get coded block pattern and coefficients (run/level) from the NAL * Input: * Output: * Return: * Attention: ************************************************************************* */ void readCBPandCoeffsFromNAL(struct img_par *img,struct inp_par *inp) { int i,j; int mb_nr = img->current_mb_nr; //GBimg->current_mb_nr; int m2,jg2; Macroblock *currMB = &mb_data[mb_nr]; int iii,jjj; int b8; int block_x,block_y; int qp_per = (img->qp-MIN_QP)/6; int qp_rem = (img->qp-MIN_QP)%6; int qp_per_uv = QP_SCALE_CR[img->qp-MIN_QP]/6; int qp_rem_uv = QP_SCALE_CR[img->qp-MIN_QP]%6; for (i=0;i cof[i][j][iii][jjj]=0;// reset luma coeffs qp_per = (img->qp-MIN_QP)/6; qp_rem = (img->qp-MIN_QP)%6; qp_per_uv = QP_SCALE_CR[img->qp-MIN_QP]/6; qp_rem_uv = QP_SCALE_CR[img->qp-MIN_QP]%6; currMB->qp = img->qp; // luma coefficients for (block_y=0; block_y < 4; block_y += 2) /* all modes */ { for (block_x=0; block_x < 4; block_x += 2) { b8 = 2*(block_y/2) + block_x/2; if (currMB->cbp&(1< cof[i][j][iii][jjj]=0; m2 =img->mb_x*2; jg2=img->mb_y*2; if ((currMB->cbp>>4)&1) { readChromaCoeff_B8(4, inp, img); } if ((currMB->cbp>>4)&2) { readChromaCoeff_B8(5, inp, img); } } /* ************************************************************************* * Function:decode one macroblock * Input: * Output: * Return: * Attention: ************************************************************************* */ int decode_one_macroblock(struct img_par *img,struct inp_par *inp) { unsigned char edgepixu[40]; #define EPU (edgepixu+20) unsigned char edgepixv[40]; #define EPV (edgepixv+20) int x,y,last_pix,new_pix; int bs_x=8; int bs_y=8; int tmp_block[8][8]; int tmp_blockbw[8][8]; int i=0,j=0,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0; int js0=0,js1=0,js2=0,js3=0,jf=0; int uv, hv; int vec1_x=0,vec1_y=0,vec2_x=0,vec2_y=0; int ioff,joff; int curr_blk[B8_SIZE][B8_SIZE]; //SW for AVS int tmp; int block8x8; // needed for ABT int bw_pred, fw_pred, ifx; int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0; int mv_mul,f1,f2,f3,f4; const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15}; Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; int refframe, fw_refframe, bw_refframe, mv_mode, pred_dir, intra_prediction; // = currMB->ref_frame; int fw_ref_idx, bw_ref_idx; int*** mv_array, ***fw_mv_array, ***bw_mv_array; int bframe = (img->type==B_IMG); int b8_s=0,b8_e=4,incr_y=1,off_y=0,even_y=4,add_y=0; int frame_no_next_P, frame_no_B, delta_P; int iTRb, iTRp,iTRd; int mb_nr = img->current_mb_nr;//GBimg->current_mb_nr; int mb_width = img->width/16; int mb_available_up; int mb_available_left; int fwd_refframe_offset,bwd_refframe_offset; int direct_pdir; int scale_refframe,iTRp1,bw_ref; // !! shenyanfei int fw_lum_scale , fw_lum_shift ; int bw_lum_scale , bw_lum_shift ; int structshift ; mb_available_up = (img->mb_y == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width].slice_nr); mb_available_left = (img->mb_x == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-1].slice_nr); // !! start shenyanfei if(img->structure){ structshift = 2 ; } else{ structshift = 1 ; } // !! end shenyanfei if(bframe) { int current_tr = 2*img->tr_frm; if(img->imgtr_next_P <= current_tr) fwd_refframe_offset = 0; else fwd_refframe_offset = 1; } else { fwd_refframe_offset = 0; } if (bframe) { bwd_refframe_offset = 0; } mv_mul=4; f1=8; f2=7; f3=f1*f1; f4=f3/2; // luma decoding ************************************************** for (block8x8=0; block8x8<4; block8x8++) { if (currMB->b8mode[block8x8] != IBLOCK) { i = block8x8%2; j = block8x8/2; ioff=i*8; i4=img->block_x+i; joff=j*8; j4=img->block_y+j; mv_mode = currMB->b8mode[block8x8]; pred_dir = currMB->b8pdir[block8x8]; if (pred_dir != 2) { //===== FORWARD/BACKWARD PREDICTION ===== if (!bframe) // !! P MB shenyanfei { refframe = refFrArr[j4][i4]; fw_ref_idx = refframe; mv_array = img->mv; } else if (!pred_dir) // !! B forward shenyanfei { refframe = img->fw_refFrArr[j4][i4];// fwd_ref_idx_to_refframe(img->fw_refFrArr[j4][i4]); fw_ref_idx = img->fw_refFrArr[j4][i4]; mv_array = img->fw_mv; } else // !! B backward shenyanfei { refframe = img->bw_refFrArr[j4][i4];// bwd_ref_idx_to_refframe(img->bw_refFrArr[j4][i4]); bw_ref_idx = img->bw_refFrArr[j4][i4]; bw_ref_idx = bw_ref_idx; mv_array = img->bw_mv; } if((progressive_sequence||progressive_frame)&&bframe&&img->picture_structure) refframe = 0; vec1_x = i4*8*mv_mul + mv_array[i4+BLOCK_SIZE][j4][0]; vec1_y = j4*8*mv_mul + mv_array[i4+BLOCK_SIZE][j4][1]; if(!bframe){ // !! for P MB shenyanfei get_block(refframe, vec1_x, vec1_y, img, tmp_block,mref[refframe]); if(((currMB->mb_type != 0)&&(img->picture_weighting_flag == 1) && (img->allframeweight == 0)&&(img->mbweightflag == 1)) ||((img->picture_weighting_flag == 1) && (img->allframeweight == 1))){ fw_lum_scale = img->lum_scale[refframe] ; fw_lum_shift = img->lum_shift[refframe] ; for(ii=0;ii<8;ii++){ for(jj=0;jj<8;jj++){ tmp_block[ii][jj] = ((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift; } } } } else // !! for B MB shenyanfei { if(!pred_dir){ // !! forward shenyanfei get_block (refframe, vec1_x, vec1_y, img, tmp_block,mref_fref[refframe]); if(((img->picture_weighting_flag == 1) && (img->allframeweight == 0)&&(img->mbweightflag == 1)) ||((img->picture_weighting_flag == 1) && (img->allframeweight == 1))){ fw_lum_scale = img->lum_scale[refframe+structshift] ; fw_lum_shift = img->lum_shift[refframe+structshift] ; for(ii=0;ii<8;ii++){ for(jj=0;jj<8;jj++){ tmp_block[ii][jj] = ((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift; } } } } else{ // !! backward shenyanfei get_block (refframe, vec1_x, vec1_y, img, tmp_block,mref_bref[refframe]); if(((img->picture_weighting_flag == 1) && (img->allframeweight == 0)&&(img->mbweightflag == 1)) ||((img->picture_weighting_flag == 1) && (img->allframeweight == 1))){ fw_lum_scale = img->lum_scale[refframe] ; fw_lum_shift = img->lum_shift[refframe] ; for(ii=0;ii<8;ii++){ for(jj=0;jj<8;jj++){ tmp_block[ii][jj] = ((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift; } } } } } for(ii=0;ii<8;ii++) for(jj=0;jj<8;jj++) img->mpr[ii+ioff][jj+joff] = tmp_block[ii][jj]; for(ii=0;ii<8;ii++) { for(jj=0;jj<8;jj++) { fprintf(luma_file,"%x", img->mpr[jj+ioff][ii+joff]); } fprintf(luma_file,"\n"); } } else // !! pred_dir == 2 { if (mv_mode != 0) { //===== BI-DIRECTIONAL PREDICTION ===== fw_mv_array = img->fw_mv; bw_mv_array = img->bw_mv; fw_refframe = img->fw_refFrArr[j4][i4];// fwd_ref_idx_to_refframe(img->fw_refFrArr[j4][i4]); bw_refframe = img->bw_refFrArr[j4][i4];// bwd_ref_idx_to_refframe(img->bw_refFrArr[j4][i4]); fw_ref_idx = img->fw_refFrArr[j4][i4]; bw_ref_idx = img->bw_refFrArr[j4][i4]; bw_ref_idx = bw_ref_idx; } else { //===== DIRECT PREDICTION ===== fw_mv_array = img->dfMV; bw_mv_array = img->dbMV; bw_refframe = 0; if(refFrArr[j4][i4] == -1) // next P is intra mode { for(hv=0; hv<2; hv++) { img->dfMV[i4+BLOCK_SIZE][j4][hv]=img->dbMV[i4+BLOCK_SIZE][j4][hv]=0; img->fw_mv[i4+BLOCK_SIZE][j4][hv]=img->bw_mv[i4+BLOCK_SIZE][j4][hv]=0; } //sw img->fw_refFrArr[j4][i4]=0; img->bw_refFrArr[j4][i4]=0; SetMotionVectorPredictor(img,&(img->fw_mv[i4+BLOCK_SIZE][j4][0]), &(img->fw_mv[i4+BLOCK_SIZE][j4][1]),0,img->fw_refFrArr, img->fw_mv,0,0,16,16, 0, 1); SetMotionVectorPredictor(img,&(img->bw_mv[i4+BLOCK_SIZE][j4][0]), &(img->bw_mv[i4+BLOCK_SIZE][j4][1]),0,img->bw_refFrArr, img->bw_mv,0,0,16,16, -1, 1); for(hv=0; hv<2; hv++) { img->dfMV[i4+BLOCK_SIZE][j4][hv]=img->fw_mv[i4+BLOCK_SIZE][j4][hv]; img->dbMV[i4+BLOCK_SIZE][j4][hv]=img->bw_mv[i4+BLOCK_SIZE][j4][hv]; } fw_refframe = 0; fw_ref_idx = 0; } else // next P is skip or inter mode { refframe = 0; fw_ref_idx = refframe; frame_no_next_P =2*img->imgtr_next_P; frame_no_B = 2*img->tr; delta_P = 2*(img->imgtr_next_P - img->imgtr_last_P); iTRp = (refframe+1)*delta_P; iTRb = iTRp - (frame_no_next_P - frame_no_B); if(!img->picture_structure) { if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field scale_refframe = refframe == 0 ? 0 : 1; else scale_refframe = refframe == 1 ? 1 : 2; } else scale_refframe = 0; if(img->picture_structure) { iTRp = (refframe+1)*delta_P; iTRp1 = (scale_refframe+1)*delta_P; }else { if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field { iTRp = delta_P*(refframe/2+1)-(refframe+1)%2; //the lates backward reference iTRp1 = delta_P*(scale_refframe/2+1)-(scale_refframe+1)%2; //the lates backward reference bw_ref = 0; } else { iTRp = 1 + delta_P*((refframe+1)/2)-refframe%2; iTRp1 = 1 + delta_P*((scale_refframe+1)/2)-scale_refframe%2; bw_ref = 1; } } iTRd = frame_no_next_P - frame_no_B; if(img->picture_structure) { iTRb = iTRp1 - (frame_no_next_P - frame_no_B); }else { iTRb = iTRp1 - (frame_no_next_P - frame_no_B); if (img->current_mb_nr_fld >= img->PicSizeInMbs) //top field scale_refframe --; } if(img->mv[i4+4][j4][0] < 0) { img->dfMV[i4+BLOCK_SIZE][j4][0] = -(((16384/iTRp)*(1-iTRb*img->mv[i4+4][j4][0])-1)>>14); img->dbMV[i4+BLOCK_SIZE][j4][0] = ((16384/iTRp)*(1-iTRd*img->mv[i4+4][j4][0])-1)>>14; } else { img->dfMV[i4+BLOCK_SIZE][j4][0] = ((16384/iTRp)*(1+iTRb*img->mv[i4+4][j4][0])-1)>>14; img->dbMV[i4+BLOCK_SIZE][j4][0] = -(((16384/iTRp)*(1+iTRd*img->mv[i4+4][j4][0])-1)>>14); } if(img->mv[i4+4][j4][1] < 0) { img->dfMV[i4+BLOCK_SIZE][j4][1] = -(((16384/iTRp)*(1-iTRb*img->mv[i4+4][j4][1])-1)>>14); img->dbMV[i4+BLOCK_SIZE][j4][1] = ((16384/iTRp)*(1-iTRd*img->mv[i4+4][j4][1])-1)>>14; } else { img->dfMV[i4+BLOCK_SIZE][j4][1] = ((16384/iTRp)*(1+iTRb*img->mv[i4+4][j4][1])-1)>>14; img->dbMV[i4+BLOCK_SIZE][j4][1] = -(((16384/iTRp)*(1+iTRd*img->mv[i4+4][j4][1])-1)>>14); } if(!img->picture_structure) { fw_refframe = scale_refframe; // DIRECT fw_ref_idx = max(0,scale_refframe); img->fw_refFrArr[j4][i4]=scale_refframe; } else { fw_refframe = 0; // DIRECT fw_ref_idx = max(0,refFrArr[j4][i4]); img->fw_refFrArr[j4][i4]=0; } img->fw_mv[i4+BLOCK_SIZE][j4][0]=img->dfMV[i4+BLOCK_SIZE][j4][0]; img->fw_mv[i4+BLOCK_SIZE][j4][1]=img->dfMV[i4+BLOCK_SIZE][j4][1]; img->bw_mv[i4+BLOCK_SIZE][j4][0]=img->dbMV[i4+BLOCK_SIZE][j4][0]; img->bw_mv[i4+BLOCK_SIZE][j4][1]=img->dbMV[i4+BLOCK_SIZE][j4][1]; if(img->picture_structure) img->bw_refFrArr[j4][i4]=0; else bw_refframe = img->bw_refFrArr[j4][i4]=bw_ref; } } //if ((progressive_sequence||progressive_frame)&&img->picture_structure) vec1_x = i4*8*mv_mul + fw_mv_array[i4+BLOCK_SIZE][j4][0]; vec1_y = j4*8*mv_mul + fw_mv_array[i4+BLOCK_SIZE][j4][1]; vec2_x = i4*8*mv_mul + bw_mv_array[i4+BLOCK_SIZE][j4][0]; vec2_y = j4*8*mv_mul + bw_mv_array[i4+BLOCK_SIZE][j4][1]; // !! bidirection prediction shenyanfei get_block (fw_refframe, vec1_x, vec1_y, img, tmp_block,mref_fref[fw_refframe]); get_block (bw_refframe, vec2_x, vec2_y, img, tmp_blockbw,mref_bref[bw_refframe]); if(((img->picture_weighting_flag == 1) && (img->allframeweight == 0)&&(img->mbweightflag == 1)&&(mv_mode !=0 )) ||((img->picture_weighting_flag == 1) && (img->allframeweight == 1))){ fw_lum_scale = img->lum_scale[fw_refframe+structshift] ; fw_lum_shift = img->lum_shift[fw_refframe+structshift] ; for(ii=0;ii<8;ii++){ for(jj=0;jj<8;jj++){ tmp_block[ii][jj] = ((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift; } } bw_lum_scale = img->lum_scale[bw_refframe] ; bw_lum_shift = img->lum_shift[bw_refframe] ; for(ii=0;ii<8;ii++){ for(jj=0;jj<8;jj++){ tmp_blockbw[ii][jj] = ((tmp_blockbw[ii][jj]*bw_lum_scale+16)>>5) + bw_lum_shift; } } } for(ii=0;ii<8;ii++) for(jj=0;jj<8;jj++) img->mpr[ii+ioff][jj+joff] = (tmp_block[ii][jj]+tmp_blockbw[ii][jj]+1)/2; for(ii=0;ii<8;ii++) { for(jj=0;jj<8;jj++) { fprintf(luma_file,"%x", img->mpr[jj+ioff][ii+joff]); } fprintf(luma_file,"\n"); } } } get_curr_blk (block8x8, img, curr_blk); if (currMB->b8mode[block8x8]!=IBLOCK)//((IS_INTER (currMB) && mv_mode!=IBLOCK)) { idct_dequant_B8 (block8x8, currMB->qp-MIN_QP, curr_blk, img); } else { //intrapred creates the intraprediction in the array img->mpr[x][y] at the location corresponding to the position within the 16x16 MB. tmp = intrapred( img, (img->mb_x<<4)+((block8x8&1)<<3), (img->mb_y<<4)+((block8x8&2)<<2)); if ( tmp == SEARCH_SYNC) /* make 4x4 prediction block mpr from given prediction img->mb_mode */ return SEARCH_SYNC; /* bit error */ idct_dequant_B8 (block8x8, currMB->qp-MIN_QP, curr_blk, img); } } // chroma decoding ******************************************************* for(uv=0;uv<2;uv++) { intra_prediction = IS_INTRA (currMB); if (intra_prediction) { if (uv==0) { if(mb_available_up) { for(x=0;x pix_c_y-1][img->pix_c_x+x]; for(x=0;x pix_c_y-1][img->pix_c_x]; } if(mb_available_left) { for(y=0;y pix_c_y+y][img->pix_c_x-1]; for(y=0;y pix_c_y][img->pix_c_x-1]; } if(mb_available_up&&mb_available_left) EPU[0]=imgUV[uv][img->pix_c_y-1][img->pix_c_x-1]; //lowpass (Those emlements that are not needed will not disturb) last_pix=EPU[-8]; for(i=-8;i<=8;i++) { new_pix=( last_pix + (EPU[i]<<1) + EPU[i+1] + 2 )>>2; last_pix=EPU[i]; EPU[i]=(unsigned char)new_pix; } } if (uv==1) { if(mb_available_up) { for(x=0;x pix_c_y-1][img->pix_c_x+x]; for(x=0;x pix_c_y-1][img->pix_c_x]; } if(mb_available_left) { for(y=0;y pix_c_y+y][img->pix_c_x-1]; for(y=0;y pix_c_y][img->pix_c_x-1]; } if(mb_available_up&&mb_available_left) EPV[0]=imgUV[uv][img->pix_c_y-1][img->pix_c_x-1]; //lowpass (Those emlements that are not needed will not disturb) last_pix=EPV[-8]; for(i=-8;i<=8;i++) { new_pix=( last_pix + (EPV[i]<<1) + EPV[i+1] + 2 )>>2; last_pix=EPV[i]; EPV[i]=(unsigned char)new_pix; } } } for (j=4;j<6;j++) { joff=(j-4)*4; j4=img->pix_c_y+joff; for(i=0;i<2;i++) { ioff=i*4; i4=img->pix_c_x+ioff; mv_mode = currMB->b8mode[2*(j-4)+i]; pred_dir = currMB->b8pdir[2*(j-4)+i]; // PREDICTION if (currMB->mb_type==I4MB) { //--- INTRA PREDICTION --- int pred; int ih, iv, ib, ic, iaa; switch (currMB->c_ipred_mode) { case DC_PRED_8: if (uv==0) { if (!mb_available_up && !mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=128; } if (mb_available_up && !mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=EPU[1+ii+ioff]; } if (!mb_available_up && mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=EPU[-1-jj-joff]; } if (mb_available_up && mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=(EPU[1+ii+ioff]+EPU[-1-jj-joff])>>1; } } if (uv==1) { if (!mb_available_up && !mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=128; } if (mb_available_up && !mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=EPV[1+ii+ioff]; } if (!mb_available_up && mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=EPV[-1-jj-joff]; } if (mb_available_up && mb_available_left) for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) { img->mpr[ii+ioff][jj+joff]=(EPV[1+ii+ioff]+EPV[-1-jj-joff])>>1; } } break; case HOR_PRED_8: if (!mb_available_left) error("unexpected HOR_PRED_8 chroma intra prediction mode",-1); for (jj=0; jj<4; jj++) { pred = imgUV[uv][img->pix_c_y+jj+joff][img->pix_c_x-1]; for (ii=0; ii<4; ii++) img->mpr[ii+ioff][jj+joff]=pred; } break; case VERT_PRED_8: if (!mb_available_up) error("unexpected VERT_PRED_8 chroma intra prediction mode",-1); for (ii=0; ii<4; ii++) { pred = imgUV[uv][img->pix_c_y-1][img->pix_c_x+ii+ioff]; for (jj=0; jj<4; jj++) img->mpr[ii+ioff][jj+joff]=pred; } break; case PLANE_8: if (!mb_available_left || !mb_available_up) error("unexpected PLANE_8 chroma intra prediction mode",-1); ih=iv=0; for (ii=1;ii<5;ii++) { ih += ii*(imgUV[uv][img->pix_c_y-1][img->pix_c_x+3+ii] - imgUV[uv][img->pix_c_y-1][img->pix_c_x+3-ii]); iv += ii*(imgUV[uv][img->pix_c_y+3+ii][img->pix_c_x-1] - imgUV[uv][img->pix_c_y+3-ii][img->pix_c_x-1]); } ib=(17*ih+16)>>5; ic=(17*iv+16)>>5; iaa=16*(imgUV[uv][img->pix_c_y-1][img->pix_c_x+7]+imgUV[uv][img->pix_c_y+7][img->pix_c_x-1]); for (ii=0; ii<4; ii++) for (jj=0; jj<4; jj++) img->mpr[ii+ioff][jj+joff]=max(0,min(255,(iaa+(ii+ioff-3)*ib +(jj+joff-3)*ic + 16)/32)); break; default: error("illegal chroma intra prediction mode", 600); break; } } else if (pred_dir != 2) { //--- FORWARD/BACKWARD PREDICTION --- if (!bframe) { mv_array = img->mv; } else if (!pred_dir) { mv_array = img->fw_mv; } else { mv_array = img->bw_mv; } for(jj=0;jj<4;jj++) { jf=(j4+jj)/4; for(ii=0;ii<4;ii++) { if1=(i4+ii)/4; if (!bframe) { refframe = refFrArr[jf][if1]; fw_ref_idx = refFrArr[jf][if1]; } else if (!pred_dir) { refframe = img->fw_refFrArr[jf][if1];// fwd_ref_idx_to_refframe(img->fw_refFrArr[jf][if1]); fw_ref_idx = img->fw_refFrArr[jf][if1]; } else { refframe = img->bw_refFrArr[jf][if1];// bwd_ref_idx_to_refframe(img->bw_refFrArr[jf][if1]); bw_ref_idx = img->bw_refFrArr[jf][if1]; bw_ref_idx = bw_ref_idx; } i1=(img->pix_c_x+ii+ioff)*f1+mv_array[if1+4][jf][0]; j1=(img->pix_c_y+jj+joff)*f1+mv_array[if1+4][jf][1]; ii0=max (0, min (i1/f1, img->width_cr-1)); jj0=max (0, min (j1/f1, img->height_cr-1)); ii1=max (0, min ((i1+f2)/f1, img->width_cr-1)); jj1=max (0, min ((j1+f2)/f1, img->height_cr-1)); if1=(i1 & f2); jf1=(j1 & f2); if0=f1-if1; jf0=f1-jf1; if(!bframe) { img->mpr[ii+ioff][jj+joff]=(if0*jf0*mcef[refframe][uv][jj0][ii0]+ if1*jf0*mcef[refframe][uv][jj0][ii1]+ if0*jf1*mcef[refframe][uv][jj1][ii0]+ if1*jf1*mcef[refframe][uv][jj1][ii1]+f4)/f3; } else { if(img->picture_structure) refframe = 0; if(!pred_dir) img->mpr[ii+ioff][jj+joff]=(if0*jf0*mcef_fref[refframe][uv][jj0][ii0]+ if1*jf0*mcef_fref[refframe][uv][jj0][ii1]+ if0*jf1*mcef_fref[refframe][uv][jj1][ii0]+ if1*jf1*mcef_fref[refframe][uv][jj1][ii1]+f4)/f3; else img->mpr[ii+ioff][jj+joff]=(if0*jf0*mcef_bref[refframe][uv][jj0][ii0]+ if1*jf0*mcef_bref[refframe][uv][jj0][ii1]+ if0*jf1*mcef_bref[refframe][uv][jj1][ii0]+ if1*jf1*mcef_bref[refframe][uv][jj1][ii1]+f4)/f3; } } } } else // !! bidirection prediction { if (mv_mode != 0) { //===== BI-DIRECTIONAL PREDICTION ===== fw_mv_array = img->fw_mv; bw_mv_array = img->bw_mv; } else { //===== DIRECT PREDICTION ===== fw_mv_array = img->dfMV; bw_mv_array = img->dbMV; } for(jj=0;jj<4;jj++) { jf=(j4+jj)/4; for(ii=0;ii<4;ii++) { ifx=(i4+ii)/4; direct_pdir = 2; if (mv_mode != 0) { fw_refframe = img->fw_refFrArr[jf][ifx];// fwd_ref_idx_to_refframe(img->fw_refFrArr[jf][ifx]); bw_refframe = img->bw_refFrArr[jf][ifx];//bwd_ref_idx_to_refframe(img->bw_refFrArr[jf][ifx]); fw_ref_idx = img->fw_refFrArr[jf][ifx]; bw_ref_idx = img->bw_refFrArr[jf][ifx]; bw_ref_idx = bw_ref_idx; } else { fw_refframe = 0; bw_refframe = 0; if(!img->picture_structure) { fw_refframe = img->fw_refFrArr[jf][ifx]; bw_refframe = img->bw_refFrArr[jf][ifx]; } } i1=(img->pix_c_x+ii+ioff)*f1+fw_mv_array[ifx+4][jf][0]; j1=(img->pix_c_y+jj+joff)*f1+fw_mv_array[ifx+4][jf][1]; ii0=max (0, min (i1/f1, img->width_cr-1)); jj0=max (0, min (j1/f1, img->height_cr-1)); ii1=max (0, min ((i1+f2)/f1, img->width_cr-1)); jj1=max (0, min ((j1+f2)/f1, img->height_cr-1)); if1=(i1 & f2); jf1=(j1 & f2); if0=f1-if1; jf0=f1-jf1; fw_pred=(if0*jf0*mcef_fref[fw_refframe][uv][jj0][ii0]+ if1*jf0*mcef_fref[fw_refframe][uv][jj0][ii1]+ if0*jf1*mcef_fref[fw_refframe][uv][jj1][ii0]+ if1*jf1*mcef_fref[fw_refframe][uv][jj1][ii1]+f4)/f3; i1=(img->pix_c_x+ii+ioff)*f1+bw_mv_array[ifx+4][jf][0]; j1=(img->pix_c_y+jj+joff)*f1+bw_mv_array[ifx+4][jf][1]; ii0=max (0, min (i1/f1, img->width_cr-1)); jj0=max (0, min (j1/f1, img->height_cr-1)); ii1=max (0, min ((i1+f2)/f1, img->width_cr-1)); jj1=max (0, min ((j1+f2)/f1, img->height_cr-1)); if1=(i1 & f2); jf1=(j1 & f2); if0=f1-if1; jf0=f1-jf1; bw_pred=(if0*jf0*mcef_bref[bw_refframe][uv][jj0][ii0]+ if1*jf0*mcef_bref[bw_refframe][uv][jj0][ii1]+ if0*jf1*mcef_bref[bw_refframe][uv][jj1][ii0]+ if1*jf1*mcef_bref[bw_refframe][uv][jj1][ii1]+f4)/f3; img->mpr[ii+ioff][jj+joff]=(fw_pred + bw_pred + 1 )/2; //qp-MIN_QP], curr_blk, img); } return 0; }