📄 macroblock.c
字号:
currMB->bitcounter[BITS_INTER_MB ] = 0;
currMB->bitcounter[BITS_CBP_MB ] = 0;
currMB->bitcounter[BITS_COEFF_Y_MB ] = 0;
currMB->bitcounter[BITS_COEFF_UV_MB ] = 0;
currMB->bitcounter[BITS_COEFF_CB_MB ] = 0;
currMB->bitcounter[BITS_COEFF_CR_MB ] = 0;
currMB->bitcounter[BITS_DELTA_QUANT_MB] = 0;
currMB->bitcounter[BITS_STUFFING ] = 0;
}
/*!
************************************************************************
* \brief
* initializes the current macroblock
*
* \param currMB
* current macroblock
* \param mb_addr
* current macroblock address
* \param mb_field
* true for field macroblock coding
************************************************************************
*/
void start_macroblock(Slice *curr_slice, Macroblock **currMB, int mb_addr, byte mb_field)
{
int i, mb_qp;
int use_bitstream_backing = (params->slice_mode == FIXED_RATE || params->slice_mode == CALL_BACK);
DataPartition *dataPart;
Bitstream *currStream;
int prev_mb;
*currMB = &img->mb_data[mb_addr];
(*currMB)->mbAddrX = mb_addr;
(*currMB)->mb_field = mb_field;
enc_picture->motion.mb_field[mb_addr] = mb_field;
(*currMB)->is_field_mode = (img->field_picture || ( img->MbaffFrameFlag && (*currMB)->mb_field));
set_MB_parameters (mb_addr);
prev_mb = FmoGetPreviousMBNr(img->current_mb_nr);
if ( params->ChromaMCBuffer )
OneComponentChromaPrediction4x4 = OneComponentChromaPrediction4x4_retrieve;
else
OneComponentChromaPrediction4x4 = OneComponentChromaPrediction4x4_regenerate;
if(use_bitstream_backing)
{
if ((!params->MbInterlace)||((mb_addr & 0x01)==0)) // KS: MB AFF -> store stream positions for 1st MB 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;
stats->stored_bit_slice = stats->bit_slice;
if (curr_slice->symbol_mode ==CABAC)
{
dataPart->ee_recode = dataPart->ee_cabac;
}
}
}
}
}
// 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 (prev_mb > -1 && (img->mb_data[prev_mb].slice_nr == img->current_slice_nr))
{
(*currMB)->prev_qp = img->mb_data[prev_mb].qp;
(*currMB)->prev_dqp = img->mb_data[prev_mb].delta_qp;
}
else
{
(*currMB)->prev_qp = curr_slice->qp;
(*currMB)->prev_dqp = 0;
}
if(params->RCEnable)
mb_qp = rc_handle_mb( prev_mb, *currMB, curr_slice );
else
{
mb_qp = img->qp;
}
mb_qp = iClip3(-img->bitdepth_luma_qp_scale, 51, mb_qp);
(*currMB)->qp = img->qp = mb_qp;
(*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;
update_qp (img, *currMB);
// deblocking filter parameter
if (active_pps->deblocking_filter_control_present_flag)
{
(*currMB)->DFDisableIdc = img->DFDisableIdc;
(*currMB)->DFAlphaC0Offset = img->DFAlphaC0Offset;
(*currMB)->DFBetaOffset = img->DFBetaOffset;
}
else
{
(*currMB)->DFDisableIdc = 0;
(*currMB)->DFAlphaC0Offset = 0;
(*currMB)->DFBetaOffset = 0;
}
// If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction
CheckAvailabilityOfNeighbors(*currMB);
if (curr_slice->symbol_mode == CABAC)
CheckAvailabilityOfNeighborsCABAC(*currMB);
reset_macroblock(*currMB, prev_mb);
if ((params->SearchMode == FAST_FULL_SEARCH) && (!params->IntraProfile))
ResetFastFullIntegerSearch ();
// disable writing of trace file
#if TRACE
for (i=0; i<curr_slice->max_part_nr; i++ )
{
curr_slice->partArr[i].bitstream->trace_enabled = FALSE;
}
#endif
}
/*!
************************************************************************
* \brief
* terminates processing of the current macroblock depending
* on the chosen slice mode
************************************************************************
*/
void terminate_macroblock(Slice *currSlice, //!< Current slice
Macroblock *currMB, //!< Current Macroblock
Boolean *end_of_slice, //!< returns true for last macroblock of a slice, otherwise false
Boolean *recode_macroblock //!< returns true if max. slice size is exceeded an macroblock must be recoded in next slice
)
{
int i;
SyntaxElement se;
int *partMap = assignSE2partition[params->partition_mode];
DataPartition *dataPart;
Bitstream *currStream;
int rlc_bits=0;
int use_bitstream_backing = (params->slice_mode == FIXED_RATE || params->slice_mode == CALL_BACK);
static int skip = FALSE;
int new_slice = 0;
// if previous mb in the same slice group has different slice number as the current, it's the
// the start of new slice
if ((img->current_mb_nr==0) || (FmoGetPreviousMBNr(img->current_mb_nr)<0) || ( img->mb_data[FmoGetPreviousMBNr(img->current_mb_nr)].slice_nr != img->current_slice_nr ))
new_slice=1;
*recode_macroblock=FALSE;
switch(params->slice_mode)
{
case NO_SLICES:
currSlice->num_mb++;
*recode_macroblock = FALSE;
if ((currSlice->num_mb) == (int)img->PicSizeInMbs) // maximum number of MBs reached
*end_of_slice = TRUE;
// if it's end of current slice group, slice ends too
*end_of_slice = (Boolean) (*end_of_slice | (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr))));
break;
case FIXED_MB:
// For slice mode one, check if a new slice boundary follows
currSlice->num_mb++;
*recode_macroblock = FALSE;
//! Check end-of-slice group condition first
*end_of_slice = (Boolean) (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr)));
//! Now check maximum # of MBs in slice
*end_of_slice = (Boolean) (*end_of_slice | (currSlice->num_mb >= params->slice_argument));
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 CAVLC (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
se.value1 = img->cod_counter;
se.value2 = 0;
se.type = SE_MBTYPE;
dataPart = &(currSlice->partArr[partMap[se.type]]);
TRACE_SE (se.tracestring, "mb_skip_run");
writeSE_UVLC(&se, dataPart);
rlc_bits=se.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(currSlice, rlc_bits))
{
*recode_macroblock = TRUE;
*end_of_slice = TRUE;
}
else if(!img->cod_counter)
skip = FALSE;
}
// maximum number of MBs
// check if current slice group is finished
if ((*recode_macroblock == FALSE) && (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr))))
{
*end_of_slice = TRUE;
if(!img->cod_counter)
skip = FALSE;
}
//! (first MB OR first MB in a slice) AND bigger that maximum size of slice
if (new_slice && slice_too_big(currSlice, rlc_bits))
{
*end_of_slice = TRUE;
if(!img->cod_counter)
skip = FALSE;
}
if (!*recode_macroblock)
currSlice->num_mb++;
break;
case CALL_BACK:
if (img->current_mb_nr > 0 && !new_slice)
{
if (currSlice->slice_too_big(rlc_bits))
{
*recode_macroblock = TRUE;
*end_of_slice = TRUE;
}
}
if ( (*recode_macroblock == FALSE) && (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr))))
*end_of_slice = TRUE;
break;
default:
snprintf(errortext, ET_SIZE, "Slice Mode %d not supported", params->slice_mode);
error(errortext, 600);
}
if (*recode_macroblock == TRUE)
{
// Restore everything
for (i=0; i<currSlice->max_part_nr; i++)
{
dataPart = &(currSlice->partArr[i]);
currStream = dataPart->bitstream;
currStream->bits_to_go = currStream->stored_bits_to_go;
currStream->byte_pos = currStream->stored_byte_pos;
currStream->byte_buf = currStream->stored_byte_buf;
stats->bit_slice = stats->stored_bit_slice;
if (currSlice->symbol_mode == CABAC)
{
dataPart->ee_cabac = dataPart->ee_recode;
}
}
}
if (currSlice->symbol_mode == CAVLC)
{
// Skip MBs at the end of this slice
dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);
if(*end_of_slice == TRUE && skip == TRUE)
{
// only for Slice Mode 2 or 3
// If we still have to write the skip, let's do it!
if(img->cod_counter && *recode_macroblock == TRUE) // MB that did not fit in this slice
{
// If recoding is true and we have had skip,
// we have to reduce the counter in case of recoding
img->cod_counter--;
if(img->cod_counter)
{
se.value1 = img->cod_counter;
se.value2 = 0;
se.type = SE_MBTYPE;
#if TRACE
snprintf(se.tracestring, TRACESTRING_SIZE, "Final MB runlength = %3d",img->cod_counter);
#endif
writeSE_UVLC(&se, dataPart);
rlc_bits=se.len;
currMB->bitcounter[BITS_MB_MODE]+=rlc_bits;
img->cod_counter = 0;
}
}
else //! MB that did not fit in this slice anymore is not a Skip MB
{
currStream = dataPart->bitstream;
// update the bitstream
currStream->bits_to_go = currStream->bits_to_go_skip;
currStream->byte_pos = currStream->byte_pos_skip;
currStream->byte_buf = currStream->byte_buf_skip;
// update the statistics
img->cod_counter = 0;
skip = FALSE;
}
}
// Skip MBs at the end of this slice for Slice Mode 0 or 1
if(*end_of_slice == TRUE && img->cod_counter && !use_bitstream_backing)
{
se.value1 = img->cod_counter;
se.value2 = 0;
se.type = SE_MBTYPE;
TRACE_SE (se.tracestring, "mb_skip_run");
writeSE_UVLC(&se, dataPart);
rlc_bits=se.len;
currMB->bitcounter[BITS_MB_MODE]+=rlc_bits;
img->cod_counter = 0;
}
}
}
/*!
*****************************************************************************
*
* \brief
* For Slice Mode 2: Checks if one partition of one slice exceeds the
* allowed size
*
* \return
* FALSE if all Partitions of this slice are smaller than the allowed size
* TRUE is at least one Partition exceeds the limit
*
* \par Side effects
* none
*
* \date
* 4 November 2001
*
* \author
* Tobias Oelbaum drehvial@gmx.net
*****************************************************************************/
int slice_too_big(Slice *currSlice, int rlc_bits)
{
DataPartition *dataPart;
Bitstream *currStream;
EncodingEnvironmentPtr eep;
int i;
int size_in_bytes;
//! CAVLC
if (currSlice->symbol_mode == CAVLC)
{
for (i=0; i<currSlice->max_part_nr; i++)
{
dataPart = &(currSlice->partArr[i]);
currStream = dataPart->bitstream;
size_in_bytes = currStream->byte_pos /*- currStream->tmp_byte_pos*/;
if (currStream->bits_to_go < 8)
size_in_bytes++;
if (currStream->bits_to_go < rlc_bits)
size_in_bytes++;
if(size_in_bytes > params->slice_argument)
return TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -