📄 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 <math.h>
#include <stdlib.h>
#include <assert.h>
#include "elements.h"
#include "macroblock.h"
#include "refbuf.h"
#include "fmo.h"
#include "vlc.h"
#include "image.h"
#include "mb_access.h"
/*!
************************************************************************
* \brief
* updates the coordinates for the next macroblock to be processed
*
* \input
* mb: MB address in scan order
************************************************************************
*/
void set_MB_parameters (int mb)
{
const int number_mb_per_row = img->width / MB_BLOCK_SIZE ;
img->current_mb_nr = mb;
img->mb_x = mb % number_mb_per_row;
img->mb_y = mb / number_mb_per_row;
// printf ("Set_MB_Parameters: mb %d, mb_x %d, mb_y %d\n", mb, img->mb_x, img->mb_y);
// Define vertical positions
img->block_y = img->mb_y * BLOCK_SIZE; // vertical luma block position
img->pix_y = img->mb_y * MB_BLOCK_SIZE; // vertical luma macroblock position
img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; // vertical chroma macroblock position
// Define horizontal positions
img->block_x = img->mb_x * BLOCK_SIZE; // luma block
img->pix_x = img->mb_x * MB_BLOCK_SIZE; // luma pixel
img->block_c_x = img->mb_x * BLOCK_SIZE/2; // chroma block
img->pix_c_x = img->mb_x * MB_BLOCK_SIZE/2; // chroma pixel
if(input->InterlaceCodingOption >= MB_CODING && mb_adaptive && img->field_mode)
{
if(img->top_field)
{
img->field_mb_y = img->mb_y/2;
img->field_pix_y = img->field_mb_y*MB_BLOCK_SIZE;
img->field_block_y = img->field_mb_y*BLOCK_SIZE;
img->field_pix_c_y = img->field_mb_y*MB_BLOCK_SIZE/2;
}
else
{
img->field_mb_y = (img->mb_y-1)/2;
img->field_pix_y = img->field_mb_y*MB_BLOCK_SIZE;
img->field_block_y = img->field_mb_y*BLOCK_SIZE;
img->field_pix_c_y = img->field_mb_y*MB_BLOCK_SIZE/2;
}
}
}
int clip1a(int a)
{
return ((a)>255?255:((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;
#if TRACE
int i;
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
stat->bit_use_mb_type[img->type] += bitCount[BITS_MB_MODE];
stat->bit_use_coeffY[img->type] += bitCount[BITS_COEFF_Y_MB] ;
stat->tmp_bit_use_cbp[img->type] += bitCount[BITS_CBP_MB];
stat->bit_use_coeffC[img->type] += bitCount[BITS_COEFF_UV_MB];
stat->bit_use_delta_quant[img->type] += bitCount[BITS_DELTA_QUANT_MB];
if (img->type==I_SLICE)
++stat->mode_use_intra[currMB->mb_type];
else
if (img->type != B_SLICE)
{
++stat->mode_use_inter[0][currMB->mb_type];
stat->bit_use_mode_inter[0][currMB->mb_type]+= bitCount[BITS_INTER_MB];
}
else
{
stat->bit_use_mode_inter[1][currMB->mb_type]+= bitCount[BITS_INTER_MB];
++stat->mode_use_inter[1][currMB->mb_type];
}
// Statistics
if ((img->type == P_SLICE)||(img->type==SP_SLICE) )
{
++stat->quant0;
stat->quant1 += img->qp; // to find average quant for inter frames
}
}
/*!
************************************************************************
* \brief
* initializes the current macroblock
************************************************************************
*/
void start_macroblock()
{
int i,j,k,l;
int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
Slice *curr_slice = img->currentSlice;
DataPartition *dataPart;
Bitstream *currStream;
EncodingEnvironmentPtr eep;
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
currMB->delta_qp = 0;
currMB->qp = img->qp; // needed in loop filter (even if constant QP is used)
// Initialize counter for MB symbols
currMB->currSEnr=0;
// If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction
CheckAvailabilityOfNeighbors(img);
// Reset vectors before doing motion search in motion_search().
if (img->type != B_SLICE)
{
for (k=0; k < 2; k++)
{
for (j=0; j < BLOCK_MULTIPLE; j++)
for (i=0; i < BLOCK_MULTIPLE; i++)
tmp_mv[k][img->block_y+j][img->block_x+i+4]=0;
}
}
for (l=0; l<2; l++)
{
for (j=0; j < BLOCK_MULTIPLE; j++)
for (i=0; i < BLOCK_MULTIPLE; i++)
for (k=0; k < 2; k++)
enc_picture->mv[l][img->block_x+i][img->block_y+j][k]=0;
}
//initialize reference index
for (j=0; j < BLOCK_MULTIPLE; j++)
{
for (i=0; i < BLOCK_MULTIPLE; i++)
for (l=0; l<2; l++)
{
enc_picture->ref_idx[l][img->block_x+i][img->block_y + j] =-1;
enc_picture->ref_pic_id[l][img->block_x+i][img->block_y+j] = -1;
}
}
// Reset syntax element entries in MB struct
currMB->mb_type = 0;
currMB->cbp_blk = 0;
currMB->cbp = 0;
currMB->mb_field = 0;
for (l=0; l < 2; l++)
for (j=0; j < BLOCK_MULTIPLE; j++)
for (i=0; i < BLOCK_MULTIPLE; i++)
for (k=0; k < 2; k++)
currMB->mvd[l][j][i][k] = 0;
currMB->cbp_bits = 0;
currMB->c_ipred_mode = DC_PRED_8; //GB
for (i=0; i < (BLOCK_MULTIPLE*BLOCK_MULTIPLE); i++)
currMB->intra_pred_modes[i] = DC_PRED;
//initialize the whole MB as INTRA coded
//Blocks ar set to notINTRA in write_one_macroblock
if (input->UseConstrainedIntraPred)
{
img->intra_block[img->current_mb_nr] = 1;
}
// store filtering parameters for this MB; For now, we are using the
// same offset throughout the sequence
currMB->lf_disable = input->LFDisableIdc;
currMB->lf_alpha_c0_offset = input->LFAlphaC0Offset;
currMB->lf_beta_offset = input->LFBetaOffset;
// Initialize bitcounters for this macroblock
if(img->current_mb_nr == 0) // No slice header to account for
{
currMB->bitcounter[BITS_HEADER] = 0;
}
else if (currMB->slice_nr == img->mb_data[img->current_mb_nr-1].slice_nr) // current MB belongs to the
// same slice as the last MB
{
currMB->bitcounter[BITS_HEADER] = 0;
}
currMB->bitcounter[BITS_MB_MODE] = 0;
currMB->bitcounter[BITS_COEFF_Y_MB] = 0;
currMB->bitcounter[BITS_INTER_MB] = 0;
currMB->bitcounter[BITS_CBP_MB] = 0;
currMB->bitcounter[BITS_DELTA_QUANT_MB] = 0;
currMB->bitcounter[BITS_COEFF_UV_MB] = 0;
#ifdef _FAST_FULL_ME_
ResetFastFullIntegerSearch ();
#endif
}
/*!
************************************************************************
* \brief
* terminates processing of the current macroblock depending
* on the chosen slice mode
************************************************************************
*/
void terminate_macroblock(Boolean *end_of_slice, Boolean *recode_macroblock)
{
int i;
Slice *currSlice = img->currentSlice;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
SyntaxElement *currSE = &img->MB_SyntaxElements[currMB->currSEnr];
int *partMap = assignSE2partition[input->partition_mode];
DataPartition *dataPart;
Bitstream *currStream;
int rlc_bits=0;
EncodingEnvironmentPtr eep;
int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
int new_slice = ( (img->current_mb_nr == 0) || img->mb_data[img->current_mb_nr-1].slice_nr != img->current_slice_nr);
static int skip = FALSE;
switch(input->slice_mode)
{
case NO_SLICES:
currSlice->num_mb++;
*recode_macroblock = FALSE;
if ((currSlice->num_mb) == img->total_number_mb) // maximum number of MBs reached
*end_of_slice = TRUE;
break;
case FIXED_MB:
// For slice mode one, check if a new slice boundary follows
currSlice->num_mb++;
*recode_macroblock = FALSE;
*end_of_slice = (currSlice->num_mb >= input->slice_argument); // End of Slice
*end_of_slice |= (img->current_mb_nr+1) == img->total_number_mb; // End of Picture condition
break;
// For slice modes two and three, check if coding of this macroblock
// resulted in too many bits for this slice. If so, indicate slice
// boundary before this macroblock and code the macroblock again
case FIXED_RATE:
// in case of skip MBs check if there is a slice boundary
// only for UVLC (img->cod_counter is always 0 in case of CABAC)
if(img->cod_counter)
{
// write out the skip MBs to know how many bits we need for the RLC
currSE->value1 = img->cod_counter;
currSE->mapping = ue_linfo;
currSE->type = SE_MBTYPE;
if (img->type != B_SLICE) dataPart = &(currSlice->partArr[partMap[currSE->type]]);
else dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
dataPart->writeSyntaxElement( currSE, dataPart);
rlc_bits=currSE->len;
currStream = dataPart->bitstream;
// save the bitstream as it would be if we write the skip MBs
currStream->bits_to_go_skip = currStream->bits_to_go;
currStream->byte_pos_skip = currStream->byte_pos;
currStream->byte_buf_skip = currStream->byte_buf;
// restore the bitstream
currStream->bits_to_go = currStream->stored_bits_to_go;
currStream->byte_pos = currStream->stored_byte_pos;
currStream->byte_buf = currStream->stored_byte_buf;
skip = TRUE;
}
//! Check if the last coded macroblock fits into the size of the slice
//! But only if this is not the first macroblock of this slice
if (!new_slice)
{
if(slice_too_big(rlc_bits))
{
*recode_macroblock = TRUE;
*end_of_slice = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -