URL
https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk
Subversion Repositories bluespec-h264
[/] [bluespec-h264/] [trunk/] [test/] [decoder/] [ldecod/] [src/] [macroblock.c] - Rev 100
Compare with Previous | Blame | View Log
/*! *********************************************************************** * \file macroblock.c * * \brief * Decode a Macroblock * * \author * Main contributors (see contributors.h for copyright, address and affiliation details) * - Inge Lille-Langøy <inge.lille-langoy@telenor.com> * - Rickard Sjoberg <rickard.sjoberg@era.ericsson.se> * - Jani Lainema <jani.lainema@nokia.com> * - Sebastian Purreiter <sebastian.purreiter@mch.siemens.de> * - Thomas Wedi <wedi@tnt.uni-hannover.de> * - Detlev Marpe <marpe@hhi.de> * - Gabi Blaettermann <blaetter@hhi.de> * - Ye-Kui Wang <wyk@ieee.org> * - Lowell Winger <lwinger@lsil.com> *********************************************************************** */ #include "contributors.h" #include <math.h> #include <stdlib.h> #include <assert.h> #include <string.h> #include "global.h" #include "mbuffer.h" #include "elements.h" #include "errorconcealment.h" #include "macroblock.h" #include "fmo.h" #include "cabac.h" #include "vlc.h" #include "image.h" #include "mb_access.h" #include "biaridecod.h" #include "transform8x8.h" #if TRACE #define TRACE_STRING(s) strncpy(currSE.tracestring, s, TRACESTRING_SIZE) #else #define TRACE_STRING(s) // do nothing #endif extern int last_dquant; extern ColocatedParams *Co_located; static void SetMotionVectorPredictor (struct img_par *img, short pmv[2], char ref_frame, byte list, char ***refPic, short ****tmp_mv, int block_x, int block_y, int blockshape_x, int blockshape_y); /*! ************************************************************************ * \brief * initializes the current macroblock ************************************************************************ */ void start_macroblock(struct img_par *img,int CurrentMBInScanOrder) { int l,j; Macroblock *currMB; // intialization code deleted, see below, StW assert (img->current_mb_nr < img->PicSizeInMbs); currMB = &img->mb_data[img->current_mb_nr]; /* Update coordinates of the current macroblock */ if (img->MbaffFrameFlag) { img->mb_x = (img->current_mb_nr)%((2*img->width)/MB_BLOCK_SIZE); img->mb_y = 2*((img->current_mb_nr)/((2*img->width)/MB_BLOCK_SIZE)); if (img->mb_x & 0x01) { img->mb_y++; } img->mb_x /= 2; } else { img->mb_x = PicPos[img->current_mb_nr][0]; img->mb_y = PicPos[img->current_mb_nr][1]; } /* Define vertical positions */ img->block_y = img->mb_y * BLOCK_SIZE; /* luma block position */ img->pix_y = img->mb_y * MB_BLOCK_SIZE; /* luma macroblock position */ img->pix_c_y = img->mb_y * img->mb_cr_size_y; /* chroma macroblock position */ /* Define horizontal positions */ img->block_x = img->mb_x * BLOCK_SIZE; /* luma block position */ img->pix_x = img->mb_x * MB_BLOCK_SIZE; /* luma pixel position */ img->pix_c_x = img->mb_x * img->mb_cr_size_x; /* chroma pixel position */ // Save the slice number of this macroblock. When the macroblock below // is coded it will use this to decide if prediction for above is possible currMB->slice_nr = img->current_slice_nr; if (img->current_slice_nr >= MAX_NUM_SLICES) { error ("maximum number of supported slices exceeded, please recompile with increased value for MAX_NUM_SLICES", 200); } dec_picture->slice_id[img->mb_y][img->mb_x] = img->current_slice_nr; if (img->current_slice_nr > dec_picture->max_slice_id) { dec_picture->max_slice_id=img->current_slice_nr; } CheckAvailabilityOfNeighbors(); // 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++) memset(&(currMB->mvd[l][j][0][0]),0, BLOCK_MULTIPLE * 2 * sizeof(int)); currMB->cbp_bits = 0; // initialize img->m7 memset(&(img->m7[0][0]), 0, MB_BLOCK_PIXELS * sizeof(int)); // store filtering parameters for this MB currMB->LFDisableIdc = img->currentSlice->LFDisableIdc; currMB->LFAlphaC0Offset = img->currentSlice->LFAlphaC0Offset; currMB->LFBetaOffset = img->currentSlice->LFBetaOffset; } /*! ************************************************************************ * \brief * set coordinates of the next macroblock * check end_of_slice condition ************************************************************************ */ Boolean exit_macroblock(struct img_par *img,struct inp_par *inp,int eos_bit) { //! The if() statement below resembles the original code, which tested //! img->current_mb_nr == img->PicSizeInMbs. Both is, of course, nonsense //! In an error prone environment, one can only be sure to have a new //! picture by checking the tr of the next slice header! // printf ("exit_macroblock: FmoGetLastMBOfPicture %d, img->current_mb_nr %d\n", FmoGetLastMBOfPicture(), img->current_mb_nr); img->num_dec_mb++; if (img->num_dec_mb == img->PicSizeInMbs) // if (img->current_mb_nr == FmoGetLastMBOfPicture(currSlice->structure)) { //thb /* if (currSlice->next_header != EOS) currSlice->next_header = SOP; */ //the // assert (nal_startcode_follows (img, eos_bit) == TRUE); return TRUE; } // ask for last mb in the slice UVLC else { // printf ("exit_macroblock: Slice %d old MB %d, now using MB %d\n", img->current_slice_nr, img->current_mb_nr, FmoGetNextMBNr (img->current_mb_nr)); img->current_mb_nr = FmoGetNextMBNr (img->current_mb_nr); if (img->current_mb_nr == -1) // End of Slice group, MUST be end of slice { assert (nal_startcode_follows (img, eos_bit) == TRUE); return TRUE; } if(nal_startcode_follows(img, eos_bit) == FALSE) return FALSE; if(img->type == I_SLICE || img->type == SI_SLICE || active_pps->entropy_coding_mode_flag == CABAC) return TRUE; if(img->cod_counter<=0) return TRUE; return FALSE; } } /*! ************************************************************************ * \brief * Interpret the mb mode for P-Frames ************************************************************************ */ void interpret_mb_mode_P(struct img_par *img) { const int ICBPTAB[6] = {0,16,32,15,31,47}; Macroblock *currMB = &img->mb_data[img->current_mb_nr]; int mbmode = currMB->mb_type; #define ZERO_P8x8 (mbmode==5) #define MODE_IS_P8x8 (mbmode==4 || mbmode==5) #define MODE_IS_I4x4 (mbmode==6) #define I16OFFSET (mbmode-7) #define MODE_IS_IPCM (mbmode==31) if(mbmode <4) { currMB->mb_type = mbmode; memset(&currMB->b8mode[0],mbmode,4 * sizeof(char)); memset(&currMB->b8pdir[0],0,4 * sizeof(char)); } else if(MODE_IS_P8x8) { currMB->mb_type = P8x8; img->allrefzero = ZERO_P8x8; } else if(MODE_IS_I4x4) { currMB->mb_type = I4MB; memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else if(MODE_IS_IPCM) { currMB->mb_type=IPCM; currMB->cbp= -1; currMB->i16mode = 0; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else { currMB->mb_type = I16MB; currMB->cbp= ICBPTAB[(I16OFFSET)>>2]; currMB->i16mode = (I16OFFSET) & 0x03; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } } /*! ************************************************************************ * \brief * Interpret the mb mode for I-Frames ************************************************************************ */ void interpret_mb_mode_I(struct img_par *img) { const int ICBPTAB[6] = {0,16,32,15,31,47}; Macroblock *currMB = &img->mb_data[img->current_mb_nr]; int mbmode = currMB->mb_type; if (mbmode==0) { currMB->mb_type = I4MB; memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else if(mbmode==25) { currMB->mb_type=IPCM; currMB->cbp= -1; currMB->i16mode = 0; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else { currMB->mb_type = I16MB; currMB->cbp= ICBPTAB[(mbmode-1)>>2]; currMB->i16mode = (mbmode-1) & 0x03; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } } /*! ************************************************************************ * \brief * Interpret the mb mode for B-Frames ************************************************************************ */ 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 = &img->mb_data[img->current_mb_nr]; int i, mbmode; int mbtype = currMB->mb_type; //--- set mbtype, b8type, and b8pdir --- if (mbtype==0) // direct { mbmode=0; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],2,4 * sizeof(char)); } else if (mbtype==23) // intra4x4 { mbmode=I4MB; memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else if ((mbtype>23) && (mbtype<48) ) // intra16x16 { mbmode=I16MB; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); currMB->cbp = ICBPTAB[(mbtype-24)>>2]; currMB->i16mode = (mbtype-24) & 0x03; } else if (mbtype==22) // 8x8(+split) { mbmode=P8x8; // b8mode and pdir is transmitted in additional codewords } else if (mbtype<4) // 16x16 { mbmode=1; memset(&currMB->b8mode[0], 1,4 * sizeof(char)); memset(&currMB->b8pdir[0],offset2pdir16x16[mbtype],4 * sizeof(char)); } else if(mbtype==48) { mbmode=IPCM; memset(&currMB->b8mode[0], 0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); currMB->cbp= -1; currMB->i16mode = 0; } else if ((mbtype&0x01)==0) // 16x8 { mbmode=2; memset(&currMB->b8mode[0], 2,4 * sizeof(char)); for(i=0;i<4;i++) { currMB->b8pdir[i]=offset2pdir16x8 [mbtype][i>>1]; } } else { mbmode=3; memset(&currMB->b8mode[0], 3,4 * sizeof(char)); for(i=0;i<4;i++) { currMB->b8pdir[i]=offset2pdir8x16 [mbtype][i&0x01]; } } currMB->mb_type = mbmode; } /*! ************************************************************************ * \brief * Interpret the mb mode for SI-Frames ************************************************************************ */ void interpret_mb_mode_SI(struct img_par *img) { const int ICBPTAB[6] = {0,16,32,15,31,47}; Macroblock *currMB = &img->mb_data[img->current_mb_nr]; int mbmode = currMB->mb_type; if (mbmode==0) { currMB->mb_type = SI4MB; memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); img->siblock[img->mb_y][img->mb_x]=1; } else if (mbmode==1) { currMB->mb_type = I4MB; memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else if(mbmode==26) { currMB->mb_type=IPCM; currMB->cbp= -1; currMB->i16mode = 0; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } else { currMB->mb_type = I16MB; currMB->cbp= ICBPTAB[(mbmode-1)>>2]; currMB->i16mode = (mbmode-2) & 0x03; memset(&currMB->b8mode[0],0,4 * sizeof(char)); memset(&currMB->b8pdir[0],-1,4 * sizeof(char)); } } /*! ************************************************************************ * \brief * init macroblock I and P frames ************************************************************************ */ void init_macroblock(struct img_par *img) { int i,j; for(j=img->block_y;j<img->block_y+BLOCK_SIZE;j++) { // reset vectors and pred. modes memset(&dec_picture->mv[LIST_0][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short)); memset(&dec_picture->mv[LIST_1][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short)); memset(&dec_picture->ref_idx[LIST_0][j][img->block_x], -1, BLOCK_SIZE * sizeof(char)); memset(&dec_picture->ref_idx[LIST_1][j][img->block_x], -1, BLOCK_SIZE * sizeof(char)); memset(&img->ipredmode[j][img->block_x], DC_PRED, BLOCK_SIZE * sizeof(char)); for (i=img->block_x;i<img->block_x+BLOCK_SIZE;i++) { dec_picture->ref_pic_id[LIST_0][j][i] = INT64_MIN; dec_picture->ref_pic_id[LIST_1][j][i] = INT64_MIN; } } } /*! ************************************************************************ * \brief * Sets mode for 8x8 block ************************************************************************ */ 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_SLICE) { 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]; } } void reset_coeffs() { int i, j; // reset all coeffs for (i=0;i<BLOCK_SIZE;i++) { for (j=0;j<BLOCK_SIZE +img->num_blk8x8_uv;j++) memset(&img->cof[i][j][0][0],0,BLOCK_SIZE * BLOCK_SIZE * sizeof(int)); } // CAVLC memset(&img->nz_coeff[img->current_mb_nr][0][0],0, BLOCK_SIZE * (BLOCK_SIZE + img->num_blk8x8_uv) * sizeof(int)); } void field_flag_inference() { Macroblock *currMB = &img->mb_data[img->current_mb_nr]; if (currMB->mbAvailA) { currMB->mb_field = img->mb_data[currMB->mbAddrA].mb_field; } else { // check top macroblock pair if (currMB->mbAvailB) { currMB->mb_field = img->mb_data[currMB->mbAddrB].mb_field; } else currMB->mb_field = 0; } } void set_chroma_qp(Macroblock* currMB) { int i; for (i=0; i<2; i++) { currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + dec_picture->chroma_qp_offset[i] ); currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]]; } } /*! ************************************************************************ * \brief * Get the syntax elements from the NAL ************************************************************************ */ int read_one_macroblock(struct img_par *img,struct inp_par *inp) { int i; SyntaxElement currSE; Macroblock *currMB = &img->mb_data[img->current_mb_nr]; Slice *currSlice = img->currentSlice; DataPartition *dP; int *partMap = assignSE2partition[currSlice->dp_mode]; Macroblock *topMB = NULL; int prevMbSkipped = 0; int img_block_y; int check_bottom, read_bottom, read_top; if (img->MbaffFrameFlag) { if (img->current_mb_nr&0x01) { topMB= &img->mb_data[img->current_mb_nr-1]; if(!(img->type == B_SLICE)) prevMbSkipped = (topMB->mb_type == 0); else prevMbSkipped = topMB->skip_flag; } else prevMbSkipped = 0; } if ((img->current_mb_nr&0x01) == 0) currMB->mb_field = 0; else currMB->mb_field = img->mb_data[img->current_mb_nr-1].mb_field; currMB->qp = img->qp ; for (i=0; i<2; i++) { currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, img->qp + dec_picture->chroma_qp_offset[i] ); currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]]; } currSE.type = SE_MBTYPE; // read MB mode ***************************************************************** dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue; if(img->type == I_SLICE || img->type == SI_SLICE) { // read MB aff if (img->MbaffFrameFlag && (img->current_mb_nr&0x01)==0) { TRACE_STRING("mb_field_decoding_flag"); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); } else { currSE.reading = readFieldModeInfo_CABAC; dP->readSyntaxElement(&currSE,img,dP); } currMB->mb_field = currSE.value1; } if(active_pps->entropy_coding_mode_flag == CABAC) CheckAvailabilityOfNeighborsCABAC(); // read MB type TRACE_STRING("mb_type"); currSE.reading = readMB_typeInfo_CABAC; dP->readSyntaxElement(&currSE,img,dP); currMB->mb_type = currSE.value1; if(!dP->bitstream->ei_flag) currMB->ei_flag = 0; } // non I/SI-slice CABAC else if (active_pps->entropy_coding_mode_flag == CABAC) { // read MB skip_flag if (img->MbaffFrameFlag && ((img->current_mb_nr&0x01) == 0||prevMbSkipped)) field_flag_inference(); CheckAvailabilityOfNeighborsCABAC(); TRACE_STRING("mb_skip_flag"); currSE.reading = readMB_skip_flagInfo_CABAC; dP->readSyntaxElement(&currSE,img,dP); currMB->mb_type = currSE.value1; currMB->skip_flag = !(currSE.value1); if (img->type==B_SLICE) currMB->cbp = currSE.value2; if(!dP->bitstream->ei_flag) currMB->ei_flag = 0; if ((img->type==B_SLICE) && currSE.value1==0 && currSE.value2==0) img->cod_counter=0; // read MB AFF if (img->MbaffFrameFlag) { check_bottom=read_bottom=read_top=0; if ((img->current_mb_nr&0x01)==0) { check_bottom = currMB->skip_flag; read_top = !check_bottom; } else { read_bottom = (topMB->skip_flag && (!currMB->skip_flag)); } if (read_bottom || read_top) { TRACE_STRING("mb_field_decoding_flag"); currSE.reading = readFieldModeInfo_CABAC; dP->readSyntaxElement(&currSE,img,dP); currMB->mb_field = currSE.value1; } if (check_bottom) check_next_mb_and_get_field_mode_CABAC(&currSE,img,dP); } CheckAvailabilityOfNeighborsCABAC(); // read MB type if (currMB->mb_type != 0 ) { currSE.reading = readMB_typeInfo_CABAC; TRACE_STRING("mb_type"); dP->readSyntaxElement(&currSE,img,dP); currMB->mb_type = currSE.value1; if(!dP->bitstream->ei_flag) currMB->ei_flag = 0; } } // VLC Non-Intra else { if(img->cod_counter == -1) { TRACE_STRING("mb_skip_run"); dP->readSyntaxElement(&currSE,img,dP); img->cod_counter = currSE.value1; } if (img->cod_counter==0) { // read MB aff if ((img->MbaffFrameFlag) && (((img->current_mb_nr&0x01)==0) || ((img->current_mb_nr&0x01) && prevMbSkipped))) { TRACE_STRING("mb_field_decoding_flag"); currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); currMB->mb_field = currSE.value1; } // read MB type TRACE_STRING("mb_type"); dP->readSyntaxElement(&currSE,img,dP); if(img->type == P_SLICE || img->type == SP_SLICE) currSE.value1++; currMB->mb_type = currSE.value1; if(!dP->bitstream->ei_flag) currMB->ei_flag = 0; img->cod_counter--; currMB->skip_flag = 0; } else { img->cod_counter--; currMB->mb_type = 0; currMB->ei_flag = 0; currMB->skip_flag = 1; // read field flag of bottom block if(img->MbaffFrameFlag) { if(img->cod_counter == 0 && ((img->current_mb_nr&0x01) == 0)) { TRACE_STRING("mb_field_decoding_flag (of coded bottom mb)"); currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); dP->bitstream->frame_bitoffset--; currMB->mb_field = currSE.value1; } else if(img->cod_counter > 0 && ((img->current_mb_nr&0x01) == 0)) { // check left macroblock pair first if (mb_is_available(img->current_mb_nr-2, img->current_mb_nr)&&((img->current_mb_nr%(img->PicWidthInMbs*2))!=0)) { currMB->mb_field = img->mb_data[img->current_mb_nr-2].mb_field; } else { // check top macroblock pair if (mb_is_available(img->current_mb_nr-2*img->PicWidthInMbs, img->current_mb_nr)) { currMB->mb_field = img->mb_data[img->current_mb_nr-2*img->PicWidthInMbs].mb_field; } else currMB->mb_field = 0; } } } } } dec_picture->mb_field[img->current_mb_nr] = currMB->mb_field; img->siblock[img->mb_y][img->mb_x]=0; if ((img->type==P_SLICE )) // inter frame interpret_mb_mode_P(img); else if (img->type==I_SLICE) // intra frame interpret_mb_mode_I(img); else if ((img->type==B_SLICE)) // B frame interpret_mb_mode_B(img); else if ((img->type==SP_SLICE)) // SP frame interpret_mb_mode_P(img); else if (img->type==SI_SLICE) // SI frame interpret_mb_mode_SI(img); if(img->MbaffFrameFlag) { if(currMB->mb_field) { img->num_ref_idx_l0_active <<=1; img->num_ref_idx_l1_active <<=1; } } //init NoMbPartLessThan8x8Flag currMB->NoMbPartLessThan8x8Flag = (IS_DIRECT(currMB) && !(active_sps->direct_8x8_inference_flag))? 0: 1; //====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ====== if (IS_P8x8 (currMB)) { currSE.type = SE_MBTYPE; dP = &(currSlice->partArr[partMap[SE_MBTYPE]]); for (i=0; i<4; i++) { if (active_pps->entropy_coding_mode_flag ==UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue; else currSE.reading = readB8_typeInfo_CABAC; TRACE_STRING("sub_mb_type"); dP->readSyntaxElement (&currSE, img, dP); SetB8Mode (img, currMB, currSE.value1, i); //set NoMbPartLessThan8x8Flag for P8x8 mode currMB->NoMbPartLessThan8x8Flag &= (currMB->b8mode[i]==0 && active_sps->direct_8x8_inference_flag) || (currMB->b8mode[i]==4); } //--- init macroblock data --- init_macroblock (img); readMotionInfoFromNAL (img, inp); } //============= Transform Size Flag for INTRA MBs ============= //------------------------------------------------------------- //transform size flag for INTRA_4x4 and INTRA_8x8 modes if (currMB->mb_type == I4MB && img->Transform8x8Mode) { currSE.type = SE_HEADER; dP = &(currSlice->partArr[partMap[SE_HEADER]]); currSE.reading = readMB_transform_size_flag_CABAC; TRACE_STRING("transform_size_8x8_flag"); // read UVLC transform_size_8x8_flag if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); } else { dP->readSyntaxElement(&currSE,img,dP); } currMB->luma_transform_size_8x8_flag = currSE.value1; if (currMB->luma_transform_size_8x8_flag) { currMB->mb_type = I8MB; for (i=0;i<4;i++) { currMB->b8mode[i]=I8MB; currMB->b8pdir[i]=-1; } } } else { currMB->luma_transform_size_8x8_flag = 0; } if(active_pps->constrained_intra_pred_flag && (img->type==P_SLICE|| img->type==B_SLICE)) // inter frame { if( !IS_INTRA(currMB) ) { img->intra_block[img->current_mb_nr] = 0; } } //! TO for error concealment //! If we have an INTRA Macroblock and we lost the partition //! which contains the intra coefficients Copy MB would be better //! than just a gray 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. dP = &(currSlice->partArr[partMap[SE_CBP_INTRA]]); if(IS_INTRA (currMB) && dP->bitstream->ei_flag && img->number) { currMB->mb_type = 0; currMB->ei_flag = 1; for (i=0;i<4;i++) {currMB->b8mode[i]=currMB->b8pdir[i]=0; } } dP = &(currSlice->partArr[partMap[currSE.type]]); //! End TO //--- init macroblock data --- if (!IS_P8x8 (currMB)) init_macroblock (img); if (IS_DIRECT (currMB) && img->cod_counter >= 0) { currMB->cbp = 0; reset_coeffs(); if (active_pps->entropy_coding_mode_flag ==CABAC) img->cod_counter=-1; return DECODE_MB; } if (IS_COPY (currMB)) //keep last macroblock { int i, j, k; short pmv[2]; int zeroMotionAbove; int zeroMotionLeft; PixelPos mb_a, mb_b; int a_mv_y = 0; int a_ref_idx = 0; int b_mv_y = 0; int b_ref_idx = 0; int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0; short ***cur_mv = dec_picture->mv[LIST_0]; getLuma4x4Neighbour(img->current_mb_nr,-1, 0, &mb_a); getLuma4x4Neighbour(img->current_mb_nr, 0,-1, &mb_b); if (mb_a.available) { a_mv_y = cur_mv[mb_a.pos_y][mb_a.pos_x][1]; a_ref_idx = dec_picture->ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x]; if (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field) { a_mv_y /=2; a_ref_idx *=2; } if (!currMB->mb_field && img->mb_data[mb_a.mb_addr].mb_field) { a_mv_y *=2; a_ref_idx >>=1; } } if (mb_b.available) { b_mv_y = cur_mv[mb_b.pos_y][mb_b.pos_x][1]; b_ref_idx = dec_picture->ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x]; if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field) { b_mv_y /=2; b_ref_idx *=2; } if (!currMB->mb_field && img->mb_data[mb_b.mb_addr].mb_field) { b_mv_y *=2; b_ref_idx >>=1; } } zeroMotionLeft = !mb_a.available ? 1 : a_ref_idx==0 && cur_mv[mb_a.pos_y][mb_a.pos_x][0]==0 && a_mv_y==0 ? 1 : 0; zeroMotionAbove = !mb_b.available ? 1 : b_ref_idx==0 && cur_mv[mb_b.pos_y][mb_b.pos_x][0]==0 && b_mv_y==0 ? 1 : 0; currMB->cbp = 0; reset_coeffs(); img_block_y = img->block_y; if (zeroMotionAbove || zeroMotionLeft) { for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++) { memset(&cur_mv[j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short)); } } else { SetMotionVectorPredictor (img, pmv, 0, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16); for(j=img_block_y;j<img_block_y + BLOCK_SIZE;j++) { for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++) for (k=0;k<2;k++) { cur_mv[j][i][k] = pmv[k]; } } } for(j=img_block_y;j< img_block_y + BLOCK_SIZE;j++) { for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++) { dec_picture->ref_idx[LIST_0][j][i] = 0; dec_picture->ref_pic_id[LIST_0][j][i] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j][i]]; } } return DECODE_MB; } if(currMB->mb_type!=IPCM) { // intra prediction modes for a macroblock 4x4 ********************************************** read_ipred_modes(img,inp); // read inter frame vector data ********************************************************* if (IS_INTERMV (currMB) && (!IS_P8x8(currMB))) { readMotionInfoFromNAL (img, inp); } // read CBP and Coeffs *************************************************************** readCBPandCoeffsFromNAL (img,inp); } else { //read pcm_alignment_zero_bit and pcm_byte[i] // here dP is assigned with the same dP as SE_MBTYPE, because IPCM syntax is in the // same category as MBTYPE dP = &(currSlice->partArr[partMap[SE_MBTYPE]]); readIPCMcoeffsFromNAL(img,inp,dP); } return DECODE_MB; } /*! ************************************************************************ * \brief * Initialize decoding engine after decoding an IPCM macroblock * (for IPCM CABAC 28/11/2003) * * \author * Dong Wang <Dong.Wang@bristol.ac.uk> ************************************************************************ */ void init_decoding_engine_IPCM(struct img_par *img) { Slice *currSlice = img->currentSlice; Bitstream *currStream; int ByteStartPosition; int PartitionNumber; int i; if(currSlice->dp_mode==PAR_DP_1) PartitionNumber=1; else if(currSlice->dp_mode==PAR_DP_3) PartitionNumber=3; else { printf("Partition Mode is not supported\n"); exit(1); } for(i=0;i<PartitionNumber;i++) { currStream = currSlice->partArr[i].bitstream; ByteStartPosition = currStream->read_len; arideco_start_decoding (&currSlice->partArr[i].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } } /*! ************************************************************************ * \brief * Read IPCM pcm_alignment_zero_bit and pcm_byte[i] from stream to img->cof * (for IPCM CABAC and IPCM CAVLC) * * \author * Dong Wang <Dong.Wang@bristol.ac.uk> ************************************************************************ */ void readIPCMcoeffsFromNAL(struct img_par *img, struct inp_par *inp, struct datapartition *dP) { SyntaxElement currSE; int i,j; //For CABAC, we don't need to read bits to let stream byte aligned // because we have variable for integer bytes position if(active_pps->entropy_coding_mode_flag == CABAC) { //read luma and chroma IPCM coefficients currSE.len=8; TRACE_STRING("pcm_byte luma"); for(i=0;i<MB_BLOCK_SIZE;i++) { for(j=0;j<MB_BLOCK_SIZE;j++) { readIPCMBytes_CABAC(&currSE, dP->bitstream); img->cof[(i>>2)][(j>>2)][i & 0x03][j & 0x03]=currSE.value1; } } if (dec_picture->chroma_format_idc != YUV400) { TRACE_STRING("pcm_byte chroma"); for(i=0;i<img->mb_cr_size_y;i++) { for(j=0;j<img->mb_cr_size_x;j++) { readIPCMBytes_CABAC(&currSE, dP->bitstream); img->cof[(i>>2)][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1; } } for(i=0;i<img->mb_cr_size_y;i++) { for(j=0;j<img->mb_cr_size_x;j++) { readIPCMBytes_CABAC(&currSE, dP->bitstream); img->cof[(i>>2)+2][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1; } } } //If the decoded MB is IPCM MB, decoding engine is initialized // here the decoding engine is directly initialized without checking End of Slice // The reason is that, whether current MB is the last MB in slice or not, there is // at least one 'end of slice' syntax after this MB. So when fetching bytes in this // initialisation process, we can guarantee there is bits available in bitstream. init_decoding_engine_IPCM(img); } else { //read bits to let stream byte aligned if((dP->bitstream->frame_bitoffset)%8!=0) { TRACE_STRING("pcm_alignment_zero_bit"); currSE.len=8-(dP->bitstream->frame_bitoffset)%8; readSyntaxElement_FLC(&currSE, dP->bitstream); } //read luma and chroma IPCM coefficients currSE.len=img->bitdepth_luma; TRACE_STRING("pcm_sample_luma"); for(i=0;i<MB_BLOCK_SIZE;i++) { for(j=0;j<MB_BLOCK_SIZE;j++) { readSyntaxElement_FLC(&currSE, dP->bitstream); img->cof[(i>>2)][(j>>2)][i & 0x03][j & 0x03]=currSE.value1; } } currSE.len=img->bitdepth_chroma; if (dec_picture->chroma_format_idc != YUV400) { TRACE_STRING("pcm_sample_chroma (u)"); for(i=0;i<img->mb_cr_size_y;i++) { for(j=0;j<img->mb_cr_size_x;j++) { readSyntaxElement_FLC(&currSE, dP->bitstream); img->cof[(i>>2)][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1; } } TRACE_STRING("pcm_sample_chroma (v)"); for(i=0;i<img->mb_cr_size_y;i++) { for(j=0;j<img->mb_cr_size_x;j++) { readSyntaxElement_FLC(&currSE, dP->bitstream); img->cof[(i>>2)+2][(j>>2)+4][i & 0x03][j & 0x03]=currSE.value1; } } } } } void read_ipred_modes(struct img_par *img,struct inp_par *inp) { int b8,i,j,bi,bj,bx,by,dec; SyntaxElement currSE; Slice *currSlice; DataPartition *dP; int *partMap; Macroblock *currMB; int ts, ls; int mostProbableIntraPredMode; int upIntraPredMode; int leftIntraPredMode; int IntraChromaPredModeFlag; int bs_x, bs_y; int ii,jj; PixelPos left_block; PixelPos top_block; currMB = &img->mb_data[img->current_mb_nr]; IntraChromaPredModeFlag = IS_INTRA(currMB); currSlice = img->currentSlice; partMap = assignSE2partition[currSlice->dp_mode]; currSE.type = SE_INTRAPREDMODE; TRACE_STRING("intra4x4_pred_mode"); dP = &(currSlice->partArr[partMap[currSE.type]]); if (!(active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)) currSE.reading = readIntraPredMode_CABAC; for(b8=0;b8<4;b8++) //loop 8x8 blocks { if((currMB->b8mode[b8]==IBLOCK )||(currMB->b8mode[b8]==I8MB)) { bs_x = bs_y = (currMB->b8mode[b8] == I8MB)?8:4; IntraChromaPredModeFlag = 1; ii=(bs_x>>2); jj=(bs_y>>2); for(j=0;j<2;j+=jj) //loop subblocks { by = (b8&2) + j; bj = img->block_y + by; for(i=0;i<2;i+=ii) { bx = ((b8&1)<<1) + i; bi = img->block_x + bx; //get from stream if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) readSyntaxElement_Intra4x4PredictionMode(&currSE,img,dP); else { currSE.context=(b8<<2)+(j<<1)+i; dP->readSyntaxElement(&currSE,img,dP); } getLuma4x4Neighbour(img->current_mb_nr, (bx<<2) - 1, (by<<2), &left_block); getLuma4x4Neighbour(img->current_mb_nr, (bx<<2), (by<<2) - 1, &top_block); //get from array and decode if (active_pps->constrained_intra_pred_flag) { left_block.available = left_block.available ? img->intra_block[left_block.mb_addr] : 0; top_block.available = top_block.available ? img->intra_block[top_block.mb_addr] : 0; } // !! KS: not sure if the following is still correct... ts = ls = 0; // Check to see if the neighboring block is SI if (IS_OLDINTRA(currMB) && img->type == SI_SLICE) // need support for MBINTLC1 { if (left_block.available) if (img->siblock [left_block.pos_y][left_block.pos_x]) ls=1; if (top_block.available) if (img->siblock [top_block.pos_y][top_block.pos_x]) ts=1; } upIntraPredMode = (top_block.available &&(ts == 0)) ? img->ipredmode[top_block.pos_y ][top_block.pos_x ] : -1; leftIntraPredMode = (left_block.available &&(ls == 0)) ? img->ipredmode[left_block.pos_y][left_block.pos_x] : -1; mostProbableIntraPredMode = (upIntraPredMode < 0 || leftIntraPredMode < 0) ? DC_PRED : upIntraPredMode < leftIntraPredMode ? upIntraPredMode : leftIntraPredMode; dec = (currSE.value1 == -1) ? mostProbableIntraPredMode : currSE.value1 + (currSE.value1 >= mostProbableIntraPredMode); //set for(jj=0;jj<(bs_y>>2);jj++) //loop 4x4s in the subblock for 8x8 prediction setting memset(&img->ipredmode[bj+jj][bi], dec, (bs_x>>2) * sizeof(char)); } } } } if (IntraChromaPredModeFlag && dec_picture->chroma_format_idc != YUV400) { currSE.type = SE_INTRAPREDMODE; TRACE_STRING("intra_chroma_pred_mode"); dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue; else currSE.reading = readCIPredMode_CABAC; dP->readSyntaxElement(&currSE,img,dP); currMB->c_ipred_mode = currSE.value1; if (currMB->c_ipred_mode < DC_PRED_8 || currMB->c_ipred_mode > PLANE_8) { error("illegal chroma intra pred mode!\n", 600); } } } /*! ************************************************************************ * \brief * Set motion vector predictor ************************************************************************ */ static void SetMotionVectorPredictor (struct img_par *img, short pmv[2], char ref_frame, byte list, char ***refPic, short ****tmp_mv, int block_x, int block_y, int blockshape_x, int blockshape_y) { int mb_x = BLOCK_SIZE*block_x; int mb_y = BLOCK_SIZE*block_y; int mb_nr = img->current_mb_nr; int mv_a, mv_b, mv_c, pred_vec=0; int mvPredType, rFrameL, rFrameU, rFrameUR; int hv; PixelPos block_a, block_b, block_c, block_d; getLuma4x4Neighbour(mb_nr, mb_x - 1, mb_y, &block_a); getLuma4x4Neighbour(mb_nr, mb_x, mb_y - 1, &block_b); getLuma4x4Neighbour(mb_nr, mb_x + blockshape_x, mb_y - 1, &block_c); getLuma4x4Neighbour(mb_nr, mb_x - 1, mb_y - 1, &block_d); if (mb_y > 0) { if (mb_x < 8) // first column of 8x8 blocks { if (mb_y==8) { if (blockshape_x == 16) block_c.available = 0; } else { if (mb_x+blockshape_x == 8) block_c.available = 0; } } else { if (mb_x+blockshape_x == 16) block_c.available = 0; } } if (!block_c.available) { block_c=block_d; } mvPredType = MVPRED_MEDIAN; if (!img->MbaffFrameFlag) { rFrameL = block_a.available ? refPic[list][block_a.pos_y][block_a.pos_x] : -1; rFrameU = block_b.available ? refPic[list][block_b.pos_y][block_b.pos_x] : -1; rFrameUR = block_c.available ? refPic[list][block_c.pos_y][block_c.pos_x] : -1; } else { if (img->mb_data[img->current_mb_nr].mb_field) { rFrameL = block_a.available ? img->mb_data[block_a.mb_addr].mb_field ? refPic[list][block_a.pos_y][block_a.pos_x]: refPic[list][block_a.pos_y][block_a.pos_x] * 2: -1; rFrameU = block_b.available ? img->mb_data[block_b.mb_addr].mb_field ? refPic[list][block_b.pos_y][block_b.pos_x]: refPic[list][block_b.pos_y][block_b.pos_x] * 2: -1; rFrameUR = block_c.available ? img->mb_data[block_c.mb_addr].mb_field ? refPic[list][block_c.pos_y][block_c.pos_x]: refPic[list][block_c.pos_y][block_c.pos_x] * 2: -1; } else { rFrameL = block_a.available ? img->mb_data[block_a.mb_addr].mb_field ? refPic[list][block_a.pos_y][block_a.pos_x] >>1: refPic[list][block_a.pos_y][block_a.pos_x] : -1; rFrameU = block_b.available ? img->mb_data[block_b.mb_addr].mb_field ? refPic[list][block_b.pos_y][block_b.pos_x] >>1: refPic[list][block_b.pos_y][block_b.pos_x] : -1; rFrameUR = block_c.available ? img->mb_data[block_c.mb_addr].mb_field ? refPic[list][block_c.pos_y][block_c.pos_x] >>1: refPic[list][block_c.pos_y][block_c.pos_x] : -1; } } /* Prediction if only one of the neighbors uses the reference frame * we are checking */ if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame) mvPredType = MVPRED_L; else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame) mvPredType = MVPRED_U; else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame) mvPredType = MVPRED_UR; // Directional predictions 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; } } for (hv=0; hv < 2; hv++) { if (!img->MbaffFrameFlag || hv==0) { mv_a = block_a.available ? tmp_mv[list][block_a.pos_y][block_a.pos_x][hv] : 0; mv_b = block_b.available ? tmp_mv[list][block_b.pos_y][block_b.pos_x][hv] : 0; mv_c = block_c.available ? tmp_mv[list][block_c.pos_y][block_c.pos_x][hv] : 0; } else { if (img->mb_data[img->current_mb_nr].mb_field) { mv_a = block_a.available ? img->mb_data[block_a.mb_addr].mb_field? tmp_mv[list][block_a.pos_y][block_a.pos_x][hv]: tmp_mv[list][block_a.pos_y][block_a.pos_x][hv] / 2: 0; mv_b = block_b.available ? img->mb_data[block_b.mb_addr].mb_field? tmp_mv[list][block_b.pos_y][block_b.pos_x][hv]: tmp_mv[list][block_b.pos_y][block_b.pos_x][hv] / 2: 0; mv_c = block_c.available ? img->mb_data[block_c.mb_addr].mb_field? tmp_mv[list][block_c.pos_y][block_c.pos_x][hv]: tmp_mv[list][block_c.pos_y][block_c.pos_x][hv] / 2: 0; } else { mv_a = block_a.available ? img->mb_data[block_a.mb_addr].mb_field? tmp_mv[list][block_a.pos_y][block_a.pos_x][hv] * 2: tmp_mv[list][block_a.pos_y][block_a.pos_x][hv]: 0; mv_b = block_b.available ? img->mb_data[block_b.mb_addr].mb_field? tmp_mv[list][block_b.pos_y][block_b.pos_x][hv] * 2: tmp_mv[list][block_b.pos_y][block_b.pos_x][hv]: 0; mv_c = block_c.available ? img->mb_data[block_c.mb_addr].mb_field? tmp_mv[list][block_c.pos_y][block_c.pos_x][hv] * 2: tmp_mv[list][block_c.pos_y][block_c.pos_x][hv]: 0; } } switch (mvPredType) { case MVPRED_MEDIAN: if(!(block_b.available || block_c.available)) pred_vec = mv_a; else pred_vec = mv_a+mv_b+mv_c-imin(mv_a,imin(mv_b,mv_c))-imax(mv_a,imax(mv_b,mv_c)); 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; } pmv[hv] = pred_vec; } } /*! ************************************************************************ * \brief * Set context for reference frames ************************************************************************ */ int BType2CtxRef (int btype) { if (btype<4) return 0; else return 1; } /*! ************************************************************************ * \brief * Read motion info ************************************************************************ */ void readMotionInfoFromNAL (struct img_par *img, struct inp_par *inp) { int i,j,k; int step_h,step_v; int curr_mvd; Macroblock *currMB = &img->mb_data[img->current_mb_nr]; SyntaxElement currSE; Slice *currSlice = img->currentSlice; DataPartition *dP; int *partMap = assignSE2partition[currSlice->dp_mode]; int bframe = (img->type==B_SLICE); 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; char refframe; short pmv[2]; int j4, i4, ii,jj; int vec; int mv_scale = 0; int flag_mode; int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0; byte ** moving_block; short **** co_located_mv; char *** co_located_ref_idx; int64 *** co_located_ref_id; if ((img->MbaffFrameFlag)&&(currMB->mb_field)) { if(img->current_mb_nr&0x01) { moving_block = Co_located->bottom_moving_block; co_located_mv = Co_located->bottom_mv; co_located_ref_idx = Co_located->bottom_ref_idx; co_located_ref_id = Co_located->bottom_ref_pic_id; } else { moving_block = Co_located->top_moving_block; co_located_mv = Co_located->top_mv; co_located_ref_idx = Co_located->top_ref_idx; co_located_ref_id = Co_located->top_ref_pic_id; } } else { moving_block = Co_located->moving_block; co_located_mv = Co_located->mv; co_located_ref_idx = Co_located->ref_idx; co_located_ref_id = Co_located->ref_pic_id; } if (bframe && IS_P8x8 (currMB)) { if (img->direct_spatial_mv_pred_flag) { int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1: img->block_y; int l0_rFrameL, l0_rFrameU, l0_rFrameUL, l0_rFrameUR; int l1_rFrameL, l1_rFrameU, l1_rFrameUL, l1_rFrameUR; PixelPos mb_left, mb_up, mb_upleft, mb_upright; char l0_rFrame,l1_rFrame; short pmvl0[2]={0,0}, pmvl1[2]={0,0}; getLuma4x4Neighbour(img->current_mb_nr, -1, 0, &mb_left); getLuma4x4Neighbour(img->current_mb_nr, 0, -1, &mb_up); getLuma4x4Neighbour(img->current_mb_nr, 16, -1, &mb_upright); getLuma4x4Neighbour(img->current_mb_nr, -1, -1, &mb_upleft); if (!img->MbaffFrameFlag) { l0_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] : -1; l0_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1; l0_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l0_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL; l1_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1; l1_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1; l1_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l1_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL; } else { if (img->mb_data[img->current_mb_nr].mb_field) { l0_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1; l0_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1; l0_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1; l0_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL; l1_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1; l1_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1; l1_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2 : -1; l1_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL; } else { l0_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1; l0_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1; l0_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l0_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL; l1_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1; l1_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1; l1_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l1_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1: dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL; } } l0_rFrame = (l0_rFrameL >= 0 && l0_rFrameU >= 0) ? imin(l0_rFrameL,l0_rFrameU): imax(l0_rFrameL,l0_rFrameU); l0_rFrame = (l0_rFrame >= 0 && l0_rFrameUR >= 0) ? imin(l0_rFrame,l0_rFrameUR): imax(l0_rFrame,l0_rFrameUR); l1_rFrame = (l1_rFrameL >= 0 && l1_rFrameU >= 0) ? imin(l1_rFrameL,l1_rFrameU): imax(l1_rFrameL,l1_rFrameU); l1_rFrame = (l1_rFrame >= 0 && l1_rFrameUR >= 0) ? imin(l1_rFrame,l1_rFrameUR): imax(l1_rFrame,l1_rFrameUR); if (l0_rFrame >=0) SetMotionVectorPredictor (img, pmvl0, l0_rFrame, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16); if (l1_rFrame >=0) SetMotionVectorPredictor (img, pmvl1, l1_rFrame, LIST_1, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16); for (i=0;i<4;i++) { if (currMB->b8mode[i] == 0) { for(j=2*(i>>1);j<2*(i>>1)+2;j++) { for(k=2*(i&0x01);k<2*(i&0x01)+2;k++) { int j6 = imgblock_y+j; j4 = img->block_y+j; i4 = img->block_x+k; if (l0_rFrame >= 0) { if (!l0_rFrame && ((!moving_block[j6][i4]) && (!listX[1+list_offset][0]->is_long_term))) { dec_picture->mv [LIST_0][j4][i4][0] = 0; dec_picture->mv [LIST_0][j4][i4][1] = 0; dec_picture->ref_idx[LIST_0][j4][i4] = 0; } else { dec_picture->mv [LIST_0][j4][i4][0] = pmvl0[0]; dec_picture->mv [LIST_0][j4][i4][1] = pmvl0[1]; dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame; } } else { dec_picture->mv [LIST_0][j4][i4][0] = 0; dec_picture->mv [LIST_0][j4][i4][1] = 0; dec_picture->ref_idx[LIST_0][j4][i4] = -1; } if (l1_rFrame >= 0) { if (l1_rFrame==0 && ((!moving_block[j6][i4])&& (!listX[1+list_offset][0]->is_long_term))) { dec_picture->mv [LIST_1][j4][i4][0] = 0; dec_picture->mv [LIST_1][j4][i4][1] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = 0; } else { dec_picture->mv [LIST_1][j4][i4][0] = pmvl1[0]; dec_picture->mv [LIST_1][j4][i4][1] = pmvl1[1]; dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame; } } else { dec_picture->mv [LIST_1][j4][i4][0] = 0; dec_picture->mv [LIST_1][j4][i4][1] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = -1; } if (l0_rFrame <0 && l1_rFrame <0) { dec_picture->ref_idx[LIST_0][j4][i4] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = 0; } } } } } } else { for (i=0;i<4;i++) { if (currMB->b8mode[i] == 0) { for(j=2*(i>>1);j<2*(i>>1)+2;j++) { for(k=2*(i&0x01);k<2*(i&0x01)+2;k++) { int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0; int imgblock_y = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1 : img->block_y>>1 : img->block_y; int refList = co_located_ref_idx[LIST_0 ][imgblock_y+j][img->block_x+k]== -1 ? LIST_1 : LIST_0; int ref_idx = co_located_ref_idx[refList][imgblock_y + j][img->block_x + k]; int mapped_idx=-1, iref; if (ref_idx == -1) { dec_picture->ref_idx [LIST_0][img->block_y + j][img->block_x + k] = 0; dec_picture->ref_idx [LIST_1][img->block_y + j][img->block_x + k] = 0; } else { for (iref=0;iref<imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++) { int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field)); if(img->structure==0 && curr_mb_field==0) { // If the current MB is a frame MB and the colocated is from a field picture, // then the co_located_ref_id may have been generated from the wrong value of // frame_poc if it references it's complementary field, so test both POC values if(listX[0][iref]->top_poc*2 == co_located_ref_id[refList][imgblock_y + j][img->block_x + k] || listX[0][iref]->bottom_poc*2 == co_located_ref_id[refList][imgblock_y + j][img->block_x + k]) { mapped_idx=iref; break; } else //! invalid index. Default to zero even though this case should not happen mapped_idx=INVALIDINDEX; continue; } if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][imgblock_y + j][img->block_x + k]) { mapped_idx=iref; break; } else //! invalid index. Default to zero even though this case should not happen mapped_idx=INVALIDINDEX; } if (INVALIDINDEX == mapped_idx) { error("temporal direct error\ncolocated block has ref that is unavailable",-1111); } dec_picture->ref_idx [LIST_0][img->block_y + j][img->block_x + k] = mapped_idx; dec_picture->ref_idx [LIST_1][img->block_y + j][img->block_x + k] = 0; } } } } } } } // If multiple ref. frames, read reference frame for the MB ********************************* if(img->num_ref_idx_l0_active>1) { flag_mode = ( img->num_ref_idx_l0_active == 2 ? 1 : 0); currSE.type = SE_REFFRAME; dP = &(currSlice->partArr[partMap[SE_REFFRAME]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue; else currSE.reading = readRefFrame_CABAC; for (j0=0; j0<4; j0+=step_v0) { for (i0=0; i0<4; i0+=step_h0) { k=2*(j0>>1)+(i0>>1); if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0) { TRACE_STRING("ref_idx_l0"); img->subblock_x = i0; img->subblock_y = j0; if (!IS_P8x8 (currMB) || bframe || (!bframe && !img->allrefzero)) { currSE.context = BType2CtxRef (currMB->b8mode[k]); if( (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) && flag_mode ) { currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); currSE.value1 = 1 - currSE.value1; } else { currSE.value2 = LIST_0; dP->readSyntaxElement (&currSE,img,dP); } refframe = currSE.value1; } else { refframe = 0; } for (j=img->block_y +j0; j<img->block_y +j0+step_v0;j++) memset(&dec_picture->ref_idx[LIST_0][j][img->block_x + i0], refframe, step_h0 * sizeof(char)); } } } } else { for (j0=0; j0<4; j0+=step_v0) { for (i0=0; i0<4; i0+=step_h0) { k=2*(j0>>1)+(i0>>1); if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0) { for (j=img->block_y + j0; j < img->block_y + j0+step_v0;j++) memset(&dec_picture->ref_idx[LIST_0][j][img->block_x + i0], 0, step_h0 * sizeof(char)); } } } } // If backward multiple ref. frames, read backward reference frame for the MB ********************************* if(img->num_ref_idx_l1_active>1) { flag_mode = ( img->num_ref_idx_l1_active == 2 ? 1 : 0); currSE.type = SE_REFFRAME; dP = &(currSlice->partArr[partMap[SE_REFFRAME]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_ue; else currSE.reading = readRefFrame_CABAC; for (j0=0; j0<4; j0+=step_v0) { for (i0=0; i0<4; i0+=step_h0) { k=2*(j0>>1)+(i0>>1); if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0) { TRACE_STRING("ref_idx_l1"); img->subblock_x = i0; img->subblock_y = j0; currSE.context = BType2CtxRef (currMB->b8mode[k]); if( (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) && flag_mode ) { currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); currSE.value1 = 1-currSE.value1; } else { currSE.value2 = LIST_1; dP->readSyntaxElement (&currSE,img,dP); } refframe = currSE.value1; for (j=img->block_y + j0; j<img->block_y + j0+step_v0;j++) { memset(&dec_picture->ref_idx[LIST_1][j][img->block_x + i0], refframe, step_h0 * sizeof(char)); } } } } } else { for (j0=0; j0<4; j0+=step_v0) { for (i0=0; i0<4; i0+=step_h0) { k=2*(j0>>1)+(i0>>1); if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0) { for (j=img->block_y + j0; j<img->block_y + j0+step_v0;j++) memset(&dec_picture->ref_idx[LIST_1][ j][img->block_x + i0], 0, step_h0 * sizeof(char)); } } } } //===== READ FORWARD MOTION VECTORS ===== currSE.type = SE_MVD; dP = &(currSlice->partArr[partMap[SE_MVD]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_se; else currSE.reading = readMVD_CABAC; for (j0=0; j0<4; j0+=step_v0) for (i0=0; i0<4; i0+=step_h0) { k=2*(j0>>1)+(i0>>1); 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]; refframe = dec_picture->ref_idx[LIST_0][img->block_y+j0][img->block_x+i0]; for (j=j0; j<j0+step_v0; j+=step_v) { j4 = img->block_y+j; for (i=i0; i<i0+step_h0; i+=step_h) { i4 = img->block_x+i; // first make mv-prediction SetMotionVectorPredictor (img, pmv, refframe, LIST_0, dec_picture->ref_idx, dec_picture->mv, i, j, 4*step_h, 4*step_v); for (k=0; k < 2; k++) { TRACE_STRING("mvd_l0"); img->subblock_x = i; // position used for context determination img->subblock_y = j; // position used for context determination currSE.value2 = k<<1; // identifies the component; only used for context determination dP->readSyntaxElement(&currSE,img,dP); curr_mvd = currSE.value1; vec=curr_mvd+pmv[k]; /* find motion vector */ for(jj=0;jj<step_v;jj++) { for(ii=0;ii<step_h;ii++) { dec_picture->mv [LIST_0][j4+jj][i4+ii][k] = vec; currMB->mvd [LIST_0][j +jj][i +ii][k] = curr_mvd; } } } } } } else if (currMB->b8mode[k=2*(j0>>1)+(i0>>1)]==0) { if (!img->direct_spatial_mv_pred_flag) { int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? 4 : 2 : 0; int imgblock_y = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1 : img->block_y; int refList = (co_located_ref_idx[LIST_0 ][imgblock_y+j0][img->block_x+i0]== -1 ? LIST_1 : LIST_0); int ref_idx = co_located_ref_idx[refList][imgblock_y+j0][img->block_x+i0]; if (ref_idx==-1) { for (j4=img->block_y+j0; j4<img->block_y+j0+step_v0; j4++) { for (i4=img->block_x+i0; i4<img->block_x+i0+step_h0; i4++) { dec_picture->ref_idx [LIST_1][j4][i4]=0; dec_picture->ref_idx [LIST_0][j4][i4]=0; for (ii=0; ii < 2; ii++) { dec_picture->mv [LIST_0][j4][i4][ii]=0; dec_picture->mv [LIST_1][j4][i4][ii]=0; } } } } else { int mapped_idx=-1, iref; int j6; for (iref = 0; iref < imin(img->num_ref_idx_l0_active, listXsize[LIST_0 + list_offset]); iref++) { int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field)); if(img->structure==0 && curr_mb_field==0) { // If the current MB is a frame MB and the colocated is from a field picture, // then the co_located_ref_id may have been generated from the wrong value of // frame_poc if it references it's complementary field, so test both POC values if(listX[0][iref]->top_poc * 2 == co_located_ref_id[refList][imgblock_y + j0][img->block_x + i0] || listX[0][iref]->bottom_poc * 2 == co_located_ref_id[refList][imgblock_y + j0][img->block_x + i0]) { mapped_idx=iref; break; } else //! invalid index. Default to zero even though this case should not happen mapped_idx=INVALIDINDEX; continue; } if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][imgblock_y+j0][img->block_x+i0]) { mapped_idx=iref; break; } else //! invalid index. Default to zero even though this case should not happen mapped_idx=INVALIDINDEX; } if (INVALIDINDEX == mapped_idx) { error("temporal direct error\ncolocated block has ref that is unavailable",-1111); } for (j=j0; j<j0+step_v0; j++) { j4 = img->block_y+j; j6 = imgblock_y + j; for (i4=img->block_x+i0; i4<img->block_x+i0+step_h0; i4++) { mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx]; dec_picture->ref_idx [LIST_0][j4][i4] = mapped_idx; dec_picture->ref_idx [LIST_1][j4][i4] = 0; for (ii=0; ii < 2; ii++) { if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term) { dec_picture->mv [LIST_0][j4][i4][ii] = co_located_mv[refList][j6][i4][ii]; dec_picture->mv [LIST_1][j4][i4][ii] = 0; } else { dec_picture->mv [LIST_0][j4][i4][ii] = (mv_scale * co_located_mv[refList][j6][i4][ii] + 128 ) >> 8; dec_picture->mv [LIST_1][j4][i4][ii] = dec_picture->mv[LIST_0][j4][i4][ii] - co_located_mv[refList][j6][i4][ii]; } } } } } } } } //===== READ BACKWARD MOTION VECTORS ===== currSE.type = SE_MVD; dP = &(currSlice->partArr[partMap[SE_MVD]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_se; else currSE.reading = readMVD_CABAC; for (j0=0; j0<4; j0+=step_v0) { for (i0=0; i0<4; i0+=step_h0) { k=2*(j0>>1)+(i0>>1); 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 = dec_picture->ref_idx[LIST_1][img->block_y+j0][img->block_x+i0]; for (j=j0; j<j0+step_v0; j+=step_v) { j4 = img->block_y+j; for (i=i0; i<i0+step_h0; i+=step_h) { i4 = img->block_x+i; // first make mv-prediction SetMotionVectorPredictor (img, pmv, refframe, LIST_1, dec_picture->ref_idx, dec_picture->mv, i, j, 4*step_h, 4*step_v); for (k=0; k < 2; k++) { TRACE_STRING("mvd_l1"); img->subblock_x = i; // position used for context determination img->subblock_y = j; // position used for context determination currSE.value2 = (k<<1) +1; // identifies the component; only used for context determination dP->readSyntaxElement(&currSE,img,dP); curr_mvd = currSE.value1; vec=curr_mvd+pmv[k]; /* find motion vector */ for(jj=0;jj<step_v;jj++) { for(ii=0;ii<step_h;ii++) { dec_picture->mv [LIST_1][j4+jj][i4+ii][k] = vec; currMB->mvd [LIST_1][j+jj] [i+ii] [k] = curr_mvd; } } } } } } } } // record reference picture Ids for deblocking decisions for(j4=img->block_y;j4<(img->block_y+4);j4++) { for(i4=img->block_x;i4<(img->block_x+4);i4++) { if (dec_picture->ref_idx[LIST_0][j4][i4]>=0) dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]]; else dec_picture->ref_pic_id[LIST_0][j4][i4] = INT64_MIN; if (dec_picture->ref_idx[LIST_1][j4][i4]>=0) dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]]; else dec_picture->ref_pic_id[LIST_1][j4][i4] = INT64_MIN; } } } /*! ************************************************************************ * \brief * Get the Prediction from the Neighboring Blocks for Number of Nonzero Coefficients * * Luma Blocks ************************************************************************ */ int predict_nnz(struct img_par *img, int i,int j) { PixelPos pix; int pred_nnz = 0; int cnt = 0; int mb_nr = img->current_mb_nr; Macroblock *currMB = &(img->mb_data[mb_nr]); // left block getLuma4x4Neighbour(mb_nr, (i<<2) - 1, (j<<2), &pix); if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3)) { pix.available &= img->intra_block[pix.mb_addr]; if (!pix.available) cnt++; } if (pix.available) { pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][pix.y]; cnt++; } // top block getLuma4x4Neighbour(mb_nr, (i<<2), (j<<2) - 1, &pix); if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3)) { pix.available &= img->intra_block[pix.mb_addr]; if (!pix.available) cnt++; } if (pix.available) { pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][pix.y]; cnt++; } if (cnt==2) { pred_nnz++; pred_nnz>>=1; } return pred_nnz; } /*! ************************************************************************ * \brief * Get the Prediction from the Neighboring Blocks for Number of Nonzero Coefficients * * Chroma Blocks ************************************************************************ */ int predict_nnz_chroma(struct img_par *img, int i,int j) { PixelPos pix; int pred_nnz = 0; int cnt =0; int mb_nr = img->current_mb_nr; static const int j_off_tab [12] = {0,0,0,0,4,4,4,4,8,8,8,8}; int j_off = j_off_tab[j]; Macroblock *currMB = &(img->mb_data[mb_nr]); if (dec_picture->chroma_format_idc != YUV444) { //YUV420 and YUV422 // left block getChroma4x4Neighbour(mb_nr, ((i&0x01)<<2) - 1, ((j-4)<<2), &pix); if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3)) { pix.available &= img->intra_block[pix.mb_addr]; if (!pix.available) cnt++; } if (pix.available) { pred_nnz = img->nz_coeff [pix.mb_addr ][2 * (i>>1) + pix.x][4 + pix.y]; cnt++; } // top block getChroma4x4Neighbour(mb_nr, ((i&0x01)<<2), ((j-4)<<2) - 1, &pix); if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3)) { pix.available &= img->intra_block[pix.mb_addr]; if (!pix.available) cnt++; } if (pix.available) { pred_nnz += img->nz_coeff [pix.mb_addr ][2 * (i>>1) + pix.x][4 + pix.y]; cnt++; } } else { //YUV444 // left block getChroma4x4Neighbour(mb_nr, (i<<2) - 1, ((j-j_off)<<2), &pix); if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3)) { pix.available &= img->intra_block[pix.mb_addr]; cnt--; } if (pix.available) { pred_nnz = img->nz_coeff [pix.mb_addr ][pix.x][j_off + pix.y]; cnt++; } // top block getChroma4x4Neighbour(mb_nr, (i<<2), ((j-j_off)<<2) -1, &pix); if (IS_INTRA(currMB) && pix.available && active_pps->constrained_intra_pred_flag && (img->currentSlice->dp_mode==PAR_DP_3)) { pix.available &= img->intra_block[pix.mb_addr]; cnt--; } if (pix.available) { pred_nnz += img->nz_coeff [pix.mb_addr ][pix.x][j_off + pix.y]; cnt++; } } if (cnt==2) { pred_nnz++; pred_nnz>>=1; } return pred_nnz; } /*! ************************************************************************ * \brief * Reads coeff of an 4x4 block (CAVLC) * * \author * Karl Lillevold <karll@real.com> * contributions by James Au <james@ubvideo.com> ************************************************************************ */ void readCoeff4x4_CAVLC (struct img_par *img,struct inp_par *inp, int block_type, int i, int j, int levarr[16], int runarr[16], int *number_coefficients) { int mb_nr = img->current_mb_nr; Macroblock *currMB = &img->mb_data[mb_nr]; SyntaxElement currSE; Slice *currSlice = img->currentSlice; DataPartition *dP; int *partMap = assignSE2partition[currSlice->dp_mode]; int k, code, vlcnum; int numcoeff, numtrailingones, numcoeff_vlc; int level_two_or_higher; int numones, totzeros, level, cdc=0, cac=0; int zerosleft, ntr, dptype = 0; int max_coeff_num = 0, nnz; char type[15]; static int incVlc[] = {0,3,6,12,24,48,32768}; // maximum vlc = 6 numcoeff = 0; switch (block_type) { case LUMA: max_coeff_num = 16; #if TRACE sprintf(type, "%s", "Luma"); #endif dptype = IS_INTRA (currMB) ? SE_LUM_AC_INTRA : SE_LUM_AC_INTER; break; case LUMA_INTRA16x16DC: max_coeff_num = 16; #if TRACE sprintf(type, "%s", "Lum16DC"); #endif dptype = SE_LUM_DC_INTRA; break; case LUMA_INTRA16x16AC: max_coeff_num = 15; #if TRACE sprintf(type, "%s", "Lum16AC"); #endif dptype = SE_LUM_AC_INTRA; break; case CHROMA_DC: max_coeff_num = img->num_cdc_coeff; cdc = 1; #if TRACE sprintf(type, "%s", "ChrDC"); #endif dptype = IS_INTRA (currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER; break; case CHROMA_AC: max_coeff_num = 15; cac = 1; #if TRACE sprintf(type, "%s", "ChrAC"); #endif dptype = IS_INTRA (currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER; break; default: error ("readCoeff4x4_CAVLC: invalid block type", 600); break; } currSE.type = dptype; dP = &(currSlice->partArr[partMap[dptype]]); img->nz_coeff[img->current_mb_nr][i][j] = 0; if (!cdc) { // luma or chroma AC if (!cac) { nnz = predict_nnz(img, i, j); } else { nnz = predict_nnz_chroma(img, i, j); } if (nnz < 2) { numcoeff_vlc = 0; } else if (nnz < 4) { numcoeff_vlc = 1; } else if (nnz < 8) { numcoeff_vlc = 2; } else // { numcoeff_vlc = 3; } currSE.value1 = numcoeff_vlc; readSyntaxElement_NumCoeffTrailingOnes(&currSE, dP, type); numcoeff = currSE.value1; numtrailingones = currSE.value2; img->nz_coeff[img->current_mb_nr][i][j] = numcoeff; } else { // chroma DC readSyntaxElement_NumCoeffTrailingOnesChromaDC(&currSE, dP); numcoeff = currSE.value1; numtrailingones = currSE.value2; } for (k = 0; k < max_coeff_num; k++) { levarr[k] = 0; runarr[k] = 0; } numones = numtrailingones; *number_coefficients = numcoeff; if (numcoeff) { if (numtrailingones) { currSE.len = numtrailingones; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "%s trailing ones sign (%d,%d)", type, i, j); #endif readSyntaxElement_FLC (&currSE, dP->bitstream); code = currSE.inf; ntr = numtrailingones; for (k = numcoeff-1; k > numcoeff-1-numtrailingones; k--) { ntr --; levarr[k] = (code>>ntr)&1 ? -1 : 1; } } // decode levels level_two_or_higher = (numcoeff > 3 && numtrailingones == 3)? 0 : 1; vlcnum = (numcoeff > 10 && numtrailingones < 3) ? 1 : 0; for (k = numcoeff - 1 - numtrailingones; k >= 0; k--) { #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "%s lev (%d,%d) k=%d vlc=%d ", type, i, j, k, vlcnum); #endif if (vlcnum == 0) readSyntaxElement_Level_VLC0(&currSE, dP); else readSyntaxElement_Level_VLCN(&currSE, vlcnum, dP); if (level_two_or_higher) { currSE.inf += (currSE.inf > 0) ? 1 : -1; level_two_or_higher = 0; } level = levarr[k] = currSE.inf; if (iabs(level) == 1) numones ++; // update VLC table if (iabs(level)>incVlc[vlcnum]) vlcnum++; if (k == numcoeff - 1 - numtrailingones && iabs(level)>3) vlcnum = 2; } if (numcoeff < max_coeff_num) { // decode total run vlcnum = numcoeff-1; currSE.value1 = vlcnum; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "%s totalrun (%d,%d) vlc=%d ", type, i,j, vlcnum); #endif if (cdc) readSyntaxElement_TotalZerosChromaDC(&currSE, dP); else readSyntaxElement_TotalZeros(&currSE, dP); totzeros = currSE.value1; } else { totzeros = 0; } // decode run before each coefficient zerosleft = totzeros; i = numcoeff - 1; if (zerosleft > 0 && i > 0) { do { // select VLC for runbefore vlcnum = zerosleft - 1; if (vlcnum > RUNBEFORE_NUM - 1) vlcnum = RUNBEFORE_NUM - 1; currSE.value1 = vlcnum; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "%s run (%d,%d) k=%d vlc=%d ", type, i, j, i, vlcnum); #endif readSyntaxElement_Run(&currSE, dP); runarr[i] = currSE.value1; zerosleft -= runarr[i]; i --; } while (zerosleft != 0 && i != 0); } runarr[i] = zerosleft; } // if numcoeff } /*! ************************************************************************ * \brief * Calculate the quantisation and inverse quantisation parameters * ************************************************************************ */ void CalculateQuant8Param() { int i, j, k, temp; for(k=0; k<6; k++) for(j=0; j<8; j++) { for(i=0; i<8; i++) { temp = (i<<3)+j; InvLevelScale8x8Luma_Intra[k][i][j] = dequant_coef8[k][j][i]*qmatrix[6][temp]; InvLevelScale8x8Luma_Inter[k][i][j] = dequant_coef8[k][j][i]*qmatrix[7][temp]; } } } /*! ************************************************************************ * \brief * Get coefficients (run/level) of one 8x8 block * from the NAL (CABAC Mode) ************************************************************************ */ void readLumaCoeff8x8_CABAC (struct img_par *img,struct inp_par *inp, int b8) { int i,j,k; int level = 1; int mb_nr = img->current_mb_nr; Macroblock *currMB = &img->mb_data[mb_nr]; int cbp = currMB->cbp; SyntaxElement currSE; Slice *currSlice = img->currentSlice; DataPartition *dP; int *partMap = assignSE2partition[currSlice->dp_mode]; int start_scan = 0; // take all coeffs int coef_ctr = start_scan - 1;// i0, j0; int boff_x, boff_y; int run, len; int qp_per = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6; int qp_rem = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6; Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1); int (*InvLevelScale8x8)[8] = IS_INTRA(currMB)? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem]; // select scan type const byte (*pos_scan8x8)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8 : FIELD_SCAN8x8; img->is_intra_block = IS_INTRA(currMB); if (cbp & (1<<b8)) // are there any coeff in current block at all { // === set offset in current macroblock === boff_x = (b8&0x01) << 3; boff_y = (b8 >> 1) << 3; img->subblock_x = boff_x >> 2; // position for coeff_count ctx img->subblock_y = boff_y >> 2; // position for coeff_count ctx if(!lossless_qpprime) { for(k=start_scan;(k < 65) && (level != 0);k++) { //============ read ============= /* * make distinction between INTRA and INTER coded * luminance coefficients */ currSE.context = LUMA_8x8; currSE.type = ((img->is_intra_block == 1) ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER)); #if TRACE sprintf(currSE.tracestring, "Luma8x8 sng "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; //============ decode ============= if (level != 0) /* leave if len=1 */ { coef_ctr += run + 1; i=pos_scan8x8[coef_ctr][0]; j=pos_scan8x8[coef_ctr][1]; currMB->cbp_blk |= 51 << (4 * b8 - 2 * (b8 & 0x01)); // corresponds to 110011, as if all four 4x4 blocks contain coeff, shifted to block position img->m7[boff_y + j][boff_x + i] = rshift_rnd_sf((level * InvLevelScale8x8[j][i]) << qp_per, 6); // dequantization } } } else { for(k=start_scan;(k < 65) && (level != 0);k++) { //============ read ============= /* * make distinction between INTRA and INTER coded * luminance coefficients */ currSE.context = LUMA_8x8; currSE.type = ((img->is_intra_block == 1) ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER)); #if TRACE sprintf(currSE.tracestring, "Luma8x8 sng "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; //============ decode ============= if (level != 0) /* leave if len=1 */ { coef_ctr += run+1; i=pos_scan8x8[coef_ctr][0]; j=pos_scan8x8[coef_ctr][1]; currMB->cbp_blk |= 51 << (4 * b8 - 2 * (b8 & 0x01)); // corresponds to 110011, as if all four 4x4 blocks contain coeff, shifted to block position img->m7[boff_y + j][boff_x + i] = level; } } } } } /*! ************************************************************************ * \brief * Get coded block pattern and coefficients (run/level) * from the NAL ************************************************************************ */ void readCBPandCoeffsFromNAL(struct img_par *img,struct inp_par *inp) { int i,j,k; int level; int mb_nr = img->current_mb_nr; int ii,jj; int m2,jg2;// i1,j1; Macroblock *currMB = &img->mb_data[mb_nr]; int cbp; SyntaxElement currSE; Slice *currSlice = img->currentSlice; DataPartition *dP; int *partMap = assignSE2partition[currSlice->dp_mode]; int coef_ctr, i0, j0, b8; int ll; int block_x,block_y; int start_scan; int run, len; int levarr[16], runarr[16], numcoeff; int qp_const; int qp_per = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6; int qp_rem = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6; int smb = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB); int uv; int qp_const_uv[2]; int qp_per_uv[2]; int qp_rem_uv[2]; int intra = IS_INTRA (currMB); int temp[4]; int b4; int yuv = dec_picture->chroma_format_idc-1; int m5[4]; int m6[4]; int need_transform_size_flag; Boolean lossless_qpprime = (Boolean) ((img->qp + img->bitdepth_luma_qp_scale)==0 && img->lossless_qpprime_flag==1); int (*InvLevelScale4x4)[4] = NULL; int (*InvLevelScale8x8)[8] = NULL; // select scan type const byte (*pos_scan8x8)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN8x8 : FIELD_SCAN8x8; const byte (*pos_scan4x4)[2] = ((img->structure == FRAME) && (!currMB->mb_field)) ? SNGL_SCAN : FIELD_SCAN; if(img->type==SP_SLICE && currMB->mb_type!=I16MB ) smb=1; // QPI //init constants for every chroma qp offset if (dec_picture->chroma_format_idc != YUV400) { for (i=0; i<2; i++) { qp_per_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)/6; qp_rem_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)%6; } } // read CBP if not new intra mode if (!IS_NEWINTRA (currMB)) { //===== C B P ===== //--------------------- currSE.type = (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB || currMB->mb_type == I8MB) ? SE_CBP_INTRA : SE_CBP_INTER; dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.mapping = (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB || currMB->mb_type == I8MB) ? linfo_cbp_intra : linfo_cbp_inter; } else { currSE.reading = readCBP_CABAC; } TRACE_STRING("coded_block_pattern"); dP->readSyntaxElement(&currSE,img,dP); currMB->cbp = cbp = currSE.value1; //============= Transform size flag for INTER MBs ============= //------------------------------------------------------------- need_transform_size_flag = (((currMB->mb_type >= 1 && currMB->mb_type <= 3)|| (IS_DIRECT(currMB) && active_sps->direct_8x8_inference_flag) || (currMB->NoMbPartLessThan8x8Flag)) && currMB->mb_type != I8MB && currMB->mb_type != I4MB && (currMB->cbp&15) && img->Transform8x8Mode); if (need_transform_size_flag) { currSE.type = SE_HEADER; dP = &(currSlice->partArr[partMap[SE_HEADER]]); currSE.reading = readMB_transform_size_flag_CABAC; TRACE_STRING("transform_size_8x8_flag"); // read UVLC transform_size_8x8_flag if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.len = 1; readSyntaxElement_FLC(&currSE, dP->bitstream); } else { dP->readSyntaxElement(&currSE,img,dP); } currMB->luma_transform_size_8x8_flag = currSE.value1; } //===== DQUANT ===== //---------------------- // Delta quant only if nonzero coeffs if (cbp !=0) { currSE.type = (IS_INTER (currMB)) ? SE_DELTA_QUANT_INTER : SE_DELTA_QUANT_INTRA; dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.mapping = linfo_se; } else currSE.reading= readDquant_CABAC; //gabi TRACE_STRING("mb_qp_delta"); dP->readSyntaxElement(&currSE,img,dP); currMB->delta_quant = currSE.value1; if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2))) error ("mb_qp_delta is out of range", 500); img->qp= ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) - img->bitdepth_luma_qp_scale; } } else { cbp = currMB->cbp; } for (i=0;i<BLOCK_SIZE;i++) for (j=0;j<BLOCK_SIZE;j++) memset(&img->cof[i][j][0][0], 0, BLOCK_SIZE * BLOCK_SIZE * sizeof(int)); // reset luma coeffs if (IS_NEWINTRA (currMB)) // read DC coeffs for new intra modes { currSE.type = SE_DELTA_QUANT_INTRA; dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.mapping = linfo_se; } else { currSE.reading= readDquant_CABAC; } #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "Delta quant "); #endif dP->readSyntaxElement(&currSE,img,dP); currMB->delta_quant = currSE.value1; if ((currMB->delta_quant < -(26 + img->bitdepth_luma_qp_scale/2)) || (currMB->delta_quant > (25 + img->bitdepth_luma_qp_scale/2))) error ("mb_qp_delta is out of range", 500); img->qp= ((img->qp + currMB->delta_quant + 52 + 2*img->bitdepth_luma_qp_scale)%(52+img->bitdepth_luma_qp_scale)) - img->bitdepth_luma_qp_scale; for (i=0;i<BLOCK_SIZE;i++) for (j=0;j<BLOCK_SIZE;j++) img->ipredmode[img->block_y+j][img->block_x+i]=DC_PRED; if (active_pps->entropy_coding_mode_flag == UVLC) { readCoeff4x4_CAVLC(img, inp, LUMA_INTRA16x16DC, 0, 0, levarr, runarr, &numcoeff); coef_ctr=-1; level = 1; // just to get inside the loop for(k = 0; k < numcoeff; k++) { if (levarr[k] != 0) // leave if len=1 { coef_ctr=coef_ctr+runarr[k]+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; img->cof[i0][j0][0][0]=levarr[k];// add new intra DC coeff } } } else { currSE.type = SE_LUM_DC_INTRA; dP = &(currSlice->partArr[partMap[currSE.type]]); currSE.context = LUMA_16DC; currSE.type = SE_LUM_DC_INTRA; img->is_intra_block = 1; if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) { currSE.mapping = linfo_levrun_inter; } else { currSE.reading = readRunLevel_CABAC; } coef_ctr = -1; level = 1; // just to get inside the loop for(k=0;(k<17) && (level!=0);k++) { #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC luma 16x16 "); #endif dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) // leave if len=1 { coef_ctr=coef_ctr+run+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; img->cof[i0][j0][0][0]=level;// add new intra DC coeff } } } if(!lossless_qpprime) itrans_2(img);// transform new intra DC } currMB->qp = img->qp; set_chroma_qp(currMB); qp_per = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)/6; qp_rem = (img->qp + img->bitdepth_luma_qp_scale - MIN_QP)%6; qp_const = 1<<(3-qp_per); InvLevelScale4x4 = intra? InvLevelScale4x4Luma_Intra[qp_rem] : InvLevelScale4x4Luma_Inter[qp_rem]; InvLevelScale8x8 = intra? InvLevelScale8x8Luma_Intra[qp_rem] : InvLevelScale8x8Luma_Inter[qp_rem]; //init constants for every chroma qp offset if (dec_picture->chroma_format_idc != YUV400) { for(i=0; i < 2; i++) { qp_per_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)/6; qp_rem_uv[i] = (currMB->qpc[i] + img->bitdepth_chroma_qp_scale)%6; } } // 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>>1) + (block_x>>1); if (active_pps->entropy_coding_mode_flag == UVLC) { for (j=block_y; j < block_y+2; j++) { for (i=block_x; i < block_x+2; i++) { ii = block_x >> 1; jj = block_y >> 1; b8 = 2 * jj + ii; if (cbp & (1<<b8)) /* are there any coeff in current block at all */ { readCoeff4x4_CAVLC(img, inp, (IS_NEWINTRA(currMB) ? LUMA_INTRA16x16AC : LUMA), i, j, levarr, runarr, &numcoeff); start_scan = IS_NEWINTRA(currMB) ? 1 : 0; coef_ctr = start_scan - 1; if(!lossless_qpprime) { if (!currMB->luma_transform_size_8x8_flag) // 4x4 transform { for (k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { coef_ctr += runarr[k]+1; i0 = pos_scan4x4[coef_ctr][0]; j0 = pos_scan4x4[coef_ctr][1]; // inverse quant for 4x4 transform only currMB->cbp_blk |= (int64) 1 << ((j<<2) + i); img->cof[i][j][j0][i0]= rshift_rnd_sf((levarr[k]*InvLevelScale4x4[j0][i0])<<qp_per, 4); } } } else // 8x8 transform { int b4, iz, jz; for (k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { coef_ctr += runarr[k]+1; // do same as CABAC for deblocking: any coeff in the 8x8 marks all the 4x4s //as containing coefficients currMB->cbp_blk |= 51 << ((block_y<<2) + block_x); b4 = 2*(j - block_y)+(i - block_x); iz = pos_scan8x8[(coef_ctr << 2) + b4][0]; jz = pos_scan8x8[(coef_ctr << 2) + b4][1]; img->m7[block_y*4 +jz][block_x*4 +iz] = rshift_rnd_sf((levarr[k]*InvLevelScale8x8[jz][iz])<<qp_per, 6); // dequantization } }//else (!currMB->luma_transform_size_8x8_flag) } } else { if (!currMB->luma_transform_size_8x8_flag) // inverse quant for 4x4 transform { for (k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { coef_ctr += runarr[k]+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; currMB->cbp_blk |= (int64) 1 << ((j<<2) + i); img->cof[i][j][j0][i0]= levarr[k]; } } } else // inverse quant for 8x8 transform { int b4, iz, jz; for (k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { coef_ctr += runarr[k]+1; // do same as CABAC for deblocking: any coeff in the 8x8 marks all the 4x4s //as containing coefficients currMB->cbp_blk |= 51 << ((block_y<<2) + block_x); b4 = 2*(j-block_y)+(i-block_x); iz=pos_scan8x8[coef_ctr*4+b4][0]; jz=pos_scan8x8[coef_ctr*4+b4][1]; img->m7[block_y*4 +jz][block_x*4 +iz] = levarr[k]; } } }//else (!currMB->luma_transform_size_8x8_flag) } } else { img->nz_coeff[img->current_mb_nr][i][j] = 0; } } } } // VLC else { if(currMB->luma_transform_size_8x8_flag) readLumaCoeff8x8_CABAC(img, inp, b8); //======= 8x8 trannsform size & CABAC ======== else { //======= Other Modes & CABAC ======== //------------------------------------ for (j=block_y; j < block_y+2; j++) { for (i=block_x; i < block_x+2; i++) { start_scan = IS_NEWINTRA (currMB)? 1 : 0; img->subblock_x = i; // position for coeff_count ctx img->subblock_y = j; // position for coeff_count ctx if (cbp & (1<<b8)) // are there any coeff in current block at all { coef_ctr = start_scan - 1; level = 1; img->is_intra_block = IS_INTRA(currMB); if(!lossless_qpprime) { for(k=start_scan;(k<17) && (level!=0);k++) { /* * make distinction between INTRA and INTER coded * luminance coefficients */ currSE.context = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4); currSE.type = (img->is_intra_block ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER)); #if TRACE sprintf(currSE.tracestring, "Luma sng "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_inter; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) /* leave if len=1 */ { coef_ctr += run+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; currMB->cbp_blk |= (int64)1 << ((j<<2) + i) ; img->cof[i][j][j0][i0]= rshift_rnd_sf((level*InvLevelScale4x4[j0][i0]) << qp_per, 4); } } } else { for(k=start_scan;(k<17) && (level!=0);k++) { /* * make distinction between INTRA and INTER coded * luminance coefficients */ currSE.context = (IS_NEWINTRA(currMB) ? LUMA_16AC : LUMA_4x4); currSE.type = (img->is_intra_block ? (k==0 ? SE_LUM_DC_INTRA : SE_LUM_AC_INTRA) : (k==0 ? SE_LUM_DC_INTER : SE_LUM_AC_INTER)); #if TRACE sprintf(currSE.tracestring, "Luma sng "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_inter; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) /* leave if len=1 */ { coef_ctr += run+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; currMB->cbp_blk |= (int64)1 << ((j<<2) + i) ; img->cof[i][j][j0][i0]= level; } } } } } } } } } } if (dec_picture->chroma_format_idc != YUV400) { for (j=4;j<(4+img->num_blk8x8_uv);j++) // reset all chroma coeffs before read for (i=0;i<4;i++) memset(&img->cof[i][j][0][0], 0, 16 * sizeof(int)); m2 = img->mb_x * 2; jg2 = img->mb_y * 2; qp_const_uv[0] = 1<<(3-qp_per_uv[0]); qp_const_uv[1] = 1<<(3-qp_per_uv[1]); //========================== CHROMA DC ============================ //----------------------------------------------------------------- // chroma DC coeff if(cbp>15) { for (ll=0;ll<3;ll+=2) { uv = ll>>1; if (dec_picture->chroma_format_idc == YUV420) { int (*InvLevelScale4x4Chroma)[4] = intra ? InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]] : InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]]; //===================== CHROMA DC YUV420 ====================== memset(&img->cofu[0], 0, 4 *sizeof(int)); if (active_pps->entropy_coding_mode_flag == UVLC) { readCoeff4x4_CAVLC(img, inp, CHROMA_DC, 0, 0, levarr, runarr, &numcoeff); coef_ctr=-1; level=1; for(k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { currMB->cbp_blk |= 0xf0000 << (ll<<1) ; coef_ctr=coef_ctr+runarr[k]+1; img->cofu[coef_ctr]=levarr[k]; } } } else { coef_ctr=-1; level=1; for(k=0;(k<(img->num_cdc_coeff+1))&&(level!=0);k++) { currSE.context = CHROMA_DC; currSE.type = (IS_INTRA(currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER); img->is_intra_block = IS_INTRA(currMB); img->is_v_block = ll; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "2x2 DC Chroma "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_c2x2; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) { currMB->cbp_blk |= 0xf0000 << (ll<<1) ; coef_ctr=coef_ctr+run+1; // Bug: img->cofu has only 4 entries, hence coef_ctr MUST be <4 (which is // caught by the assert(). If it is bigger than 4, it starts patching the // img->predmode pointer, which leads to bugs later on. // // This assert() should be left in the code, because it captures a very likely // bug early when testing in error prone environments (or when testing NAL // functionality). assert (coef_ctr < img->num_cdc_coeff); img->cofu[coef_ctr]=level; } } } if (smb // check to see if MB type is SPred or SIntra4x4 || lossless_qpprime) { img->cof[0+ll][4][0][0]=img->cofu[0]; img->cof[1+ll][4][0][0]=img->cofu[1]; img->cof[0+ll][5][0][0]=img->cofu[2]; img->cof[1+ll][5][0][0]=img->cofu[3]; } else { temp[0]=(img->cofu[0]+img->cofu[1]+img->cofu[2]+img->cofu[3]); temp[1]=(img->cofu[0]-img->cofu[1]+img->cofu[2]-img->cofu[3]); temp[2]=(img->cofu[0]+img->cofu[1]-img->cofu[2]-img->cofu[3]); temp[3]=(img->cofu[0]-img->cofu[1]-img->cofu[2]+img->cofu[3]); for (i=0;i<img->num_cdc_coeff;i++) { if(qp_per_uv[uv]<5) { temp[i]=(temp[i]*InvLevelScale4x4Chroma[0][0])>>(5-qp_per_uv[uv]); } else { temp[i]=(temp[i]*InvLevelScale4x4Chroma[0][0])<<(qp_per_uv[uv]-5); } } img->cof[0+ll][4][0][0]=temp[0]; img->cof[1+ll][4][0][0]=temp[1]; img->cof[0+ll][5][0][0]=temp[2]; img->cof[1+ll][5][0][0]=temp[3]; } } else if (dec_picture->chroma_format_idc == YUV422) { int i,j,j1; int uv_idx = ll; int m3[2][4] = {{0,0,0,0},{0,0,0,0}}; int m4[2][4] = {{0,0,0,0},{0,0,0,0}}; int qp_per_uv_dc = (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale)/6; //for YUV422 only int qp_rem_uv_dc = (currMB->qpc[uv] + 3 + img->bitdepth_chroma_qp_scale)%6; //for YUV422 only //===================== CHROMA DC YUV422 ====================== if (active_pps->entropy_coding_mode_flag == UVLC) { readCoeff4x4_CAVLC(img, inp, CHROMA_DC, 0, 0, levarr, runarr, &numcoeff); coef_ctr=-1; level=1; for(k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2); coef_ctr=coef_ctr+runarr[k]+1; i0 = SCAN_YUV422[coef_ctr][0]; j0 = SCAN_YUV422[coef_ctr][1]; m3[i0][j0]=levarr[k]; } } } else { coef_ctr=-1; level=1; for(k=0;(k<9)&&(level!=0);k++) { currSE.context = CHROMA_DC_2x4; currSE.type = (IS_INTRA(currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER); img->is_intra_block = IS_INTRA(currMB); img->is_v_block = ll; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "2x4 DC Chroma "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_c2x2; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) { currMB->cbp_blk |= ((int64)0xff0000) << (ll<<2) ; coef_ctr=coef_ctr+run+1; assert (coef_ctr < img->num_cdc_coeff); i0=SCAN_YUV422[coef_ctr][0]; j0=SCAN_YUV422[coef_ctr][1]; m3[i0][j0]=level; } } } // inverse CHROMA DC YUV422 transform // horizontal if(!lossless_qpprime) { m4[0][0] = m3[0][0] + m3[1][0]; m4[0][1] = m3[0][1] + m3[1][1]; m4[0][2] = m3[0][2] + m3[1][2]; m4[0][3] = m3[0][3] + m3[1][3]; m4[1][0] = m3[0][0] - m3[1][0]; m4[1][1] = m3[0][1] - m3[1][1]; m4[1][2] = m3[0][2] - m3[1][2]; m4[1][3] = m3[0][3] - m3[1][3]; } else { for(i=0;i<2;i++) for(j=0;j<4;j++) img->cof[i+uv_idx][j+4][0][0]=m3[i][j]; } // vertical for (i=0;i<2 && !lossless_qpprime;i++) { int (*imgcof)[4][4] = img->cof[i+uv_idx]; for (j=0; j < 4;j++) //TODO: remove m5 with m4 m5[j]=m4[i][j]; m6[0]=m5[0]+m5[2]; m6[1]=m5[0]-m5[2]; m6[2]=m5[1]-m5[3]; m6[3]=m5[1]+m5[3]; for (j=0;j<2;j++) { j1=3-j; if(qp_per_uv_dc<4) { if(intra == 1) { imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2; imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2; } else { imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2; imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0]+(1<<(3-qp_per_uv_dc)))>>(4-qp_per_uv_dc))+2)>>2; } } else { if(intra == 1) { imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2; imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2; } else { imgcof[j +4][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2; imgcof[j1+4][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv_dc][0][0])<<(qp_per_uv_dc-4))+2)>>2; } } }//for (j=0;j<2;j++) }//for (i=0;i<2;i++) }//else if (dec_picture->chroma_format_idc == YUV422) else { //===================== CHROMA DC YUV444 ====================== int i,j,i1,j1; int uv_idx = 4 + (ll<<1); if (active_pps->entropy_coding_mode_flag == UVLC) { readCoeff4x4_CAVLC(img, inp, CHROMA_DC, 0, 0, levarr, runarr, &numcoeff); coef_ctr=-1; level=1; for(k = 0; k < numcoeff; k++) { if (levarr[k] != 0) { currMB->cbp_blk |= ((int64)0xffff0000) << (ll<<3) ; coef_ctr=coef_ctr+runarr[k]+1; i0=SNGL_SCAN[coef_ctr][0]; j0=SNGL_SCAN[coef_ctr][1]; img->cof[i0][j0+uv_idx][0][0]=levarr[k]; } } } else { coef_ctr=-1; level=1; for(k=0;(k<17)&&(level!=0);k++) { currSE.context = CHROMA_DC_4x4; currSE.type = (IS_INTRA(currMB) ? SE_CHR_DC_INTRA : SE_CHR_DC_INTER); img->is_intra_block = IS_INTRA(currMB); img->is_v_block = ll; #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "DC Chroma "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_c2x2; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) { currMB->cbp_blk |= ((int64)0xffff0000) << (ll<<3) ; coef_ctr=coef_ctr+run+1; assert (coef_ctr < img->num_cdc_coeff); i0=SNGL_SCAN[coef_ctr][0]; j0=SNGL_SCAN[coef_ctr][1]; img->cof[i0][j0+uv_idx][0][0]=level; } } } // inverse CHROMA DC YUV444 transform // horizontal for (j=uv_idx; (j < 4+uv_idx) && !lossless_qpprime;j++) { for (i=0;i<4;i++) m5[i]=img->cof[i][j][0][0]; m6[0]=m5[0]+m5[2]; m6[1]=m5[0]-m5[2]; m6[2]=m5[1]-m5[3]; m6[3]=m5[1]+m5[3]; for (i=0;i<2;i++) { i1=3-i; img->cof[i][j][0][0]= m6[i]+m6[i1]; img->cof[i1][j][0][0]=m6[i]-m6[i1]; } } // vertical for (i=0;i<4 && !lossless_qpprime;i++) { for (j=0; j < 4;j++) m5[j]=img->cof[i][j+uv_idx][0][0]; m6[0]=m5[0]+m5[2]; m6[1]=m5[0]-m5[2]; m6[2]=m5[1]-m5[3]; m6[3]=m5[1]+m5[3]; for (j=0;j<2;j++) { j1=3-j; if(qp_per_uv[uv]<4) { if(intra == 1) { img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2; img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2; } else { img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2; img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0]+(1<<(3-qp_per_uv[uv])))>>(4-qp_per_uv[uv]))+2)>>2; } } else { if(intra == 1) { img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2; img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Intra[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2; } else { img->cof[i][j +uv_idx][0][0]=((((m6[j]+m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2; img->cof[i][j1+uv_idx][0][0]=((((m6[j]-m6[j1])*InvLevelScale4x4Chroma_Inter[uv][qp_rem_uv[uv]][0][0])<<(qp_per_uv[uv]-4))+2)>>2; } } } }//for (i=0;i<4;i++) }//else (dec_picture->chroma_format_idc == YUV444) }//for (ll=0;ll<3;ll+=2) } // chroma AC coeff, all zero fram start_scan if (cbp<=31) for (i=0; i < 4; i++) memset(&img->nz_coeff [img->current_mb_nr ][i][4], 0, img->num_blk8x8_uv * sizeof(int)); //========================== CHROMA AC ============================ //----------------------------------------------------------------- // chroma AC coeff, all zero fram start_scan if (cbp>31) { for (b8=0; b8 < img->num_blk8x8_uv; b8++) { int uvc = (b8 > ((img->num_blk8x8_uv>>1) - 1 )); int (*InvLevelScale4x4Chroma)[4] = intra ? InvLevelScale4x4Chroma_Intra[uvc][qp_rem_uv[uvc]] : InvLevelScale4x4Chroma_Inter[uvc][qp_rem_uv[uvc]]; img->is_v_block = uv = uvc; for (b4=0; b4 < 4; b4++) { i = cofuv_blk_x[yuv][b8][b4]; j = cofuv_blk_y[yuv][b8][b4]; if (active_pps->entropy_coding_mode_flag == UVLC) { readCoeff4x4_CAVLC(img, inp, CHROMA_AC, i, j, levarr, runarr, &numcoeff); coef_ctr=0; level=1; if(!lossless_qpprime) { for(k = 0; k < numcoeff;k++) { if (levarr[k] != 0) { currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4]; coef_ctr=coef_ctr+runarr[k]+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; img->cof[i][j][j0][i0] = rshift_rnd_sf((levarr[k]*InvLevelScale4x4Chroma[j0][i0])<<qp_per_uv[uv], 4); } } } else { for(k = 0; k < numcoeff;k++) { if (levarr[k] != 0) { currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4]; coef_ctr=coef_ctr+runarr[k]+1; i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; img->cof[i][j][j0][i0]=levarr[k]; } } } } else { coef_ctr=0; level=1; img->subblock_y = subblk_offset_y[yuv][b8][b4]>>2; img->subblock_x = subblk_offset_x[yuv][b8][b4]>>2; currSE.context = CHROMA_AC; currSE.type = (IS_INTRA(currMB) ? SE_CHR_AC_INTRA : SE_CHR_AC_INTER); img->is_intra_block = IS_INTRA(currMB); if(!lossless_qpprime) { for(k=0;(k<16)&&(level!=0);k++) { #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_inter; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) { currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4]; coef_ctr += (run + 1); i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; img->cof[i][j][j0][i0] = rshift_rnd_sf((level*InvLevelScale4x4Chroma[j0][i0])<<qp_per_uv[uv], 4); } } //for(k=0;(k<16)&&(level!=0);k++) } else { for(k=0;(k<16)&&(level!=0);k++) { #if TRACE snprintf(currSE.tracestring, TRACESTRING_SIZE, "AC Chroma "); #endif dP = &(currSlice->partArr[partMap[currSE.type]]); if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_levrun_inter; else currSE.reading = readRunLevel_CABAC; dP->readSyntaxElement(&currSE,img,dP); level = currSE.value1; run = currSE.value2; len = currSE.len; if (level != 0) { currMB->cbp_blk |= ((int64)1) << cbp_blk_chroma[b8][b4]; coef_ctr += (run + 1); i0=pos_scan4x4[coef_ctr][0]; j0=pos_scan4x4[coef_ctr][1]; img->cof[i][j][j0][i0]=level; } } //for(k=0;(k<16)&&(level!=0);k++) } } //else / if (active_pps->entropy_coding_mode_flag == UVLC) } //for (b4=0; b4 < 4; b4++) } //for (b8=0; b8 < img->num_blk8x8_uv; b8++) } //if (cbp>31) } //if (dec_picture->chroma_format_idc != YUV400) } /*! ************************************************************************ * \brief * Copy IPCM coefficients to decoded picture buffer and set parameters for this MB * (for IPCM CABAC and IPCM CAVLC 28/11/2003) * * \author * Dong Wang <Dong.Wang@bristol.ac.uk> ************************************************************************ */ void decode_ipcm_mb(struct img_par *img) { int i,j; Macroblock *currMb = &img->mb_data[img->current_mb_nr]; //Copy coefficients to decoded picture buffer //IPCM coefficients are stored in img->cof which is set in function readIPCMcoeffsFromNAL() for(i=0;i<16;i++) for(j=0;j<16;j++) dec_picture->imgY[img->pix_y+i][img->pix_x+j]=img->cof[(i>>2)][(j>>2)][i & 0x03][j & 0x03]; if (dec_picture->chroma_format_idc != YUV400) { for(i=0;i<img->mb_cr_size_y;i++) for(j=0;j<img->mb_cr_size_x;j++) dec_picture->imgUV[0][img->pix_c_y+i][img->pix_c_x+j]=img->cof[(i>>2) ][(j>>2)+4][i & 0x03][j & 0x03]; for(i=0;i<img->mb_cr_size_y;i++) for(j=0;j<img->mb_cr_size_x;j++) dec_picture->imgUV[1][img->pix_c_y+i][img->pix_c_x+j]=img->cof[(i>>2)+2][(j>>2)+4][i & 0x03][j & 0x03]; } // for deblocking filter currMb->qp=0; set_chroma_qp(currMb); // for CAVLC: Set the nz_coeff to 16. // These parameters are to be used in CAVLC decoding of neighbour blocks for(i=0;i<4;i++) for (j=0;j<(4 + img->num_blk8x8_uv);j++) img->nz_coeff[img->current_mb_nr][i][j]=16; // for CABAC decoding of MB skip flag currMb->skip_flag = 0; //for deblocking filter CABAC currMb->cbp_blk=0xFFFF; //For CABAC decoding of Dquant last_dquant=0; } /*! ************************************************************************ * \brief * decode one macroblock ************************************************************************ */ int decode_one_macroblock(struct img_par *img,struct inp_par *inp) { int tmp_block[BLOCK_SIZE][BLOCK_SIZE]; int tmp_blockbw[BLOCK_SIZE][BLOCK_SIZE]; int i=0,j=0,k,l,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0; int uv, hv; int vec1_x=0,vec1_y=0,vec2_x=0,vec2_y=0; int ioff,joff; int block8x8; // needed for ABT int bw_pred=0, fw_pred=0, pred, ifx; int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0; int mv_mul, f1_x, f1_y, f2_x, f2_y, f3, f4; static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15}; Macroblock *currMB = &img->mb_data[img->current_mb_nr]; short ref_idx, l0_refframe=-1, l1_refframe=-1; int mv_mode, pred_dir, intra_prediction; // = currMB->ref_frame; short l0_ref_idx=-1, l1_ref_idx=-1; int alpha_l0, alpha_l1, wp_offset; short *** mv_array, ***l0_mv_array, ***l1_mv_array; int mv_scale; int mb_nr = img->current_mb_nr; int smb = ((img->type==SP_SLICE) && IS_INTER (currMB)) || (img->type == SI_SLICE && currMB->mb_type == SI4MB); int list_offset; int max_y_cr; StorablePicture **list; int jf; char l0_rFrame = -1, l1_rFrame = -1; short pmvl0[2]={0,0}, pmvl1[2]={0,0}; int direct_pdir=-1; int curr_mb_field = ((img->MbaffFrameFlag)&&(currMB->mb_field)); byte ** moving_block; short **** co_located_mv; char *** co_located_ref_idx; int64 *** co_located_ref_id; int need_4x4_transform = (!currMB->luma_transform_size_8x8_flag); int b8, b4; int uv_shift; int yuv = dec_picture->chroma_format_idc - 1; if(img->type==SP_SLICE && currMB->mb_type!=I16MB) smb=1;// modif ES added if(currMB->mb_type==IPCM) { //copy readed data into imgY and set parameters decode_ipcm_mb(img); return 0; } ////////////////////////// // find out the correct list offsets if (curr_mb_field) { if(mb_nr&0x01) { list_offset = 4; // top field mb moving_block = Co_located->bottom_moving_block; co_located_mv = Co_located->bottom_mv; co_located_ref_idx = Co_located->bottom_ref_idx; co_located_ref_id = Co_located->bottom_ref_pic_id; } else { list_offset = 2; // bottom field mb moving_block = Co_located->top_moving_block; co_located_mv = Co_located->top_mv; co_located_ref_idx = Co_located->top_ref_idx; co_located_ref_id = Co_located->top_ref_pic_id; } max_y_cr = (dec_picture->size_y_cr>>1)-1; } else { list_offset = 0; // no mb aff or frame mb moving_block = Co_located->moving_block; co_located_mv = Co_located->mv; co_located_ref_idx = Co_located->ref_idx; co_located_ref_id = Co_located->ref_pic_id; max_y_cr = dec_picture->size_y_cr-1; } if (!img->MbaffFrameFlag) { for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++) { for(k = 0; k < listXsize[l]; k++) { listX[l][k]->chroma_vector_adjustment= 0; if(img->structure == TOP_FIELD && img->structure != listX[l][k]->structure) listX[l][k]->chroma_vector_adjustment = -2; if(img->structure == BOTTOM_FIELD && img->structure != listX[l][k]->structure) listX[l][k]->chroma_vector_adjustment = 2; } } } else { if (curr_mb_field) { for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++) { for(k = 0; k < listXsize[l]; k++) { listX[l][k]->chroma_vector_adjustment= 0; if(img->current_mb_nr % 2 == 0 && listX[l][k]->structure == BOTTOM_FIELD) listX[l][k]->chroma_vector_adjustment = -2; if(img->current_mb_nr % 2 == 1 && listX[l][k]->structure == TOP_FIELD) listX[l][k]->chroma_vector_adjustment = 2; } } } else { for (l = LIST_0 + list_offset; l <= (LIST_1 + list_offset); l++) { for(k = 0; k < listXsize[l]; k++) { listX[l][k]->chroma_vector_adjustment= 0; } } } } mv_mul=4; // luma decoding ************************************************** // get prediction for INTRA_MB_16x16 if (IS_NEWINTRA (currMB)) { intrapred_luma_16x16(img, currMB->i16mode); } if (img->type==B_SLICE && img->direct_spatial_mv_pred_flag && (IS_DIRECT (currMB) || (IS_P8x8(currMB) && !(currMB->b8mode[0] && currMB->b8mode[1] && currMB->b8mode[2] && currMB->b8mode[3])))) { char l0_rFrameL, l0_rFrameU, l0_rFrameUL, l0_rFrameUR; char l1_rFrameL, l1_rFrameU, l1_rFrameUL, l1_rFrameUR; PixelPos mb_left, mb_up, mb_upleft, mb_upright; getLuma4x4Neighbour(img->current_mb_nr, -1, 0, &mb_left); getLuma4x4Neighbour(img->current_mb_nr, 0, -1, &mb_up); getLuma4x4Neighbour(img->current_mb_nr, 16, -1, &mb_upright); getLuma4x4Neighbour(img->current_mb_nr, -1, -1, &mb_upleft); if (!img->MbaffFrameFlag) { l0_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] : -1; l0_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1; l0_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l0_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL; l1_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1; l1_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1; l1_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l1_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL; } else { if (img->mb_data[img->current_mb_nr].mb_field) { l0_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] * 2: -1; l0_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] * 2: -1; l0_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1; l0_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] * 2: l0_rFrameUL; l1_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] * 2: -1; l1_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] * 2: -1; l1_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] *2: -1; l1_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] * 2: l1_rFrameUL; } else { l0_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x] >> 1 : dec_picture->ref_idx[LIST_0][mb_left.pos_y][mb_left.pos_x]: -1; l0_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] >> 1 : dec_picture->ref_idx[LIST_0][mb_up.pos_y][mb_up.pos_x] : -1; l0_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x]>> 1 : dec_picture->ref_idx[LIST_0][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l0_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] < 0 ? dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] >> 1 : dec_picture->ref_idx[LIST_0][mb_upright.pos_y][mb_upright.pos_x] : l0_rFrameUL; l1_rFrameL = mb_left.available ? img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] >> 1 : dec_picture->ref_idx[LIST_1][mb_left.pos_y][mb_left.pos_x] : -1; l1_rFrameU = mb_up.available ? img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] >> 1 : dec_picture->ref_idx[LIST_1][mb_up.pos_y][mb_up.pos_x] : -1; l1_rFrameUL = mb_upleft.available ? img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] >> 1 : dec_picture->ref_idx[LIST_1][mb_upleft.pos_y][mb_upleft.pos_x] : -1; l1_rFrameUR = mb_upright.available ? img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] < 0 ? dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] >> 1: dec_picture->ref_idx[LIST_1][mb_upright.pos_y][mb_upright.pos_x] : l1_rFrameUL; } } l0_rFrame = (l0_rFrameL >= 0 && l0_rFrameU >= 0) ? imin(l0_rFrameL,l0_rFrameU): imax(l0_rFrameL,l0_rFrameU); l0_rFrame = (l0_rFrame >= 0 && l0_rFrameUR >= 0) ? imin(l0_rFrame,l0_rFrameUR): imax(l0_rFrame,l0_rFrameUR); l1_rFrame = (l1_rFrameL >= 0 && l1_rFrameU >= 0) ? imin(l1_rFrameL,l1_rFrameU): imax(l1_rFrameL,l1_rFrameU); l1_rFrame = (l1_rFrame >= 0 && l1_rFrameUR >= 0) ? imin(l1_rFrame,l1_rFrameUR): imax(l1_rFrame,l1_rFrameUR); if (l0_rFrame >=0) SetMotionVectorPredictor (img, pmvl0, l0_rFrame, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16); if (l1_rFrame >=0) SetMotionVectorPredictor (img, pmvl1, l1_rFrame, LIST_1, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16); } for (block8x8=0; block8x8<4; block8x8++) { if (currMB->b8mode[block8x8] == I8MB) { //=========== 8x8 BLOCK TYPE ============ ioff = 8*(block8x8&0x01); joff = 8*(block8x8>>1); //PREDICTION intrapred8x8(img, block8x8); itrans8x8(img,ioff,joff); // use DCT transform and make 8x8 block m7 from prediction block mpr for(jj=joff;jj<joff + 8;jj++) { for(ii=ioff;ii<ioff + 8;ii++) { dec_picture->imgY[img->pix_y + jj][img->pix_x + ii] = img->m7[jj][ii]; // construct picture from 4x4 blocks } } continue; } for (k = block8x8*4; k < block8x8*4+4; k ++) { i = (decode_block_scan[k] & 3); j = ((decode_block_scan[k] >> 2) & 3); ioff = (i << 2); i4 = img->block_x + i; joff = (j << 2); j4 = img->block_y + j; mv_mode = currMB->b8mode[2*(j>>1)+(i>>1)]; pred_dir = currMB->b8pdir[2*(j>>1)+(i>>1)]; assert (pred_dir<=2); // PREDICTION if (mv_mode==IBLOCK) { //===== INTRA PREDICTION ===== if (intrapred(img,ioff,joff,i4,j4)==SEARCH_SYNC) /* make 4x4 prediction block mpr from given prediction img->mb_mode */ return SEARCH_SYNC; /* bit error */ } else if (!IS_NEWINTRA (currMB)) { if (pred_dir != 2) { //===== FORWARD/BACKWARD PREDICTION ===== l0_refframe = ref_idx = dec_picture->ref_idx[LIST_0 + pred_dir][j4][i4]; mv_array = dec_picture->mv[LIST_0 + pred_dir]; list = listX[0+list_offset+ pred_dir]; vec1_x = i4*4*mv_mul + mv_array[j4][i4][0]; if (!curr_mb_field) { vec1_y = j4 * 4 * mv_mul + mv_array[j4][i4][1]; } else { if ((mb_nr&0x01) == 0) vec1_y = (img->block_y * 2 + joff) * mv_mul + mv_array[j4][i4][1]; else vec1_y = ((img->block_y-4) * 2 + joff)* mv_mul + mv_array[j4][i4][1]; } get_block (ref_idx, list, vec1_x, vec1_y, img, tmp_block); if (img->apply_weights) { if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))|| (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field) { ref_idx >>=1; } alpha_l0 = img->wp_weight[pred_dir][ref_idx][0]; wp_offset = img->wp_offset[pred_dir][l0_refframe>>curr_mb_field][0]; for(jj=0;jj<BLOCK_SIZE;jj++) { int jpos = jj+joff; for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jpos][ii+ioff] = iClip1(img->max_imgpel_value, (rshift_rnd_sf((alpha_l0 * tmp_block[jj][ii]), img->luma_log2_weight_denom) + wp_offset )); } } else { for(jj=0;jj<BLOCK_SIZE;jj++) { int jpos = jj+joff; for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jpos][ii+ioff] = tmp_block[jj][ii]; } } } else { if (mv_mode != 0) { //===== BI-DIRECTIONAL PREDICTION ===== l0_mv_array = dec_picture->mv[LIST_0]; l1_mv_array = dec_picture->mv[LIST_1]; l0_refframe = dec_picture->ref_idx[LIST_0][j4][i4]; l1_refframe = dec_picture->ref_idx[LIST_1][j4][i4]; l0_ref_idx = l0_refframe; l1_ref_idx = l1_refframe; } else { //===== DIRECT PREDICTION ===== l0_mv_array = dec_picture->mv[LIST_0]; l1_mv_array = dec_picture->mv[LIST_1]; l1_refframe = 0; if (img->direct_spatial_mv_pred_flag ) { int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1: img->block_y; int j6 = imgblock_y + j; if (l0_rFrame >=0) { if (!l0_rFrame && ((!moving_block[j6][i4]) && (!listX[1+list_offset][0]->is_long_term))) { dec_picture->mv [LIST_0][j4][i4][0] = 0; dec_picture->mv [LIST_0][j4][i4][1] = 0; dec_picture->ref_idx[LIST_0][j4][i4] = 0; } else { dec_picture->mv [LIST_0][j4][i4][0] = pmvl0[0]; dec_picture->mv [LIST_0][j4][i4][1] = pmvl0[1]; dec_picture->ref_idx[LIST_0][j4][i4] = l0_rFrame; } } else { dec_picture->ref_idx[LIST_0][j4][i4] = -1; dec_picture->mv [LIST_0][j4][i4][0] = 0; dec_picture->mv [LIST_0][j4][i4][1] = 0; } if (l1_rFrame >=0) { if (l1_rFrame==0 && ((!moving_block[j6][i4]) && (!listX[1+list_offset][0]->is_long_term))) { dec_picture->mv [LIST_1][j4][i4][0] = 0; dec_picture->mv [LIST_1][j4][i4][1] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame; } else { dec_picture->mv [LIST_1][j4][i4][0] = pmvl1[0]; dec_picture->mv [LIST_1][j4][i4][1] = pmvl1[1]; dec_picture->ref_idx[LIST_1][j4][i4] = l1_rFrame; } } else { dec_picture->mv [LIST_1][j4][i4][0] = 0; dec_picture->mv [LIST_1][j4][i4][1] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = -1; } if (l0_rFrame < 0 && l1_rFrame < 0) { dec_picture->ref_idx[LIST_0][j4][i4] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = 0; } l0_refframe = (dec_picture->ref_idx[LIST_0][j4][i4]!=-1) ? dec_picture->ref_idx[LIST_0][j4][i4] : 0; l1_refframe = (dec_picture->ref_idx[LIST_1][j4][i4]!=-1) ? dec_picture->ref_idx[LIST_1][j4][i4] : 0; l0_ref_idx = l0_refframe; l1_ref_idx = l1_refframe; if (dec_picture->ref_idx[LIST_1][j4][i4]==-1) direct_pdir = 0; else if (dec_picture->ref_idx[LIST_0][j4][i4]==-1) direct_pdir = 1; else direct_pdir = 2; } else // Temporal Mode { int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr&0x01) ? (img->block_y-4)>>1:img->block_y>>1: img->block_y; int j6= imgblock_y + j; int refList = (co_located_ref_idx[LIST_0][j6][i4]== -1 ? LIST_1 : LIST_0); int ref_idx = co_located_ref_idx[refList][j6][i4]; if(ref_idx==-1) // co-located is intra mode { for(hv=0; hv<2; hv++) { dec_picture->mv [LIST_0][j4][i4][hv]=0; dec_picture->mv [LIST_1][j4][i4][hv]=0; } dec_picture->ref_idx[LIST_0][j4][i4] = 0; dec_picture->ref_idx[LIST_1][j4][i4] = 0; l0_refframe = 0; l0_ref_idx = 0; } else // co-located skip or inter mode { int mapped_idx=0; int iref; { for (iref=0;iref<imin(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++) { if(img->structure==0 && curr_mb_field==0) { // If the current MB is a frame MB and the colocated is from a field picture, // then the co_located_ref_id may have been generated from the wrong value of // frame_poc if it references it's complementary field, so test both POC values if(listX[0][iref]->top_poc*2 == co_located_ref_id[refList][j6][i4] || listX[0][iref]->bottom_poc*2 == co_located_ref_id[refList][j6][i4]) { mapped_idx=iref; break; } else //! invalid index. Default to zero even though this case should not happen mapped_idx=INVALIDINDEX; continue; } if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][j6][i4]) { mapped_idx=iref; break; } else //! invalid index. Default to zero even though this case should not happen { mapped_idx=INVALIDINDEX; } } if (INVALIDINDEX == mapped_idx) { error("temporal direct error\ncolocated block has ref that is unavailable",-1111); } } l0_ref_idx = mapped_idx; mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx]; //! In such case, an array is needed for each different reference. if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term) { dec_picture->mv [LIST_0][j4][i4][0]=co_located_mv[refList][j6][i4][0]; dec_picture->mv [LIST_0][j4][i4][1]=co_located_mv[refList][j6][i4][1]; dec_picture->mv [LIST_1][j4][i4][0]=0; dec_picture->mv [LIST_1][j4][i4][1]=0; } else { dec_picture->mv [LIST_0][j4][i4][0]=(mv_scale * co_located_mv[refList][j6][i4][0] + 128 ) >> 8; dec_picture->mv [LIST_0][j4][i4][1]=(mv_scale * co_located_mv[refList][j6][i4][1] + 128 ) >> 8; dec_picture->mv [LIST_1][j4][i4][0]=dec_picture->mv[LIST_0][j4][i4][0] - co_located_mv[refList][j6][i4][0] ; dec_picture->mv [LIST_1][j4][i4][1]=dec_picture->mv[LIST_0][j4][i4][1] - co_located_mv[refList][j6][i4][1] ; } l0_refframe = dec_picture->ref_idx[LIST_0][j4][i4] = mapped_idx; //listX[1][0]->ref_idx[refList][j4][i4]; l1_refframe = dec_picture->ref_idx[LIST_1][j4][i4] = 0; l0_ref_idx = l0_refframe; l1_ref_idx = l1_refframe; } } // store reference picture ID determined by direct mode dec_picture->ref_pic_id[LIST_0][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][(short)dec_picture->ref_idx[LIST_0][j4][i4]]; dec_picture->ref_pic_id[LIST_1][j4][i4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][(short)dec_picture->ref_idx[LIST_1][j4][i4]]; } if (mv_mode==0 && img->direct_spatial_mv_pred_flag ) { if (dec_picture->ref_idx[LIST_0][j4][i4] >= 0) { vec1_x = i4*4*mv_mul + l0_mv_array[j4][i4][0]; if (!curr_mb_field) { vec1_y = j4*4*mv_mul + l0_mv_array[j4][i4][1]; } else { if ((mb_nr&0x01) == 0) { vec1_y = (img->block_y * 2 + joff) * mv_mul + l0_mv_array[j4][i4][1]; } else { vec1_y = ((img->block_y-4) * 2 + joff)* mv_mul + l0_mv_array[j4][i4][1]; } } get_block(l0_refframe, listX[0+list_offset], vec1_x, vec1_y, img, tmp_block); } if (dec_picture->ref_idx[LIST_1][j4][i4] >= 0) { vec2_x = i4*4*mv_mul + l1_mv_array[j4][i4][0]; if (!curr_mb_field) { vec2_y = j4*4*mv_mul + l1_mv_array[j4][i4][1]; } else { if ((mb_nr&0x01) == 0) { vec2_y = (img->block_y * 2 + joff) * mv_mul + l1_mv_array[j4][i4][1]; } else { vec2_y = ((img->block_y-4) * 2 + joff)* mv_mul + l1_mv_array[j4][i4][1]; } } get_block(l1_refframe, listX[1+list_offset], vec2_x, vec2_y, img, tmp_blockbw); } } else { vec1_x = i4 * 4 * mv_mul + l0_mv_array[j4][i4][0]; vec2_x = i4 * 4 * mv_mul + l1_mv_array[j4][i4][0]; if (!curr_mb_field) { vec1_y = j4 * 4 * mv_mul + l0_mv_array[j4][i4][1]; vec2_y = j4 * 4 * mv_mul + l1_mv_array[j4][i4][1]; } else { if ((mb_nr&0x01) == 0) { vec1_y = (img->block_y * 2 + joff) * mv_mul + l0_mv_array[j4][i4][1]; vec2_y = (img->block_y * 2 + joff) * mv_mul + l1_mv_array[j4][i4][1]; } else { vec1_y = ((img->block_y-4) * 2 + joff)* mv_mul + l0_mv_array[j4][i4][1]; vec2_y = ((img->block_y-4) * 2 + joff)* mv_mul + l1_mv_array[j4][i4][1]; } } get_block(l0_refframe, listX[0+list_offset], vec1_x, vec1_y, img, tmp_block); get_block(l1_refframe, listX[1+list_offset], vec2_x, vec2_y, img, tmp_blockbw); } if (mv_mode==0 && img->direct_spatial_mv_pred_flag && direct_pdir==0) { if (img->apply_weights) { if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))|| (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field) { l0_ref_idx >>=1; } alpha_l0 = img->wp_weight[LIST_0][l0_ref_idx][0]; wp_offset = img->wp_offset[LIST_0][l0_refframe>>curr_mb_field][0]; for(jj=0;jj<BLOCK_SIZE;jj++) for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jj+joff][ii+ioff] = iClip1(img->max_imgpel_value, (rshift_rnd_sf((alpha_l0 * tmp_block[jj][ii]), img->luma_log2_weight_denom) + wp_offset)); } else { for(jj=0;jj<BLOCK_SIZE;jj++) for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jj+joff][ii+ioff] = tmp_block[jj][ii]; } } else if (mv_mode==0 && img->direct_spatial_mv_pred_flag && direct_pdir==1) { if (img->apply_weights) { if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))|| (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field) { l1_ref_idx >>=1; } alpha_l1 = img->wp_weight[LIST_1][l1_ref_idx][0]; wp_offset = img->wp_offset[LIST_1][l1_refframe>>curr_mb_field][0]; for(jj=0;jj<BLOCK_SIZE;jj++) for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jj+joff][ii+ioff] = iClip1(img->max_imgpel_value, (rshift_rnd_sf((alpha_l1 * tmp_blockbw[jj][ii]), img->luma_log2_weight_denom) + wp_offset)); } else { for(jj=0;jj<BLOCK_SIZE;jj++) for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jj+joff][ii+ioff] = tmp_blockbw[jj][ii]; } } else if(img->apply_weights) { int wt_list_offset = (active_pps->weighted_bipred_idc==2)?list_offset:0; if (mv_mode==0 && img->direct_spatial_mv_pred_flag==0 )l1_ref_idx=0; //temporal direct if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))|| (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field) { l0_ref_idx >>=1; l1_ref_idx >>=1; } alpha_l0 = img->wbp_weight[LIST_0 + wt_list_offset][l0_ref_idx][l1_ref_idx][0]; alpha_l1 = img->wbp_weight[LIST_1 + wt_list_offset][l0_ref_idx][l1_ref_idx][0]; wp_offset = ((img->wp_offset [LIST_0 + wt_list_offset][l0_ref_idx][0] + img->wp_offset[LIST_1 + wt_list_offset][l1_ref_idx][0] + 1) >>1); for(ii=0;ii<BLOCK_SIZE;ii++) for(jj=0;jj<BLOCK_SIZE;jj++) img->mpr[jj+joff][ii+ioff] = (int)iClip1(img->max_imgpel_value, (rshift_rnd_sf((alpha_l0 * tmp_block[jj][ii] + alpha_l1 * tmp_blockbw[jj][ii]), (img->luma_log2_weight_denom + 1)) + wp_offset)); } else { for(jj=0;jj<BLOCK_SIZE;jj++) for(ii=0;ii<BLOCK_SIZE;ii++) img->mpr[jj+joff][ii+ioff] = (tmp_block[jj][ii]+tmp_blockbw[jj][ii]+1)>>1; } } } // =============== 4x4 itrans ================ // ------------------------------------------- if (smb && mv_mode!=IBLOCK) { if(!IS_NEWINTRA (currMB))// modif ES added itrans_sp(img,ioff,joff,i,j); else //modif ES added itrans(img,ioff,joff,i,j,0); // modif ES added } else { if(need_4x4_transform) { if(img->type==SP_SLICE && currMB->mb_type != I16MB) // ES added itrans_sp(img,ioff,joff,i,j);//ES added else itrans (img,ioff,joff,i,j, 0); // use DCT transform and make 4x4 block m7 from prediction block mpr } } if(need_4x4_transform) { int j_pos = j4 * BLOCK_SIZE; int i_pos = i4 * BLOCK_SIZE; for(jj=0;jj<BLOCK_SIZE;jj++) { for(ii=0;ii<BLOCK_SIZE;ii++) { dec_picture->imgY[j_pos + jj][i_pos + ii]=img->m7[jj][ii]; // construct picture from 4x4 blocks } } }// if(need_4x4_transform) } if(!need_4x4_transform) { // =============== 8x8 itrans ================ // ------------------------------------------- ioff = 8*(block8x8&0x01); joff = 8*(block8x8>>1); itrans8x8(img,ioff,joff); // use DCT transform and make 8x8 block m7 from prediction block mpr for(jj=joff;jj<joff + 8;jj++) { for(ii=ioff;ii<ioff + 8;ii++) { dec_picture->imgY[img->pix_y + jj][img->pix_x + ii]=img->m7[jj][ii]; // construct picture from 4x4 blocks } } } } if (dec_picture->chroma_format_idc != YUV400) { // chroma decoding ******************************************************* f1_x = 64/img->mb_cr_size_x; f2_x = f1_x-1; f1_y = 64/img->mb_cr_size_y; f2_y = f1_y-1; f3 = f1_x*f1_y; f4 = f3>>1; for(uv=0;uv<2;uv++) { uv_shift = uv*(img->num_blk8x8_uv>>1); intra_prediction = IS_INTRA (currMB); if (intra_prediction) { intrapred_chroma(img, uv); } for (b8=0;b8<(img->num_blk8x8_uv>>1);b8++) { for(b4=0;b4<4;b4++) { joff = subblk_offset_y[yuv][b8][b4]; j4 = img->pix_c_y+joff; ioff = subblk_offset_x[yuv][b8][b4]; i4 = img->pix_c_x+ioff; mv_mode = currMB->b8mode[block8x8_idx[yuv][b8][b4]]; pred_dir = currMB->b8pdir[block8x8_idx[yuv][b8][b4]]; assert (pred_dir<=2); if (!intra_prediction) { if (pred_dir != 2) { int jpos; //--- FORWARD/BACKWARD PREDICTION --- mv_array = dec_picture->mv[LIST_0 + pred_dir]; list = listX[0+list_offset+pred_dir]; for(jj=0;jj<4;jj++) { jf=(j4+jj)/(img->mb_size_blk[1][1]); // jf = Subblock_y-coordinate if (!curr_mb_field) jpos=(j4+jj)*f1_y; else { if ((mb_nr&0x01) == 0) jpos=(((img->pix_c_y)>>1) + jj + joff)*f1_y; else jpos=(((img->pix_c_y-img->mb_cr_size_y)>>1) + jj + joff)*f1_y; } for(ii=0;ii<4;ii++) { ifx=(i4+ii)/(img->mb_size_blk[1][0]); // ifx = Subblock_x-coordinate l0_refframe = ref_idx = dec_picture->ref_idx[LIST_0+pred_dir][jf][ifx]; i1=(i4+ii)*f1_x+mv_array[jf][ifx][0]; j1 = jpos+mv_array[jf][ifx][1]; if (active_sps->chroma_format_idc == 1) j1 += list[ref_idx]->chroma_vector_adjustment; ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x); jj0 = iClip3 (0, max_y_cr, j1/f1_y); ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x)); jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y)); if1=(i1 & f2_x); jf1=(j1 & f2_y); if0=f1_x-if1; jf0=f1_y-jf1; if (img->apply_weights) { imgpel **curUV = list[ref_idx]->imgUV[uv]; pred = (if0*jf0*curUV[jj0][ii0] + if1*jf0*curUV[jj0][ii1]+ if0*jf1*curUV[jj1][ii0] + if1*jf1*curUV[jj1][ii1]+f4)/f3; if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))|| (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field) { ref_idx >>=1; } img->mpr[jj+joff][ii+ioff] = iClip1(img->max_imgpel_value_uv, (((img->wp_weight[pred_dir][ref_idx][uv+1] * pred + img->wp_round_chroma)>>img->chroma_log2_weight_denom) + img->wp_offset[pred_dir][ref_idx][uv+1])); } else { imgpel **curUV = list[ref_idx]->imgUV[uv]; img->mpr[jj+joff][ii+ioff]=( if0*jf0*curUV[jj0][ii0] + if1*jf0*curUV[jj0][ii1]+ if0*jf1*curUV[jj1][ii0] + if1*jf1*curUV[jj1][ii1]+f4)/f3; } } } } else { l0_mv_array = dec_picture->mv[LIST_0]; l1_mv_array = dec_picture->mv[LIST_1]; for(jj=0;jj<4;jj++) { int jpos; jf=(j4+jj)/(img->mb_size_blk[1][1]); // jf = Subblock_y-coordinate if (!curr_mb_field) { jpos=(j4+jj)*f1_y; } else { if ((mb_nr&0x01) == 0) jpos=(((img->pix_c_y)>>1) + jj + joff)*f1_y; else jpos=(((img->pix_c_y-img->mb_cr_size_y)>>1) + jj + joff)*f1_y; } for(ii=0;ii<4;ii++) { ifx=(i4+ii)/(img->mb_size_blk[1][0]); // ifx = Subblock_x-coordinate direct_pdir = 2; if (mv_mode == 0 && img->direct_spatial_mv_pred_flag) { //===== DIRECT PREDICTION ===== if (dec_picture->ref_idx[LIST_0][2*(jf>>1)][(ifx>>1)*2]!=-1) { l0_refframe = dec_picture->ref_idx[LIST_0][2*(jf>>1)][(ifx>>1)*2]; l0_ref_idx = l0_refframe; } if (dec_picture->ref_idx[LIST_1][2*(jf>>1)][(ifx>>1)*2]!=-1) { l1_refframe = dec_picture->ref_idx[LIST_1][2*(jf>>1)][(ifx>>1)*2]; l1_ref_idx = l1_refframe; } if (dec_picture->ref_idx[LIST_1][2*(jf>>1)][(ifx>>1)*2]==-1) direct_pdir = 0; else if (dec_picture->ref_idx[LIST_0][2*(jf>>1)][(ifx>>1)*2]==-1) direct_pdir = 1; if (direct_pdir == 0 || direct_pdir == 2) { i1=(i4+ii)*f1_x+l0_mv_array[jf][ifx][0]; j1=jpos+l0_mv_array[jf][ifx][1]; if (active_sps->chroma_format_idc == 1) j1 += listX[0+list_offset][l0_refframe]->chroma_vector_adjustment; ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x); jj0 = iClip3 (0, max_y_cr, j1/f1_y); ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x)); jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y)); if1=(i1 & f2_x); jf1=(j1 & f2_y); if0=f1_x-if1; jf0=f1_y-jf1; { imgpel **curUV = listX[LIST_0 + list_offset][l0_refframe]->imgUV[uv]; fw_pred=(if0*jf0 * curUV[jj0][ii0]+ if1*jf0 * curUV[jj0][ii1]+ if0*jf1 * curUV[jj1][ii0]+ if1*jf1 * curUV[jj1][ii1]+f4)/f3; } } if (direct_pdir == 1 || direct_pdir == 2) { i1=(i4+ii)*f1_x+l1_mv_array[jf][ifx][0]; j1=jpos+l1_mv_array[jf][ifx][1]; if (active_sps->chroma_format_idc == 1) j1 += listX[1+list_offset][l1_refframe]->chroma_vector_adjustment; ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x); jj0 = iClip3 (0, max_y_cr, j1/f1_y); ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x)); jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y)); if1=(i1 & f2_x); jf1=(j1 & f2_y); if0=f1_x-if1; jf0=f1_y-jf1; { imgpel **curUV = listX[1+list_offset][l1_refframe]->imgUV[uv]; bw_pred=(if0*jf0*curUV[jj0][ii0] + if1*jf0*curUV[jj0][ii1]+ if0*jf1*curUV[jj1][ii0] + if1*jf1*curUV[jj1][ii1]+f4)/f3; } } } else { //===== BI-DIRECTIONAL PREDICTION ===== l0_refframe = dec_picture->ref_idx[LIST_0][jf][ifx]; l1_refframe = dec_picture->ref_idx[LIST_1][jf][ifx]; l0_ref_idx = l0_refframe; l1_ref_idx = l1_refframe; i1=(i4+ii)*f1_x+l0_mv_array[jf][ifx][0]; j1=jpos+l0_mv_array[jf][ifx][1]; if (active_sps->chroma_format_idc == 1) j1 += listX[0+list_offset][l0_refframe]->chroma_vector_adjustment; ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x); jj0 = iClip3 (0, max_y_cr, j1/f1_y); ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x)); jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y)); if1=(i1 & f2_x); jf1=(j1 & f2_y); if0=f1_x-if1; jf0=f1_y-jf1; { imgpel **curUV = listX[0+list_offset][l0_refframe]->imgUV[uv]; fw_pred=(if0*jf0*curUV[jj0][ii0]+ if1*jf0*curUV[jj0][ii1]+ if0*jf1*curUV[jj1][ii0]+ if1*jf1*curUV[jj1][ii1]+f4)/f3; } i1=(i4+ii)*f1_x+l1_mv_array[jf][ifx][0]; j1=jpos+l1_mv_array[jf][ifx][1]; if (active_sps->chroma_format_idc == 1) j1 += listX[1+list_offset][l1_refframe]->chroma_vector_adjustment; ii0 = iClip3 (0, img->width_cr_m1, i1/f1_x); jj0 = iClip3 (0, max_y_cr, j1/f1_y); ii1 = iClip3 (0, img->width_cr_m1, ((i1+f2_x)/f1_x)); jj1 = iClip3 (0, max_y_cr, ((j1+f2_y)/f1_y)); if1=(i1 & f2_x); jf1=(j1 & f2_y); if0=f1_x-if1; jf0=f1_y-jf1; { imgpel **curUV = listX[1+list_offset][l1_refframe]->imgUV[uv]; bw_pred=(if0*jf0*curUV[jj0][ii0]+ if1*jf0*curUV[jj0][ii1]+ if0*jf1*curUV[jj1][ii0]+if1*jf1*curUV[jj1][ii1]+f4)/f3; } } if (img->apply_weights) { if (((active_pps->weighted_pred_flag&&(img->type==P_SLICE|| img->type == SP_SLICE))|| (active_pps->weighted_bipred_idc==1 && (img->type==B_SLICE))) && curr_mb_field) { l0_ref_idx >>=1; l1_ref_idx >>=1; } if (img->direct_spatial_mv_pred_flag && direct_pdir==1) { img->mpr[jj+joff][ii+ioff]= iClip1(img->max_imgpel_value_uv, (((img->wp_weight[1][l1_ref_idx][uv+1] * bw_pred + img->wp_round_chroma)>>img->chroma_log2_weight_denom) + img->wp_offset[1][l1_refframe>>curr_mb_field][uv+1])); // Replaced with integer only operations } else if (img->direct_spatial_mv_pred_flag && direct_pdir==0) { img->mpr[jj+joff][ii+ioff]=iClip1(img->max_imgpel_value_uv, (((img->wp_weight[0][l0_ref_idx][uv+1] * fw_pred + img->wp_round_chroma)>>img->chroma_log2_weight_denom) + img->wp_offset[0][l0_refframe>>curr_mb_field][uv+1])); // Replaced with integer only operations } else { int wt_list_offset = (active_pps->weighted_bipred_idc==2)?list_offset:0; alpha_l0 = img->wbp_weight[0+wt_list_offset][l0_ref_idx][l1_ref_idx][uv+1]; alpha_l1 = img->wbp_weight[1+wt_list_offset][l0_ref_idx][l1_ref_idx][uv+1]; img->mpr[jj+joff][ii+ioff]= iClip1(img->max_imgpel_value_uv, (((alpha_l0 * fw_pred + alpha_l1 * bw_pred + (1<<img->chroma_log2_weight_denom)) >> (img->chroma_log2_weight_denom + 1))+ ((img->wp_offset[wt_list_offset + 0][l0_ref_idx][uv+1] + img->wp_offset[wt_list_offset + 1][l1_ref_idx][uv+1] + 1)>>1))); } } else { if (img->direct_spatial_mv_pred_flag && direct_pdir==1) { img->mpr[jj+joff][ii+ioff]=bw_pred; } else if (img->direct_spatial_mv_pred_flag && direct_pdir==0) { img->mpr[jj+joff][ii+ioff]=fw_pred; } else { img->mpr[jj+joff][ii+ioff]=(fw_pred + bw_pred + 1 )>>1; } } } } } } //if (!intra_prediction) if (!smb) { imgpel **curUV = dec_picture->imgUV[uv]; itrans(img,ioff,joff, cofuv_blk_x[yuv][b8+uv_shift][b4], cofuv_blk_y[yuv][b8+uv_shift][b4], 1); for(jj=0;jj<4;jj++) for(ii=0;ii<4;ii++) { curUV[j4+jj][i4+ii]=img->m7[jj][ii]; } } } } if(smb) { imgpel **curUV = dec_picture->imgUV[uv]; itrans_sp_chroma(img,2*uv); 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; itrans(img,ioff,joff,2*uv+i,j, 1); for(jj=0;jj<4;jj++) for(ii=0;ii<4;ii++) { curUV[j4+jj][i4+ii]=img->m7[jj][ii]; } } } } } } return 0; }