📄 macroblock.c
字号:
/*!
*************************************************************************************
* \file macroblock.c
*
* \brief
* Process one macroblock
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Inge Lille-Langoy <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>
* - Alexis Michael Tourapis <alexismt@ieee.org>
*************************************************************************************
*/
#include "contributors.h"
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <memory.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
* macroblock 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;
img->mb_data[mb_addr].list_offset = (mb_addr % 2) ? 4 : 2;
}
else
{
imgY_org = imgY_org_frm;
imgUV_org = imgUV_org_frm;
img->opix_y = img->block_y << 2;
img->mb_data[mb_addr].list_offset = 0;
}
}
else
{
img->opix_y = img->block_y << 2;
img->mb_data[mb_addr].list_offset = 0;
}
if (img->yuv_format != YUV400)
{
img->pix_c_x = (img->mb_cr_size_x * img->pix_x) >> 4;
img->pix_c_y = (img->mb_cr_size_y * img->pix_y) >> 4;
img->opix_c_x = (img->mb_cr_size_x * img->opix_x) >> 4;
img->opix_c_y = (img->mb_cr_size_y * img->opix_y) >> 4;
}
// printf ("set_MB_parameters: mb %d, mb_x %d, mb_y %d\n", mb_addr, img->mb_x, img->mb_y);
}
/*!
************************************************************************
* \brief
* clip to range [0..max luma pel value]
************************************************************************
*/
int clip1a(int a)
{
return ((a)>img->max_imgpel_value?img->max_imgpel_value:((a)<0?0:(a)));
}
/*!
************************************************************************
* \brief
* clip to range [0..max chroma pel value]
************************************************************************
*/
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(void)
{
#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 (bitCount[BITS_TOTAL_MB] > 128 + 256 * img->bitdepth_luma + 2 * img->mb_cr_size_y * img->mb_cr_size_x * img->bitdepth_chroma)
printf("Warning!!! Number of bits (%d) of macroblock_layer() data seems to exceed defined limit.\n", bitCount[BITS_TOTAL_MB]);
#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->Transform8x8Mode == 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
*
* \param mb_addr
* macroblock address in scan order
* \param mb_field
* true for field macroblock coding
************************************************************************
*/
void start_macroblock(int mb_addr, int mb_field)
{
int i,j,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);
int prev_mb;
currMB->mb_field = mb_field;
enc_picture->mb_field[mb_addr] = mb_field;
set_MB_parameters (mb_addr);
prev_mb = FmoGetPreviousMBNr(img->current_mb_nr);
if(use_bitstream_backing)
{
if ((!input->MbInterlace)||((mb_addr&1)==0)) // KS: MB AFF -> store stream positions for
// first macroblock only
{
// 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->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 (prev_mb>-1)
{
currMB->prev_qp = img->mb_data[prev_mb].qp;
if (img->mb_data[prev_mb].slice_nr == img->current_slice_nr)
{
currMB->prev_delta_qp = img->mb_data[prev_mb].delta_qp;
}
else
{
currMB->prev_delta_qp = 0;
}
}
else
{
currMB->prev_qp = curr_slice->qp;
currMB->prev_delta_qp = 0;
}
// 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 (prev_mb < 0) //first macroblock (of slice)
{
// 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[prev_mb].prev_cbp == 1)
{
currMB->delta_qp = 0;
currMB->qp = img->qp;
}
else
{
currMB->qp = img->mb_data[prev_mb].prev_qp;
currMB->delta_qp = currMB->qp - img->mb_data[prev_mb].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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -