📄 slice.c
字号:
{
//!Go back to the previous MB to recode it
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
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 // TBD -- Addition of FMO
{
//! This following ugly code breaks slices, at least for a slice mode that accumulates a certain
//! number of bits into one slice.
//! The suggested algorithm is as follows:
//!
//! SaveState (Bitstream, stats, etc. etc.);
//! BitsForThisMBPairInFrameMode = CodeMB (Upper, FRAME_MODE) + CodeMB (Lower, FRAME_MODE);
//! DistortionForThisMBPairInFrameMode = CalculateDistortion(Upper) + CalculateDistortion (Lower);
//! RestoreState();
//! BitsForThisMBPairInFieldMode = CodeMB (Upper, FIELD_MODE) + CodeMB (Lower, FIELD_MODE);
//! DistortionForThisMBPairInFrameMode = CalculateDistortion(Upper) + CalculateDistortion (Lower);
//! FrameFieldMode = Decision (...)
//! RestoreState()
//! if (FrameFieldMode == FRAME) {
//! CodeMB (Upper, FRAME); CodeMB (Lower, FRAME);
//! } else {
//! CodeMB (Upper FIELD); CodeMB (Lower, FIELD);
//! }
//!
//! Open questions/issues:
//! 1. CABAC/CA-VLC state: It seems that the CABAC/CA_VLC states are changed during the
//! dummy encoding processes (for the R-D based selection), but that they are never
//! reset, once the selection is made. I believe that this breaks the MB-adaptive
//! frame/field coding. The necessary code for the state saves is readily available
//! in macroblock.c, start_macroblock() and terminate_macroblock() (this code needs
//! to be double checked that it works with CA-VLC as well
//! 2. would it be an option to allocate Bitstreams with zero data in them (or copy the
//! already generated bitstream) for the "test coding"?
if (input->MbInterlace == ADAPTIVE_CODING)
{
//================ code MB pair as frame MB ================
//----------------------------------------------------------
recode_macroblock = FALSE;
img->field_mode = 0; // MB coded as frame
img->top_field = 0; // Set top field to 0
//Rate control
img->write_macroblock = 0;
img->bot_MB = 0;
start_macroblock (CurrentMbAddr, FALSE);
rdopt = &rddata_top_frame_mb; // store data in top frame MB
#ifdef ADAPTIVE_FD_SD_CODING
currMB = &img->mb_data[CurrentMbAddr];
if (img->APEC_in_FD_and_SD==0)
{
currMB->SD_Coding_on_off=0;//Turn SD Coding off
encode_one_macroblock ();
}
else
{
store_coding_state(cs_slice_coding1);
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;//Turn SD Coding on
encode_one_macroblock ();
store_rdopt_data_for_FDSD_coding ();
store_rdopt_data_for_FDSD_coding_interlace ();
write_one_macroblock (1); // write the Top MB data to the bitstream
rate_only_FD=stats->bit_slice-slice_bits;
SSD_only_FD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_only_FD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_only_FD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
slice_bits=stats->bit_slice;
reset_coding_state(cs_slice_coding1);
currMB->SD_Coding_on_off=0;
encode_one_macroblock ();
write_one_macroblock (1); // write the Top MB data to the bitstream
rate_FD_and_SD=stats->bit_slice-slice_bits;
reset_coding_state(cs_slice_coding1);
SSD_FD_and_SD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_FD_and_SD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_FD_and_SD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
rd_cost_only_FD =(double)SSD_only_FD +img->lambda_md[img->type][img->qp] * (double)rate_only_FD;
rd_cost_FD_and_SD=(double)SSD_FD_and_SD+img->lambda_md[img->type][img->qp] * (double)rate_FD_and_SD;
if (rd_cost_only_FD<rd_cost_FD_and_SD)
{
restore_rdopt_data_for_FDSD_coding();
restore_rdopt_data_for_FDSD_coding_interlace ();
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;
}
}
#else
encode_one_macroblock (); // code the MB as frame
#endif
FrameRDCost = rdopt->min_rdcost;
//*** Top MB coded as frame MB ***//
//Rate control
img->bot_MB = 1; //for Rate control
// go to the bottom MB in the MB pair
img->field_mode = 0; // MB coded as frame //GB
start_macroblock (CurrentMbAddr+1, FALSE);
rdopt = &rddata_bot_frame_mb; // store data in top frame MB
#ifdef ADAPTIVE_FD_SD_CODING
currMB = &img->mb_data[CurrentMbAddr+1];
if (img->APEC_in_FD_and_SD==0)
{
currMB->SD_Coding_on_off=0;//Turn SD Coding off
encode_one_macroblock ();
}
else
{
store_coding_state(cs_slice_coding1);
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;//Turn SD Coding on
encode_one_macroblock ();
store_rdopt_data_for_FDSD_coding();
store_rdopt_data_for_FDSD_coding_interlace ();
write_one_macroblock (0); // write the Bottom MB data to the bitstream
rate_only_FD=stats->bit_slice-slice_bits;
SSD_only_FD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_only_FD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_only_FD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
slice_bits=stats->bit_slice;
reset_coding_state(cs_slice_coding1);
currMB->SD_Coding_on_off=0;
encode_one_macroblock ();
write_one_macroblock (0); // write the Bottom MB data to the bitstream
reset_coding_state(cs_slice_coding1);
rate_FD_and_SD=stats->bit_slice-slice_bits;
SSD_FD_and_SD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_FD_and_SD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_FD_and_SD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
rd_cost_only_FD =(double)SSD_only_FD +img->lambda_md[img->type][img->qp] * (double)rate_only_FD;
rd_cost_FD_and_SD=(double)SSD_FD_and_SD+img->lambda_md[img->type][img->qp] * (double)rate_FD_and_SD;
if (rd_cost_only_FD<rd_cost_FD_and_SD)
{
restore_rdopt_data_for_FDSD_coding();
restore_rdopt_data_for_FDSD_coding_interlace ();
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;
}
}
#else
encode_one_macroblock (); // code the MB as frame
#endif
FrameRDCost += rdopt->min_rdcost;
//*** Bottom MB coded as frame MB ***//
}
if ((input->MbInterlace == ADAPTIVE_CODING) || (input->MbInterlace == FIELD_CODING))
{
//Rate control
img->bot_MB = 0;
//=========== start coding the MB pair as a field MB pair =============
//---------------------------------------------------------------------
img->field_mode = 1; // MB coded as field
img->top_field = 1; // Set top field to 1
img->buf_cycle <<= 1;
input->num_ref_frames <<= 1;
img->num_ref_idx_l0_active <<= 1;
img->num_ref_idx_l0_active += 1;
start_macroblock (CurrentMbAddr, TRUE);
rdopt = &rddata_top_field_mb; // store data in top frame MB
// TopFieldIsSkipped = 0; // set the top field MB skipped flag to 0
#ifdef ADAPTIVE_FD_SD_CODING
currMB = &img->mb_data[CurrentMbAddr];
if (img->APEC_in_FD_and_SD==0)
{
currMB->SD_Coding_on_off=0;//Turn SD Coding off
encode_one_macroblock ();
}
else
{
store_coding_state(cs_slice_coding1);
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;//Turn SD Coding on
encode_one_macroblock ();
store_rdopt_data_for_FDSD_coding();
store_rdopt_data_for_FDSD_coding_interlace ();
write_one_macroblock (1);
rate_only_FD=stats->bit_slice-slice_bits;
reset_coding_state(cs_slice_coding1);
SSD_only_FD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_only_FD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_only_FD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=0;
encode_one_macroblock ();
write_one_macroblock (1);
rate_FD_and_SD=stats->bit_slice-slice_bits;
reset_coding_state(cs_slice_coding1);
SSD_FD_and_SD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_FD_and_SD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_FD_and_SD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
rd_cost_only_FD =(double)SSD_only_FD +img->lambda_md[img->type][img->qp] * (double)rate_only_FD;
rd_cost_FD_and_SD=(double)SSD_FD_and_SD+img->lambda_md[img->type][img->qp] * (double)rate_FD_and_SD;
if (rd_cost_only_FD<rd_cost_FD_and_SD)
{
restore_rdopt_data_for_FDSD_coding ();
restore_rdopt_data_for_FDSD_coding_interlace ();
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;
}
}
#else
encode_one_macroblock (); // code the MB as frame
#endif
FieldRDCost = rdopt->min_rdcost;
//*** Top MB coded as field MB ***//
//Rate control
img->bot_MB = 1;//for Rate control
img->top_field = 0; // Set top field to 0
start_macroblock (CurrentMbAddr+1, TRUE);
rdopt = &rddata_bot_field_mb; // store data in top frame MB
#ifdef ADAPTIVE_FD_SD_CODING
currMB = &img->mb_data[CurrentMbAddr+1];
if (img->APEC_in_FD_and_SD==0)
{
currMB->SD_Coding_on_off=0;//Turn SD Coding off
encode_one_macroblock ();
}
else
{
store_coding_state(cs_slice_coding1);
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;//Turn SD Coding on
encode_one_macroblock ();
store_rdopt_data_for_FDSD_coding ();
store_rdopt_data_for_FDSD_coding_interlace ();
write_one_macroblock (0);
rate_only_FD=stats->bit_slice-slice_bits;
reset_coding_state(cs_slice_coding1);
SSD_only_FD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_only_FD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_only_FD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=0;
write_one_macroblock (0);
encode_one_macroblock ();
rate_FD_and_SD=stats->bit_slice-slice_bits;
reset_coding_state(cs_slice_coding1);
SSD_FD_and_SD=0;
for (i=0;i<16;i++)
{
for (j=0;j<16;j++)
{
#ifdef INTERNAL_BIT_DEPTH_INCREASE
SSD_FD_and_SD+=SQR_DEPTH(enc_picture->imgY[img->pix_y+j][img->pix_x+i], imgY_org[img->opix_y+j][img->opix_x+i], input->BitDepthLuma, img->BitDepthIncrease);
#else
SSD_FD_and_SD+=img->quad[enc_picture->imgY[img->pix_y+j][img->pix_x+i]-imgY_org[img->opix_y+j][img->opix_x+i]];
#endif
}
}
rd_cost_only_FD =(double)SSD_only_FD +img->lambda_md[img->type][img->qp] * (double)rate_only_FD;
rd_cost_FD_and_SD=(double)SSD_FD_and_SD+img->lambda_md[img->type][img->qp] * (double)rate_FD_and_SD;
if (rd_cost_only_FD<rd_cost_FD_and_SD)
{
restore_rdopt_data_for_FDSD_coding();
restore_rdopt_data_for_FDSD_coding_interlace ();
slice_bits=stats->bit_slice;
currMB->SD_Coding_on_off=1;
}
}
#else
encode_one_macroblock (); // code the MB as frame
#endif
FieldRDCost += rdopt->min_rdcost;
//*** Bottom MB coded as field MB ***//
}
//Rate control
img->write_macroblock_frame = 0; //Rate control
//=========== decide between frame/field MB pair ============
//-----------------------------------------------------------
if ((input->MbInterlace == ADAPTIVE_CODING) && (FrameRDCost < FieldRDCost))
{
img->field_mode = 0;
img->buf_cycle >>= 1;
input->num_ref_frames >>= 1;
MBPairIsField = 0;
img->num_ref_idx_l0_active -= 1;
img->num_ref_idx_l0_active >>= 1;
//Rate control
img->write_macroblock_frame = 1; //for Rate control
}
else
{
img->field_mode = 1;
MBPairIsField = 1;
}
//Rate control
img->write_macroblock = 1;//Rate control
if (MBPairIsField)
img->top_field = 1;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -