📄 macroblock.c
字号:
/*!
*************************************************************************************
* \file macroblock.c
*
* \brief
* Process one macroblock
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Inge Lille-Lang鴜 <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>
* - Detlev Marpe <marpe@hhi.de>
* - Thomas Wedi <wedi@tnt.uni-hannover.de>
* - Ragip Kurceren <ragip.kurceren@nokia.com>
*************************************************************************************
*/
#include "contributors.h"
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include "global.h"
#include "elements.h"
#include "macroblock.h"
#include "refbuf.h"
#include "fmo.h"
#include "vlc.h"
#include "image.h"
#include "mb_access.h"
#include "ratectl.h" // head file for rate control
#include "cabac.h"
#include "transform8x8.h"
//Rate control
int predict_error,dq;
extern int DELTA_QP,DELTA_QP2;
extern int QP,QP2;
/*!
************************************************************************
* \brief
* updates the coordinates for the next macroblock to be processed
*
* \param mb_addr
* MB address in scan order
************************************************************************
*/
void set_MB_parameters (int mb_addr)
{
img->current_mb_nr = mb_addr;
get_mb_block_pos(mb_addr, &img->mb_x, &img->mb_y);
img->block_x = img->mb_x << 2;
img->block_y = img->mb_y << 2;
img->pix_x = img->block_x << 2;
img->pix_y = img->block_y << 2;
img->opix_x = img->pix_x;
if (img->MbaffFrameFlag)
{
if (img->mb_data[mb_addr].mb_field)
{
imgY_org = (mb_addr % 2) ? imgY_org_bot : imgY_org_top;
imgUV_org = (mb_addr % 2) ? imgUV_org_bot : imgUV_org_top;
img->opix_y = (img->mb_y >> 1 ) << 4;
}
else
{
imgY_org = imgY_org_frm;
imgUV_org = imgUV_org_frm;
img->opix_y = img->block_y << 2;
}
}
else
{
img->opix_y = img->block_y << 2;
}
if (img->yuv_format != YUV400)
{
img->pix_c_x = img->pix_x / (16/img->mb_cr_size_x);
img->pix_c_y = img->pix_y / (16/img->mb_cr_size_y);
img->opix_c_x = img->opix_x / (16/img->mb_cr_size_x);
img->opix_c_y = img->opix_y / (16/img->mb_cr_size_y);
}
// printf ("set_MB_parameters: mb %d, mb_x %d, mb_y %d\n", mb_addr, img->mb_x, img->mb_y);
}
int clip1a(int a)
{
return ((a)>img->max_imgpel_value?img->max_imgpel_value:((a)<0?0:(a)));
}
int clip1a_chr(int a)
{
return ((a)>img->max_imgpel_value_uv?img->max_imgpel_value_uv:((a)<0?0:(a)));
}
/*!
************************************************************************
* \brief
* updates the coordinates and statistics parameter for the
* next macroblock
************************************************************************
*/
void proceed2nextMacroblock()
{
#if TRACE
int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
#endif
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
int* bitCount = currMB->bitcounter;
int i;
#if TRACE
if (p_trace)
{
fprintf(p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i **********\n\n", frame_no, img->current_mb_nr, img->current_slice_nr);
if(use_bitstream_backing)
fprintf(p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i **********\n\n", frame_no, img->current_mb_nr, img->current_slice_nr);
// Write out the tracestring for each symbol
for (i=0; i<currMB->currSEnr; i++)
trace2out(&(img->MB_SyntaxElements[i]));
}
#endif
// Update the statistics
stats->bit_use_mb_type[img->type] += bitCount[BITS_MB_MODE];
stats->bit_use_coeffY[img->type] += bitCount[BITS_COEFF_Y_MB] ;
stats->tmp_bit_use_cbp[img->type] += bitCount[BITS_CBP_MB];
stats->bit_use_coeffC[img->type] += bitCount[BITS_COEFF_UV_MB];
stats->bit_use_delta_quant[img->type] += bitCount[BITS_DELTA_QUANT_MB];
if (IS_INTRA(currMB))
{
++stats->intra_chroma_mode[currMB->c_ipred_mode];
if ((currMB->cbp&15) != 0)
{
if (currMB->luma_transform_size_8x8_flag)
++stats->mode_use_transform_8x8[img->type][currMB->mb_type];
else
++stats->mode_use_transform_4x4[img->type][currMB->mb_type];
}
}
++stats->mode_use[img->type][currMB->mb_type];
stats->bit_use_mode[img->type][currMB->mb_type]+= bitCount[BITS_INTER_MB];
if (img->type != I_SLICE)
{
if (currMB->mb_type == P8x8)
{
for(i=0;i<4;i++)
{
if (currMB->b8mode[i] > 0)
++stats->mode_use[img->type][currMB->b8mode[i]];
else
++stats->b8_mode_0_use[img->type][currMB->luma_transform_size_8x8_flag];
if (currMB->b8mode[i]==4)
{
if ((currMB->luma_transform_size_8x8_flag && (currMB->cbp&15) != 0) || input->AllowTransform8x8 == 2)
++stats->mode_use_transform_8x8[img->type][4];
else
++stats->mode_use_transform_4x4[img->type][4];
}
}
}
else if (currMB->mb_type >= 0 && currMB->mb_type <=3 && ((currMB->cbp&15) != 0))
{
if (currMB->luma_transform_size_8x8_flag)
++stats->mode_use_transform_8x8[img->type][currMB->mb_type];
else
++stats->mode_use_transform_4x4[img->type][currMB->mb_type];
}
}
// Statistics
if ((img->type == P_SLICE)||(img->type==SP_SLICE) )
{
++stats->quant0;
stats->quant1 += currMB->qp; // to find average quant for inter frames
}
}
/*!
************************************************************************
* \brief
* initializes the current macroblock
************************************************************************
*/
void start_macroblock(int mb_addr, int mb_field)
{
int i,j,k,l;
int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
Macroblock *currMB = &img->mb_data[mb_addr];
Slice *curr_slice = img->currentSlice;
DataPartition *dataPart;
Bitstream *currStream;
EncodingEnvironmentPtr eep;
int max_qp_delta = 25 + img->bitdepth_luma_qp_scale/2;
int min_qp_delta = (26 + img->bitdepth_luma_qp_scale/2);
currMB->mb_field = mb_field;
enc_picture->mb_field[mb_addr] = mb_field;
set_MB_parameters (mb_addr);
if(use_bitstream_backing)
{
// Keep the current state of the bitstreams
if(!img->cod_counter)
for (i=0; i<curr_slice->max_part_nr; i++)
{
dataPart = &(curr_slice->partArr[i]);
currStream = dataPart->bitstream;
currStream->stored_bits_to_go = currStream->bits_to_go;
currStream->stored_byte_pos = currStream->byte_pos;
currStream->stored_byte_buf = currStream->byte_buf;
if (input->symbol_mode ==CABAC)
{
eep = &(dataPart->ee_cabac);
eep->ElowS = eep->Elow;
eep->ErangeS = eep->Erange;
eep->EbufferS = eep->Ebuffer;
eep->Ebits_to_goS = eep->Ebits_to_go;
eep->Ebits_to_followS = eep->Ebits_to_follow;
eep->EcodestrmS = eep->Ecodestrm;
eep->Ecodestrm_lenS = eep->Ecodestrm_len;
eep->CS = eep->C;
eep->BS = eep->B;
eep->ES = eep->E;
}
}
}
// 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;
// Initialize delta qp change from last macroblock. Feature may be used for future rate control
// Rate control
currMB->qpsp = img->qpsp;
if(input->RCEnable)
{
if (img->current_mb_nr==0)
{
currMB->prev_qp = img->qp;
currMB->prev_delta_qp = 0;
}
else
{
currMB->prev_qp = img->mb_data[img->current_mb_nr-1].qp;
currMB->prev_delta_qp = img->mb_data[img->current_mb_nr-1].delta_qp;
}
/*frame layer rate control*/
if(input->basicunit==img->Frame_Total_Number_MB)
{
currMB->delta_qp = 0;
currMB->qp = img->qp;
}
/*basic unit layer rate control*/
else
{
/*each I or B frame has only one QP*/
if((img->type==I_SLICE)||(img->type==B_SLICE))
{
currMB->delta_qp = 0;
currMB->qp = img->qp;
}
else if(img->type==P_SLICE)
{
if (!img->write_macroblock) //write macroblock
{
if (!currMB->mb_field) //frame macroblock
{
if (img->current_mb_nr == 0) //first macroblock
{
// Initialize delta qp change from last macroblock. Feature may be used for future rate control
currMB->delta_qp = 0;
currMB->qp = img->qp;
DELTA_QP = DELTA_QP2 = currMB->delta_qp;
QP = QP2 = currMB->qp;
}
else
{
if (!((input->MbInterlace) && img->bot_MB)) //top macroblock
{
if (img->mb_data[img->current_mb_nr-1].prev_cbp == 1)
{
currMB->delta_qp = 0;
currMB->qp = img->qp;
}
else
{
currMB->qp = img->mb_data[img->current_mb_nr-1].prev_qp;
currMB->delta_qp = currMB->qp - img->mb_data[img->current_mb_nr-1].qp;
img->qp = currMB->qp;
}
DELTA_QP = DELTA_QP2 = currMB->delta_qp;
QP = QP2 = currMB->qp;
}
else //bottom macroblock
{
// Initialize delta qp change from last macroblock. Feature may be used for future rate control
currMB->delta_qp = 0;
currMB->qp = img->qp; // needed in loop filter (even if constant QP is used)
}
}
}
else //field macroblock
{
if (!img->bot_MB) //top macroblock
{
currMB->delta_qp = DELTA_QP2;
currMB->qp = img->qp = QP2;
}
else//bottom macroblock
{
currMB->qp = img->qp;
currMB->delta_qp = 0;
}
}
}
else
{
if (!img->bot_MB) //write top macroblock
{
if (img->write_macroblock_frame)
{
currMB->delta_qp = DELTA_QP;
img->qp = currMB->qp = QP;
}
else
{
currMB->delta_qp = DELTA_QP2;
img->qp = currMB->qp = QP2;
}
}
else //write bottom macroblock
{
currMB->delta_qp = 0;
currMB->qp = img->qp;
}
}
/*compute the quantization parameter for each basic unit of P frame*/
if(!((input->MbInterlace)&&img->bot_MB))
{
if(!currMB->mb_field)
{
if((img->NumberofCodedMacroBlocks>0)\
&&(img->NumberofCodedMacroBlocks%img->BasicUnit==0))
{
/*frame coding*/
if(active_sps->frame_mbs_only_flag)
{
updateRCModel();
img->BasicUnitQP=updateQuantizationParameter(img->TopFieldFlag);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -