📄 slice.c
字号:
if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
{
if ( params->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
rc_copy_quadratic( quadratic_RC_init, quadratic_RC ); // save initial RC status
if ( params->MbInterlace == ADAPTIVE_CODING )
rc_copy_generic( generic_RC_init, generic_RC ); // save initial RC status
}
start_macroblock (currSlice, &currMB, CurrentMbAddr, FALSE);
rdopt = &rddata_top_frame_mb; // store data in top frame MB
img->masterQP = img->qp;
encode_one_macroblock (currMB); // code the MB as frame
FrameRDCost = rdopt->min_rdcost;
//*** Top MB coded as frame MB ***//
//Rate control
img->bot_MB = TRUE; //for Rate control
// go to the bottom MB in the MB pair
img->field_mode = FALSE; // MB coded as frame //GB
start_macroblock (currSlice, &currMB, CurrentMbAddr + 1, FALSE);
rdopt = &rddata_bot_frame_mb; // store data in top frame MB
img->masterQP = img->qp;
encode_one_macroblock (currMB); // code the MB as frame
if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
{
if ( params->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
rc_copy_quadratic( quadratic_RC_best, quadratic_RC ); // restore initial RC status
if ( params->MbInterlace == ADAPTIVE_CODING )
rc_copy_generic( generic_RC_best, generic_RC ); // save frame RC stats
}
FrameRDCost += rdopt->min_rdcost;
//*** Bottom MB coded as frame MB ***//
}
if ((params->MbInterlace == ADAPTIVE_CODING) || (params->MbInterlace == FIELD_CODING))
{
//Rate control
img->bot_MB = FALSE;
//set mv limits to field type
update_mv_limits(img, TRUE);
//=========== start coding the MB pair as a field MB pair =============
//---------------------------------------------------------------------
img->field_mode = TRUE; // MB coded as field
img->top_field = TRUE; // Set top field to 1
img->buf_cycle <<= 1;
params->num_ref_frames <<= 1;
img->num_ref_idx_l0_active <<= 1;
img->num_ref_idx_l0_active += 1;
if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
{
if ( params->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
rc_copy_quadratic( quadratic_RC, quadratic_RC_init ); // restore initial RC status
if ( params->MbInterlace == ADAPTIVE_CODING )
rc_copy_generic( generic_RC, generic_RC_init ); // reset RC stats
}
start_macroblock (currSlice, &currMB, CurrentMbAddr, TRUE);
rdopt = &rddata_top_field_mb; // store data in top frame MB
// TopFieldIsSkipped = 0; // set the top field MB skipped flag to 0
img->masterQP = img->qp;
encode_one_macroblock (currMB); // code the MB as field
FieldRDCost = rdopt->min_rdcost;
//*** Top MB coded as field MB ***//
//Rate control
img->bot_MB = TRUE;//for Rate control
img->top_field = FALSE; // Set top field to 0
start_macroblock (currSlice, &currMB, CurrentMbAddr+1, TRUE);
rdopt = &rddata_bot_field_mb; // store data in top frame MB
img->masterQP = img->qp;
encode_one_macroblock (currMB); // code the MB as field
FieldRDCost += rdopt->min_rdcost;
//*** Bottom MB coded as field MB ***//
}
//Rate control
img->write_mbaff_frame = 0; //Rate control
//=========== decide between frame/field MB pair ============
//-----------------------------------------------------------
if ( ((params->MbInterlace == ADAPTIVE_CODING) && (FrameRDCost < FieldRDCost)) || params->MbInterlace == FRAME_MB_PAIR_CODING )
{
img->field_mode = FALSE;
MBPairIsField = FALSE;
if ( params->MbInterlace != FRAME_MB_PAIR_CODING )
{
img->buf_cycle >>= 1;
params->num_ref_frames >>= 1;
img->num_ref_idx_l0_active -= 1;
img->num_ref_idx_l0_active >>= 1;
}
if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
{
if ( params->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
rc_copy_quadratic( quadratic_RC, quadratic_RC_best ); // restore initial RC status
if ( params->MbInterlace == ADAPTIVE_CODING )
rc_copy_generic( generic_RC, generic_RC_best ); // restore frame RC stats
}
//Rate control
img->write_mbaff_frame = 1; //for Rate control
}
else
{
img->field_mode = TRUE;
MBPairIsField = TRUE;
}
//Rate control
img->write_macroblock = TRUE;//Rate control
if (MBPairIsField)
img->top_field = TRUE;
else
img->top_field = FALSE;
//Rate control
img->bot_MB = FALSE;// for Rate control
// go back to the Top MB in the MB pair
start_macroblock (currSlice, &currMB, CurrentMbAddr, img->field_mode);
rdopt = img->field_mode ? &rddata_top_field_mb : &rddata_top_frame_mb;
copy_rdopt_data (currMB, 0); // copy the MB data for Top MB from the temp buffers
write_one_macroblock (currMB, 1, prev_recode_mb); // write the Top MB data to the bitstream
terminate_macroblock (currSlice, currMB, &end_of_slice, &recode_macroblock); // done coding the Top MB
prev_recode_mb = recode_macroblock;
if (recode_macroblock == FALSE) // The final processing of the macroblock has been done
{
img->SumFrameQP += currMB->qp;
CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr);
if (CurrentMbAddr == -1) // end of slice
{
end_of_slice = TRUE;
}
NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice
proceed2nextMacroblock (currMB);
//Rate control
img->bot_MB = TRUE;//for Rate control
// go to the Bottom MB in the MB pair
img->top_field = FALSE;
start_macroblock (currSlice, &currMB, CurrentMbAddr, img->field_mode);
rdopt = img->field_mode ? &rddata_bot_field_mb : &rddata_bot_frame_mb;
copy_rdopt_data (currMB, 1); // copy the MB data for Bottom MB from the temp buffers
write_one_macroblock (currMB, 0, prev_recode_mb); // write the Bottom MB data to the bitstream
terminate_macroblock (currSlice, currMB, &end_of_slice, &recode_macroblock); // done coding the Top MB
prev_recode_mb = recode_macroblock;
if (recode_macroblock == FALSE) // The final processing of the macroblock has been done
{
img->SumFrameQP += currMB->qp;
CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr);
if (CurrentMbAddr == -1) // end of slice
{
end_of_slice = TRUE;
}
NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice
proceed2nextMacroblock (currMB);
}
else
{
//Go back to the beginning of the macroblock pair to recode it
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
img->NumberofCodedMacroBlocks -= 2;
if(img->current_mb_nr == -1 ) // The first MB of the slice group is too big,
// which means it's impossible to encode picture using current slice bits restriction
{
snprintf (errortext, ET_SIZE, "Error encoding first MB with specified parameter, bits of current MB may be too big");
error (errortext, 300);
}
}
}
else
{
//!Go back to the previous MB to recode it
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
img->NumberofCodedMacroBlocks--;
if(img->current_mb_nr == -1 ) // The first MB of the slice group is too big,
// which means it's impossible to encode picture using current slice bits restriction
{
snprintf (errortext, ET_SIZE, "Error encoding first MB with specified parameter, bits of current MB may be too big");
error (errortext, 300);
}
}
if (MBPairIsField) // if MB Pair was coded as field the buffer size variables back to frame mode
{
img->buf_cycle >>= 1;
params->num_ref_frames >>= 1;
img->num_ref_idx_l0_active -= 1;
img->num_ref_idx_l0_active >>= 1;
}
img->field_mode = img->top_field = FALSE; // reset to frame mode
if ( !end_of_slice )
{
assert( CurrentMbAddr < (int)img->PicSizeInMbs );
assert( CurrentMbAddr >= 0 );
if (CurrentMbAddr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (CurrentMbAddr)))
end_of_slice = TRUE; // just in case it doesn't get set in terminate_macroblock
}
}
}
terminate_slice (currSlice, (NumberOfCodedMBs + TotalCodedMBs >= (int)img->PicSizeInMbs), cur_stats );
return NumberOfCodedMBs;
}
/*!
************************************************************************
* \brief
* Initializes the parameters for a new slice and
* allocates the memory for the coded slice in the Picture structure
* \par Side effects:
* Adds slice/partition header symbols to the symbol buffer
* increments Picture->no_slices, allocates memory for the
* slice, sets img->currSlice
************************************************************************
*/
void init_slice (Slice **currSlice, int start_mb_addr)
{
int i,j;
Picture *currPic = img->currentPicture;
DataPartition *dataPart;
Bitstream *currStream;
int active_ref_lists = (img->MbaffFrameFlag) ? 6 : 2;
img->current_mb_nr = start_mb_addr;
// Allocate new Slice in the current Picture, and set img->currentSlice
assert (currPic != NULL);
currPic->no_slices++;
if (currPic->no_slices >= MAXSLICEPERPICTURE)
error ("Too many slices per picture, increase MAXSLICEPERPICTURE in global.h.", -1);
currPic->slices[currPic->no_slices-1] = malloc_slice();
*currSlice = currPic->slices[currPic->no_slices-1];
img->currentSlice = *currSlice;
(*currSlice)->picture_id = img->tr % 256;
(*currSlice)->qp = img->qp;
(*currSlice)->start_mb_nr = start_mb_addr;
(*currSlice)->slice_too_big = dummy_slice_too_big;
for (i = 0; i < (*currSlice)->max_part_nr; i++)
{
dataPart = &(*currSlice)->partArr[i];
currStream = dataPart->bitstream;
currStream->bits_to_go = 8;
currStream->byte_pos = 0;
currStream->byte_buf = 0;
}
img->num_ref_idx_l0_active = active_pps->num_ref_idx_l0_active_minus1 + 1;
img->num_ref_idx_l1_active = active_pps->num_ref_idx_l1_active_minus1 + 1;
// primary and redundant slices: number of references overriding.
if(params->redundant_pic_flag)
{
if(!redundant_coding)
{
img->num_ref_idx_l0_active = imin(img->number,params->NumRefPrimary);
}
else
{
// 1 reference picture for redundant slices
img->num_ref_idx_l0_active = 1;
}
}
// code now also considers fields. Issue whether we should account this within the appropriate input params directly
if ((img->type == P_SLICE || img->type == SP_SLICE) && params->P_List0_refs)
{
img->num_ref_idx_l0_active = imin(img->num_ref_idx_l0_active, params->P_List0_refs * ((img->structure !=0) + 1));
}
if (img->type == B_SLICE )
{
if (params->B_List0_refs)
{
img->num_ref_idx_l0_active = imin(img->num_ref_idx_l0_active, params->B_List0_refs * ((img->structure !=0) + 1));
}
if (params->B_List1_refs)
{
img->num_ref_idx_l1_active = imin(img->num_ref_idx_l1_active, params->B_List1_refs * ((img->structure !=0) + 1));
}
}
// generate reference picture lists
init_lists(img->type, (PictureStructure) img->structure);
// assign list 0 size from list size
img->num_ref_idx_l0_active = listXsize[0];
img->num_ref_idx_l1_active = listXsize[1];
if ( params->WPMCPrecision && params->WPMCPrecFullRef )
{
wpxAdaptRefNum(img);
}
//Perform memory management based on poc distances
if (img->nal_reference_idc && params->PocMemoryManagement)
{
if (img->structure == FRAME && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
{
poc_based_ref_management_frame_pic(img->frame_num);
}
else if (img->structure == TOP_FIELD && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
{
poc_based_ref_management_field_pic((img->frame_num << 1) + 1);
}
else if (img->structure == BOTTOM_FIELD)
poc_based_ref_management_field_pic((img->frame_num << 1) + 1);
}
if (params->EnableOpenGOP)
{
for (i = 0; i<listXsize[0]; i++)
{
if (listX[0][i]->poc < img->last_valid_reference && img->ThisPOC > img->last_valid_reference)
{
listXsize[0] = img->num_ref_idx_l0_active = imax(1, i);
break;
}
}
for (i = 0; i<listXsize[1]; i++)
{
if (listX[1][i]->poc < img->last_valid_reference && img->ThisPOC > img->last_valid_reference)
{
listXsize[1] = img->num_ref_idx_l1_active = imax(1,i);
break;
}
}
}
init_ref_pic_list_reordering(*currSlice);
// reference list reordering
if ( (img->type == P_SLICE || img->type == B_SLICE) &&
params->WPMCPrecision && pWPX->curr_wp_rd_pass->algorithm != WP_REGULAR )
{
wpxReorderLists( img, *currSlice );
}
else
{
// Perform reordering based on poc distances for HierarchicalCoding
if ( img->type == P_SLICE && params->ReferenceReorder)
{
int i, num_ref;
alloc_ref_pic_list_reordering_buffer(*currSlice);
for (i = 0; i < img->num_ref_idx_l0_active + 1; i++)
{
(*currSlice)->reordering_of_pic_nums_idc_l0[i] = 3;
(*currSlice)->abs_diff_pic_num_minus1_l0[i] = 0;
(*currSlice)->long_term_pic_idx_l0[i] = 0;
}
num_ref = img->num_ref_idx_l0_active;
if ( img->structure == FRAME )
poc_ref_pic_reorder_frame(listX[LIST_0], num_ref,
(*currSlice)->reordering_of_pic_nums_idc_l0,
(*currSlice)->abs_diff_pic_num_minus1_l0,
(*currSlice)->long_term_pic_idx_l0, LIST_0);
else
{
poc_ref_pic_reorder_field(listX[LIST_0], num_ref,
(*currSlice)->reordering_of_pic_nums_idc_l0,
(*currSlice)->abs_diff_pic_num_minus1_l0,
(*currSlice)->long_term_pic_idx_l0, LIST_0);
}
//reference picture reordering
reorder_ref_pic_list(listX[LIST_0], &listXsize[LIST_0],
img->num_ref_idx_l0_active - 1,
(*currSlice)->reordering_of_pic_nums_idc_l0,
(*currSlice)->abs_diff_pic_num_minus1_l0,
(*currSlice)->long_term_pic_idx_l0);
}
}
//if (img->MbaffFrameFlag)
if (img->structure==FRAME)
init_mbaff_lists();
InitWP(params);
if (img->type != I_SLICE && (active_pps->weighted_pred_flag == 1 || (active_pps->weighted_bipred_idc > 0 && (img->type == B_SLICE))))
{
if (img->type==P_SLICE || img->type==SP_SLICE)
{
int wp_type = (params->GenerateMultiplePPS && params->RDPictureDecision) && (enc_picture != enc_frame_picture[1]);
EstimateWPPSlice (img, params, wp_type);
}
else
EstimateWPBSlice (img, params);
}
set_ref_pic_num();
if (img->type == B_SLICE)
{
if( IS_INDEPENDENT(params) )
{
compute_colocated_JV(Co_located, listX);
}
else
{
compute_colocated(Co_located, listX);
}
}
if (img->type != I_SLICE && params->SearchMode == EPZS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -