char sub_mb_P_cabac ( int *dct_allowed, CABACContext *c, unsigned char *state, SLICE *slice, RESIDU *Current_residu, short mv_cache_l0[][2], short *ref_cache_l0, short mvl0_cache[][2], short *refl0_cache) { int mbPartIdx ; int subMbPartIdx ; char RefIdxL0[4] = {0, 0, 0, 0}; //Recovery of the sub-macroblock type for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { Current_residu -> SubMbType [mbPartIdx] = decode_cabac_p_mb_sub_type(c, state); } #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckSubMbType( Current_residu -> SubMbType, MaxPSubMbType)){ //should be set to zero because the macroblock will be decoded. refl0_cache [12] = refl0_cache [14] = refl0_cache [28] = refl0_cache [30] = 0; return 1; } #endif //Recovery of the image reference of each sub-macroblock if (slice -> num_RefIdxL0_active_minus1 > 0) { if(GetCabacPSubRefIdx(c, state, RefIdxL0, ref_cache_l0, RefIdxL0, slice -> num_RefIdxL0_active_minus1)){ refl0_cache [12] = refl0_cache [14] = refl0_cache [28] = refl0_cache [30] = 0; return 1; } } else { ref_cache_l0[12] = ref_cache_l0[14] = ref_cache_l0[28] = ref_cache_l0[30] = 0; } //Recovery of the motion vector of each sub-macroblock for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { short MvdL0[2]; int sub_mb_type = Current_residu -> SubMbType [mbPartIdx]; for ( subMbPartIdx = 0 ; subMbPartIdx < sub_num_p_part[ sub_mb_type] ; subMbPartIdx++ ) { int index = SCAN8(( mbPartIdx << 2) + (sub_mb_type == 1 ? 2 * subMbPartIdx: subMbPartIdx)); //Decode cabac ReadCabacSubMotionVector(c, state, mv_cache_l0, MvdL0, mbPartIdx, subMbPartIdx, sub_mb_type, index, slice -> slice_type); //Compute Mv refill_ref(2 - (sub_mb_type > 1), 2 - (sub_mb_type & 1), RefIdxL0[mbPartIdx], &refl0_cache[index]); motion_vector(mvl0_cache, MvdL0, refl0_cache, &mvl0_cache[index][0], RefIdxL0[mbPartIdx], index, 2 / ( 1 + ( sub_mb_type > 1))); } refill_motion_vector(0, sub_mb_type, &mvl0_cache[SCAN8(( mbPartIdx << 2))]); } for ( mbPartIdx = 0; mbPartIdx < 4 && dct_allowed; mbPartIdx ++){ if ( !(sub_num_p_part[Current_residu -> SubMbType[mbPartIdx]] == 1) ){ *dct_allowed = 0; } } return 0; }
void mb_pred_intra_8x8_cabac ( CABACContext *c, unsigned char *state, short *Mode, short *intra4x4_pred_mode_cache) { int luma4x4BlkIdx ; //Recovery of the prediction mode for ( luma4x4BlkIdx = 0 ; luma4x4BlkIdx < 4 ; luma4x4BlkIdx++ ) { Mode[(luma4x4BlkIdx << 2)] = Mode[(luma4x4BlkIdx << 2) + 1] = Mode[(luma4x4BlkIdx << 2) + 2] = Mode[(luma4x4BlkIdx << 2) + 3] = intra4x4_pred_mode_cache[SCAN8(luma4x4BlkIdx << 2)] = intra4x4_pred_mode_cache[SCAN8(1 + (luma4x4BlkIdx << 2))] = intra4x4_pred_mode_cache[SCAN8( (luma4x4BlkIdx << 2) + 2)] = intra4x4_pred_mode_cache[SCAN8((luma4x4BlkIdx << 2) + 3)] = GetCabacIPredMode(c, state, intra4x4_pred_mode_cache, luma4x4BlkIdx << 2); } }
/** This function allows to get the prediction of an non IDR picture. //8.4.2.2 @param DpbLuma Table of the reference decoded picture buffer. @param DpbCb Table of the reference decoded picture buffer. @param DpbCr Table of the reference decoded picture buffer. @param Luma_l0 Table of current frame. @param Luma_l1 Table of current frame. @param Chroma_Cb_l0 Table of current frame. @param Chroma_Cb_l1 Table of current frame. @param Chroma_Cr_l0 Table of current frame. @param Chroma_Cr_l1 Table of current frame. @param mvL0 The motion vector are stocked for each 4x4 block of each macroblock. @param mvL1 The motion vector are stocked for each 4x4 block of each macroblock. @param ref_cache_l0 A cache table where the reference is stocked for each 4x4 block of each macroblock. @param ref_cache_l1 A cache table where the reference is stocked for each 4x4 block of each macroblock. @param x X-coordinate. @param y Y-coordinate. @param PicWidthInPix Width in pixel of the current frame. @param PicHeightInPix Height in pixel of the current frame. @prama RefPicListL0 List l0 of reference image. @prama RefPicListL1 List l1 of reference image. @param interpol Function pointer of 4x4 interpoaltion. */ void sample_interpolation_main(unsigned char *DpbLuma, unsigned char *DpbCb,unsigned char *DpbCr, unsigned char *Luma_l0, unsigned char *Luma_l1 , unsigned char *Chroma_Cb_l0, unsigned char *Chroma_Cb_l1, unsigned char *Chroma_Cr_l0 , unsigned char *Chroma_Cr_l1, short mvL0[][2], short mvL1[][2], short *ref_cache_l0, short *ref_cache_l1, short x, short y, const short PicWidthInPix, const short PicHeightInPix , const LIST_MMO *RefPicListL0, const LIST_MMO * RefPicListL1, const interpol_4x4 *interpol) { int i; for( i = 0; i < 16; i++){ short index8 = SCAN8(i); const short Currentx = x + LOCX(i); const short Currenty = y + LOCY(i); if ( ref_cache_l0[index8] >= 0){ Interpolate(ref_cache_l0[index8], Currentx, Currenty, &mvL0[index8][0], 4, PicWidthInPix, PicHeightInPix, RefPicListL0, &Luma_l0[i << 4], &Chroma_Cb_l0[i << 2], &Chroma_Cr_l0[i << 2], DpbLuma, DpbCb, DpbCr, interpol); } if ( ref_cache_l1[index8] >= 0){ Interpolate(ref_cache_l1[index8], Currentx, Currenty, &mvL1[index8][0], 4, PicWidthInPix, PicHeightInPix, RefPicListL1, &Luma_l1[i << 4], &Chroma_Cb_l1[i << 2], &Chroma_Cr_l1[i << 2], DpbLuma, DpbCb, DpbCr, interpol); } } }
void mb_pred_intra_cabac ( CABACContext *c, unsigned char *state, short *Mode, short *intra4x4_pred_mode_cache){ int luma4x4BlkIdx ; //Recovery of the prediction mode for ( luma4x4BlkIdx = 0 ; luma4x4BlkIdx < 16 ; luma4x4BlkIdx++ ) { Mode[luma4x4BlkIdx] = intra4x4_pred_mode_cache[SCAN8(luma4x4BlkIdx)] = GetCabacIPredMode(c, state, intra4x4_pred_mode_cache, luma4x4BlkIdx); } }
void get_mv_neighbourhood( int *mva, int *mvb, short mv_cache[][2], int sub_mb_type, int mbPartIdx, int SubMbPart, int compIdx, int slice_type){ int ind = SCAN8((mbPartIdx << 2) + SubMbPart); if (slice_type == SLICE_TYPE_P){ if (sub_mb_type == 1){ ind = SCAN8(((mbPartIdx << 1) + SubMbPart) << 1); *mva = mv_cache[ ind - 1][compIdx]; *mvb = mv_cache[ ind - 8][compIdx]; }else{ *mva = mv_cache[ ind - 1][compIdx]; *mvb = mv_cache[ ind - 8][compIdx]; } }else{ if (sub_mb_type == 4 || sub_mb_type == 6 || sub_mb_type == 8){ ind = SCAN8(((mbPartIdx << 1) + SubMbPart) << 1); *mva = mv_cache[ ind - 1][compIdx]; *mvb = mv_cache[ ind - 8][compIdx]; }else{ *mva = mv_cache[ ind - 1][compIdx]; *mvb = mv_cache[ ind - 8][compIdx]; } } }
/** This function decode the motion vector of a macroblock with 8x8 partition */ void ReadCabac8x8MotionVector(CABACContext *c, unsigned char *state, RESIDU *CurrentResidu, SLICE *slice, short mv_cache_lx[][2], short MvdLx[][2], int Pred_Lx) { int mbPartIdx, subMbPartIdx; for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { int SubMbType = CurrentResidu -> SubMbType [mbPartIdx]; if ( (sub_mb_b_name [SubMbType] != B_direct) && (sub_mb_b_name [SubMbType] != Pred_Lx )) { for ( subMbPartIdx = 0 ; subMbPartIdx < sub_num_b_part[SubMbType] ; subMbPartIdx++ ) { int xpart = (SubMbType < 5 || SubMbType == 6 || SubMbType == 8) ? 2:1; int index = SCAN8(( mbPartIdx << 2) + subMbPartIdx * xpart); ReadCabacSubMotionVector(c, state, mv_cache_lx, &MvdLx [(mbPartIdx << 2) + subMbPartIdx][0], mbPartIdx, subMbPartIdx, SubMbType, index, slice -> slice_type); } } } }
/** This function is used to decode the sub macroblock information in a P slice. */ int SubMbPCabacSVC ( int *dct_allowed, CABACContext *c, unsigned char *state, SLICE *slice, DATA *macroblock, RESIDU *CurrentResidu, short mv_cache_l0[][2], short ref_cache_l0[]) { int mbPartIdx ; int subMbPartIdx ; int compIdx ; int mva; int mvb; //Recovery of the sub-macroblock type for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { CurrentResidu -> SubMbType [mbPartIdx] = decode_cabac_p_mb_sub_type( c, state); } #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckSubMbType( CurrentResidu -> SubMbType, MaxPSubMbType)){ //should be set to zero because the macroblock will be decoded. memset(ref_cache_l0, 0, 48 * sizeof(short)); return 1; } #endif if(GetCabacSVCPMotionPred(c, state, slice, macroblock, macroblock -> MotionPredL0, CurrentResidu -> InCropWindow, Pred_L1, 0)){ return 1; } //Recovery of the image reference of each sub-macroblock if (slice -> num_RefIdxL0_active_minus1 > 0) { if(GetCabacPSubRefIdx(c, state, macroblock -> RefIdxL0, ref_cache_l0, macroblock -> MotionPredL0, slice -> num_RefIdxL0_active_minus1)){ return 1; } }else { ref_cache_l0[12] = ref_cache_l0[13] = ref_cache_l0[14] = ref_cache_l0[15] = ref_cache_l0[20] = ref_cache_l0[21] = ref_cache_l0[22] = ref_cache_l0[23] = ref_cache_l0[28] = ref_cache_l0[29] = ref_cache_l0[30] = ref_cache_l0[21] = ref_cache_l0[36] = ref_cache_l0[37] = ref_cache_l0[38] = ref_cache_l0[39] = 0; } //Recovery of the motion vector of each sub-macroblock for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { short MvdL0[2]; int sub_mb_type = CurrentResidu -> SubMbType [mbPartIdx]; for ( subMbPartIdx = 0 ; subMbPartIdx < sub_num_p_part[ sub_mb_type] ; subMbPartIdx++ ) { int index = SCAN8(( mbPartIdx << 2) + (sub_mb_type == 1 ? 2 * subMbPartIdx: subMbPartIdx)); for ( compIdx = 0 ; compIdx < 2 ; compIdx++ ) { get_mv_neighbourhood(&mva, &mvb, mv_cache_l0, sub_mb_type, mbPartIdx , subMbPartIdx , compIdx, slice -> slice_type); macroblock -> MvdL0 [(mbPartIdx << 2) + subMbPartIdx][compIdx] = MvdL0[compIdx] = decode_cabac_mb_mvd( c, state, mva, mvb, compIdx); } FillSubMotionVector(MvdL0, &mv_cache_l0[index], sub_mb_type, slice -> slice_type); } } for ( mbPartIdx = 0; mbPartIdx < 4 && *dct_allowed; mbPartIdx ++){ if ( !(sub_num_p_part[CurrentResidu -> SubMbType[mbPartIdx]] == 1) ){ *dct_allowed = 0; } } return 0; }
char sub_mb_pred_cabac ( int *dct_allowed, CABACContext *c, unsigned char *state, SLICE *slice, RESIDU *Current_residu, short mv_cache_l0[][2], short mv_cache_l1[][2], short *ref_cache_l0, short *ref_cache_l1, short mvl0_cache[][2], short mvl1_cache[][2], short *refl0_cache, short *refl1_cache, short *mvl1_l0, short *mvl1_l1, short *refl1_l0, short *refl1_l1, int direct_8x8_inference_flag, int long_term, int slice_type, int is_svc) { int mbPartIdx ; char RefIdxL0[4] = {0, 0, 0, 0}; char RefIdxL1[4] = {0, 0, 0, 0}; //Recovery of the sub-macroblock type for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { Current_residu -> SubMbType [mbPartIdx] = decode_cabac_b_mb_sub_type( c, state); } #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckSubMbType( Current_residu -> SubMbType, MaxBSubMbType)){ //should be set to zero because the macroblock will be decoded. refl0_cache [12] = refl0_cache [14] = refl0_cache [28] = refl0_cache [30] = 0; refl1_cache [12] = refl1_cache [14] = refl1_cache [28] = refl1_cache [30] = 0; return 1; } #endif //L0 and L1 reference index if(GetCabacBSubRefList(c, state, RefIdxL0, ref_cache_l0, RefIdxL0, Current_residu -> SubMbType, slice -> num_RefIdxL0_active_minus1, Pred_L1)){ refl0_cache [12] = refl0_cache [14] = refl0_cache [28] = refl0_cache [30] = 0; refl1_cache [12] = refl1_cache [14] = refl1_cache [28] = refl1_cache [30] = 0; return 1; } if(GetCabacBSubRefList(c, state, RefIdxL1, ref_cache_l1, RefIdxL1, Current_residu -> SubMbType, slice -> num_RefIdxL1_active_minus1, Pred_L0)){ refl1_cache [12] = refl1_cache [14] = refl1_cache [28] = refl1_cache [30] = 0; return 1; } //Recovery of the motion vector of each sub-macroblock for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { int sub_mb_type = Current_residu -> SubMbType [mbPartIdx]; if ( sub_mb_b_name[sub_mb_type] == B_direct){ int ind = SCAN8(mbPartIdx << 2); short mv[2] = {0, 0}; refill_mv(2, 2, mv, &mv_cache_l0[ind]); if (slice -> direct_spatial_mv_pred_flag){ spatial_direct_prediction_l0(mvl0_cache, mvl1_l0, mvl1_l1, refl0_cache, refl1_cache, refl1_l0, refl1_l1, mbPartIdx, slice -> b_stride, slice -> b8_stride, direct_8x8_inference_flag, long_term, is_svc, slice_type); }else{ temporal_direct_prediction_l0(mvl0_cache, mvl1_l0, refl0_cache, refl1_l0, refl1_l1, slice, mbPartIdx, direct_8x8_inference_flag, is_svc, slice_type); } }else if (sub_mb_b_name[sub_mb_type] != Pred_L1 ) { ReadAndComputeCabac8x8MotionVector( c, state, mbPartIdx, sub_mb_type, RefIdxL0, refl0_cache, mv_cache_l0, mvl0_cache, 1); }else { int ind = SCAN8(mbPartIdx << 2); short mv[2] = {0, 0}; refill_mv(2, 2, mv, &mv_cache_l0[ind]); refill_ref(2, 2, -1, &refl0_cache[ind]); } } //Recovery of the motion vector of each sub-macroblock for ( mbPartIdx = 0 ; mbPartIdx < 4 ; mbPartIdx++ ) { int sub_mb_type = Current_residu -> SubMbType [mbPartIdx]; if ( sub_mb_b_name[ sub_mb_type] == B_direct){ int ind = SCAN8(mbPartIdx << 2); short mv[2] = {0, 0}; refill_mv(2, 2, mv, &mv_cache_l1[ind]); if (slice -> direct_spatial_mv_pred_flag){ spatial_direct_prediction_l1(mvl1_cache, mvl1_l0, mvl1_l1, refl0_cache, refl1_cache, refl1_l0, refl1_l1 , mbPartIdx, slice -> b_stride, slice -> b8_stride, direct_8x8_inference_flag, long_term, is_svc , slice_type); }else{ temporal_direct_prediction_l1(mvl1_cache, mvl1_l0, refl1_cache, refl1_l0, refl1_l1,slice , mbPartIdx, direct_8x8_inference_flag, is_svc, slice_type); } }else if (sub_mb_b_name[sub_mb_type] != Pred_L0 ) { ReadAndComputeCabac8x8MotionVector( c, state, mbPartIdx, sub_mb_type, RefIdxL1, refl1_cache, mv_cache_l1, mvl1_cache, 1); }else{ int ind = SCAN8(mbPartIdx << 2); short mv[2] = {0, 0}; refill_mv(2, 2, mv, &mv_cache_l1[ind]); refill_ref(2, 2, -1, &refl1_cache[ind]); } } for ( mbPartIdx = 0; mbPartIdx < 4 && *dct_allowed; mbPartIdx ++){ if ( !((sub_num_b_part[Current_residu -> SubMbType[mbPartIdx]] == 1) || ( direct_8x8_inference_flag && sub_mb_b_name[Current_residu -> SubMbType[mbPartIdx]] == B_direct))){ *dct_allowed = 0; } } return 0; }