No.3 encode_one_slice() DeblockMb() Relation of Functions Encode_one_slice() Code_a_picture() DeblockFrame() DeblockMb()
H.264 Code Tracing encode_one_slice() No.3 9762642 陳則伊
Introduction-caller and main function “slice.c” Caller: code_a_picture() Main function of encode_one_slice(): Encode a slice group Execute PAFF / MBAFF mode
Introduction-input and output int SliceGroupId Picture *pic int TotalCodedMBs Output: int NumberOfCodedMBs
Local Variables Boolean end_of_slice = FALSE; Boolean recode_macroblock; int len; //# of bits of header used in a slice int NumberOfCodedMBs = 0; //return int CurrentMbAddr; double FrameRDCost = DBL_MAX; double FieldRDCost = DBL_MAX;
Initializations CurrentMbAddr = FmoGetFirstMacroblockInSlice (SliceGroupId); init_slice (CurrentMbAddr); SetLagrangianMultipliers(); len = start_slice ();
Main function code(1) Loop over MBs in a slice while (end_of_slice == FALSE) { -Encode by PAFF mode -Encode by MBAFF mode } terminate_slice(……); return NumberOfCodedMBs;
Main function code(2) Calculate the quantization offset parameters if (img->AdaptiveRounding && input->AdaptRndPeriod && (img->current_mb_nr % input->AdaptRndPeriod == 0)) { CalculateOffsetParam(); if(input->Transform8x8Mode) CalculateOffset8Param(); }
Main function code(3)-PAFF Use PAFF mode if (!img->MbaffFrameFlag) { recode_macroblock = FALSE; rdopt = &rddata_top_frame_mb; start_macroblock (CurrentMbAddr, FALSE); encode_one_macroblock (); write_one_macroblock (1); terminate_macroblock (&end_of_slice, &recode_macroblock); ……
Main function code(4)-PAFF If MB don’t need to be recoded …… if (recode_macroblock == FALSE) { CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr); if (CurrentMbAddr == -1) // end of slice end_of_slice = TRUE; NumberOfCodedMBs++; proceed2nextMacroblock (); }
Main function code(5)-PAFF If MB need to be recoded …… else{ img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr); if(img->current_mb_nr == -1 ) error (errortext, 300); } } // end of PAFF mode
Main function code(6)-MBAFF Check whether it is frame mode else{ //Use MBAFF mode if (input->MbInterlace == ADAPTIVE_CODING || input->MbInterlace == FRAME_MB_PAIR_CODING) { -Encode top MB as frame MB -Encode bottom MB as frame MB } ……
Main function code(7)-MBAFF Encode top MB as frame MB Set top MB coded as frame MB recode_macroblock = FALSE; img->field_mode = 0; // MB coded as frame img->top_field = 0; // Set top field to 0 Rate control img->write_macroblock = 0; img->bot_MB = 0; Encode one MB start_macroblock (CurrentMbAddr, FALSE); rdopt = &rddata_top_frame_mb; // store data in top frame MB encode_one_macroblock (); // code the MB as frame MB FrameRDCost = rdopt->min_rdcost;
Main function code(8)-MBAFF Encode bottom MB as frame MB Set bottom MB coded as frame MB img->field_mode = 0; // MB coded as frame MB Rate control img->bot_MB = 1; Encode one MB start_macroblock (CurrentMbAddr+1, FALSE); rdopt = &rddata_bot_frame_mb; // store data in bottom frame MB encode_one_macroblock (); // code the MB as frame MB FrameRDCost += rdopt->min_rdcost;
Main function code(9)-MBAFF Check whether it is field mode if ((input->MbInterlace == ADAPTIVE_CODING) || (input->MbInterlace == FIELD_CODING)) { -Encode top MB as field MB -Encode bottom MB as field MB }
Main function code(10)-MBAFF Encode top MB as field MB Set top MB coded as field MB img->field_mode = 1; // MB coded as field img->top_field = 1; // Set top field to 1 Rate control img->bot_MB = 0; Encode one MB start_macroblock (CurrentMbAddr, TRUE); rdopt = &rddata_top_field_mb; // store data in top field MB encode_one_macroblock (); // code the MB as field MB FieldRDCost = rdopt->min_rdcost;
Main function code(11)-MBAFF Encode bottom MB as field MB Set bottom MB coded as field MB img->top_field = 0; // Set top field to 0 Rate control img->bot_MB = 1; Encode one MB start_macroblock (CurrentMbAddr+1, TRUE); rdopt = &rddata_bot_field_mb; // store data in bottom field MB encode_one_macroblock (); // code the MB as field MB FieldRDCost += rdopt->min_rdcost;
Main function code(12)- MBAFF Decide between frame/field MB pair if ( ((input->MbInterlace == ADAPTIVE_CODING) && (FrameRDCost < FieldRDCost)) || input->MbInterlace == FRAME_MB_PAIR_CODING ) { img->field_mode = 0; //Frame MB MBPairIsField = 0; } else { img->field_mode = 1; //Field MB MBPairIsField = 1; }
Main function code(13)- MBAFF if (recode_macroblock == FALSE) { CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr); if (CurrentMbAddr == -1) // end of slice end_of_slice = TRUE; NumberOfCodedMBs++; proceed2nextMacroblock (); write_one_macroblock (0); //wrt bot MB to bitstream terminate_macroblock (&end_of_slice, &recode_macroblock); }
Main function code(14)- MBAFF else { img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr); if(img->current_mb_nr == -1 ) error (errortext, 300); } //End of MBAFF mode
Main function code(15)- End of encoding a Slice Group while (end_of_slice == FALSE) { -Encode by PAFF mode -Encode by MBAFF mode } terminate_slice ( (NumberOfCodedMBs+TotalCodedMBs >= (int)img->PicSizeInMbs) ); return NumberOfCodedMBs;
H.264 Code Tracing DeblockMb() No.3 9762642 陳則伊
Introduction-caller and goal “loopFilter.c” Caller: DeblockFrame() Goal: Deblocking filter for one MB No filter beyond picture boundary Compute strength values for one stripe in a MB Filters luma/chroma block edge for frame or field coded pictures
Introduction-input and output ImageParameters *img imgpel **imgY imgpel ***imgUV int MbQAddr //index of MB in a frame Output: void
Local Variables int EdgeCondition; int dir, edge; byte Strength[16]; int mb_x, mb_y; int filterNon8x8LumaEdgesFlag[4] = {1,1,1,1}; int filterLeftMbEdgeFlag; int filterTopMbEdgeFlag; int fieldModeMbFlag; int mvlimit = 4; int i, StrengthSum; Macroblock *MbQ; int edge_cr;
Main function code(1) img->DeblockCall = 1; get_mb_pos (MbQAddr, &mb_x, &mb_y, IS_LUMA); filterLeftMbEdgeFlag = (mb_x != 0); filterTopMbEdgeFlag = (mb_y != 0); MbQ = &(img->mb_data[MbQAddr]) ; // current Mb filterNon8x8LumaEdgesFlag[1] = filterNon8x8LumaEdgesFlag[3] = !(MbQ->luma_transform_size_8x8_flag);
Main function code(2) if (img->MbaffFrameFlag && mb_y == MB_BLOCK_SIZE && MbQ->mb_field) filterTopMbEdgeFlag = 0; fieldModeMbFlag = (img->structure!=FRAME) || (img->MbaffFrameFlag && MbQ->mb_field); if (fieldModeMbFlag) mvlimit = 2;
Main function code(3) if (MbQ->LFDisableIdc==1) { //return, if filter is disabled img->DeblockCall = 0; return; } if (MbQ->LFDisableIdc==2){ // don't filter at slice boundaries filterLeftMbEdgeFlag = MbQ->mbAvailA; filterTopMbEdgeFlag = (img->MbaffFrameFlag && !MbQ->mb_field && (MbQAddr & 0x01)) ? 1 : MbQ->mbAvailB; img->current_mb_nr = MbQAddr; CheckAvailabilityOfNeighbors();
Main function code(4) for( dir = 0 ; dir < 2 ; dir++ ) // 0=vertical edges; 1=horizontal { EdgeCondition = (dir && filterTopMbEdgeFlag) || (!dir && filterLeftMbEdgeFlag); for( edge=0; edge<4 ; edge++ ) // first 4 vertical strips of 16 pel { // then 4 horizontal if( edge || EdgeCondition ) edge_cr = chroma_edge[dir][edge][img->yuv_format]; GetStrength(Strength, img, MbQAddr, dir, edge << 2, mvlimit); StrengthSum = Strength[0]; ……
Main function code(5) for (i = 0; i < MB_BLOCK_SIZE; i++) { if (StrengthSum) break; StrengthSum += Strength[i]; } if( StrengthSum ) { // only if one of the 16 Strength bytes is != 0 if (filterNon8x8LumaEdgesFlag[edge]) EdgeLoopLuma( imgY, Strength, img, MbQAddr, MbQ->LFAlphaC0Offset, MbQ->LFBetaOffset, dir, edge << 2, img->width) ; if( (imgUV != NULL) && (edge_cr >= 0)) { EdgeLoopChroma( imgUV[0], Strength, img, MbQAddr, MbQ->LFAlphaC0Offset, MbQ->LFBetaOffset, dir, edge_cr, img->width_cr, 0) ; EdgeLoopChroma( imgUV[1], Strength, img, MbQAddr, MbQ->LFAlphaC0Offset, MbQ->LFBetaOffset, dir, edge_cr, img->width_cr, 1) ;
Main function code(6) if (dir && !edge && !MbQ->mb_field && mixedModeEdgeFlag) { // extra horizontal edge between a frame macroblock pair and a field img->DeblockCall = 2; GetStrength(Strength, img, MbQAddr, dir, MB_BLOCK_SIZE, mvlimit); ……
Main function code(7) if (filterNon8x8LumaEdgesFlag[edge]) EdgeLoopLuma( imgY, Strength, img, MbQAddr, MbQ->LFAlphaC0Offset, MbQ->LFBetaOffset, dir, 16, img->width) ; if( (imgUV != NULL) && (edge_cr >= 0)) { EdgeLoopChroma( imgUV[0], Strength, img, MbQAddr, MbQ->LFAlphaC0Offset, MbQ->LFBetaOffset, dir, MB_BLOCK_SIZE, img->width_cr, 0) ; EdgeLoopChroma( imgUV[1], Strength, img, MbQAddr, MbQ->LFAlphaC0Offset, MbQ->LFBetaOffset, dir, MB_BLOCK_SIZE, img->width_cr, 1) ; } img->DeblockCall = 1; } //end edge } //end loop dir img->DeblockCall = 0;