📄 umc_h264_gen_enc.cpp
字号:
m_SliceHeader.MbaffFrameFlag = 0;
m_SliceHeader.bottom_field_flag = 0;
m_SliceHeader.direct_spatial_mv_pred_flag = 1;
m_SliceHeader.long_term_reference_flag = 0;
m_SliceHeader.sp_for_switch_flag = 0;
m_SliceHeader.slice_qs_delta = 0;
m_SliceHeader.frame_num = 0;
m_SliceHeader.idr_pic_id = 0;
m_SliceHeader.pic_order_cnt_lsb = 0;
m_SliceHeader.delta_pic_order_cnt[0] = 0;
m_SliceHeader.delta_pic_order_cnt[1] = 0;
m_SliceHeader.redundant_pic_cnt = 0;
m_SliceHeader.slice_group_change_cycle = 0;
m_SliceHeader.delta_pic_order_cnt_bottom = 0;
eFrameType[0] = PREDPIC;
m_DirectTypeStat[0]=m_DirectTypeStat[1]=0;
if (UMC_OK == status){ // Create noise reduction filter object
m_noisepf = new CNoiseReductionFilter<PixType>(true,true,false);
if (NULL == m_noisepf) status = UMC::UMC_ERR_ALLOC;
}
return;
}
//========================================================================
//========================================================================
template <class PixType, class CoeffsType>
Status H264CoreEncoder<PixType,CoeffsType>::Start_Sequence()
{
Status Status = UMC_OK;
// Set up for the 8 bit/default frame rate
m_uTRWrapAround = TR_WRAP;
m_uFrames_Num = 0;
m_uFrameCounter = 0;
SetSequenceParameters();
if((m_EmptyThreshold = ippsMalloc_32u(52)) == NULL) {
return(UMC::UMC_ERR_ALLOC);
}
if((m_DirectBSkipMEThres = ippsMalloc_32u(52)) == NULL) {
return(UMC::UMC_ERR_ALLOC);
}
if((m_PSkipMEThres = ippsMalloc_32u(52)) == NULL) {
return(UMC::UMC_ERR_ALLOC);
}
if((m_BestOf5EarlyExitThres = ippsMalloc_32s(52)) == NULL) {
return(UMC::UMC_ERR_ALLOC);
}
ippsCopy_32s((const Ipp32s*)UMC_H264_ENCODER::EmptyThreshold, (Ipp32s*)m_EmptyThreshold, 52);
ippsCopy_32s((const Ipp32s*)UMC_H264_ENCODER::DirectBSkipMEThres, (Ipp32s*)m_DirectBSkipMEThres, 52);
ippsCopy_32s((const Ipp32s*)UMC_H264_ENCODER::PSkipMEThres, (Ipp32s*)m_PSkipMEThres, 52);
ippsCopy_32s(UMC_H264_ENCODER::BestOf5EarlyExitThres, m_BestOf5EarlyExitThres, 52);
//TODO Add QP check
if(m_SeqParamSet.qpprime_y_zero_transform_bypass_flag) {
// Lossless mode
m_EmptyThreshold[0] = 0;
m_DirectBSkipMEThres[0] = 0;
m_PSkipMEThres[0] = 0;
m_BestOf5EarlyExitThres[0] = 0;
}
m_PaddedSize.width = (m_info.info.clip_info.width + 15) & ~15;
m_PaddedSize.height = (m_info.info.clip_info.height + (16<<(1 - m_SeqParamSet.frame_mbs_only_flag)) - 1) & ~((16<<(1 - m_SeqParamSet.frame_mbs_only_flag)) - 1);
m_WidthInMBs = m_PaddedSize.width >> 4;
m_HeightInMBs = m_PaddedSize.height >> 4;
m_Pitch = CalcPitchFromWidth(m_PaddedSize.width, sizeof(PixType)) / sizeof(PixType);
// Make sure the input color conversion is supported before allocating
// buffers.
// Read the profile and build the input frame queue.
// Also allocate the Core_Encoder
if (!m_bBuffersAllocated)
{
Status = Allocate_Buffers();
if (Status != UMC_OK)
{
goto done;
}
m_bBuffersAllocated = true;
}
/*
* This flag is used by the encoder to signal that the
* next frame should be encoded as an INTRA regardless of what
* the client asks for. This may be either because an error was
* detected in compressing the current delta, or to ensure that
* the first frame is encoded INTRA.
*/
m_bMakeNextFrameKey = true; // Ensure that we always start with a key frame.
m_bMakeNextFrameIDR = false;
if (H264_KFCM_INTERVAL == m_info.key_frame_controls.method)
{
m_uIntraFrameInterval = m_info.key_frame_controls.interval + 1;
m_uIDRFrameInterval = m_info.key_frame_controls.idr_interval + 1;
}else{
m_uIDRFrameInterval = m_uIntraFrameInterval = 0;
}
if (!m_noisepf->Start_Sequence(m_info.info.clip_info.width,m_info.info.clip_info.height)){
Status = UMC_ERR_FAILED;
}
done:
memset(&m_AdaptiveMarkingInfo,0,sizeof(m_AdaptiveMarkingInfo));
memset(&m_ReorderInfoL0,0,sizeof(m_ReorderInfoL0));
memset(&m_ReorderInfoL1,0,sizeof(m_ReorderInfoL1));
return Status;
} // Start_Sequence
//
// Encode - drives the compression of a "Temporal Reference"
//
template <class PixType, class CoeffsType> Status H264CoreEncoder<PixType,CoeffsType>::Encode(
VideoData* src,
MediaData* dst,
const H264_Encoder_Compression_Flags flags,
H264_Encoder_Compression_Notes ¬es)
{
Status ps = UMC_OK;
m_pCurrentFrame = 0;
m_field_index = 0;
Ipp32s isRef=0,frame_index;
if (!(flags & H264_ECF_LAST_FRAME)){
Ipp32u nShortTerm, nLongTerm;
EnumPicCodType ePictureType;
FrameType ft = src->GetFrameType();
switch(ft){
case I_PICTURE:
ePictureType = INTRAPIC;
break;
case P_PICTURE:
//Check for available frames in dpb
m_dpb.countActiveRefs( nShortTerm, nLongTerm );
if( (nShortTerm + nLongTerm) == 0 ) return UMC_ERR_NOT_ENOUGH_DATA; //May be it should be UMC_ERR_INVALID_PARAMS
ePictureType = PREDPIC;
break;
case B_PICTURE:
//Check for available frames in dpb
m_dpb.countActiveRefs( nShortTerm, nLongTerm );
if( (nShortTerm + nLongTerm) == 0 ) return UMC_ERR_NOT_ENOUGH_DATA; //May be it should be UMC_ERR_INVALID_PARAMS
ePictureType = BPREDPIC;
break;
case NONE_PICTURE:
default:
frame_index = m_iProfileIndex;
ePictureType = DetermineFrameType(m_iProfileIndex);
if( ePictureType == BPREDPIC ){
switch( m_info.treat_B_as_reference ){
case 0:
isRef=0; //No B references
break;
case 1:
if( m_iProfileIndex-1 == ((m_info.B_frame_rate+1)>>1) ) //Only middle B is reference, better to use round to low in case of even number of B frames
isRef = 1;
else isRef = 0;
break;
case 2: //All B frames are refereces
isRef = 1;
break;
}
}
break;
}
m_pLastFrame = m_pCurrentFrame = m_cpb.InsertFrame(src, ePictureType, isRef,
m_info.num_slices,
m_PaddedSize
#if defined ALPHA_BLENDING_H264
, m_SeqParamSet.aux_format_idc
#endif
);
if(m_pCurrentFrame){
m_pCurrentFrame->m_bIsIDRPic = false;
if (m_bMakeNextFrameIDR && ePictureType == INTRAPIC){
m_pCurrentFrame->m_bIsIDRPic = true;
m_PicOrderCnt_Accu += m_PicOrderCnt;
m_PicOrderCnt = 0;
m_bMakeNextFrameIDR = false;
}
switch(m_info.coding_type)
{
case 0:
m_pCurrentFrame->m_PictureStructureForDec = m_pCurrentFrame->m_PictureStructureForRef = FRM_STRUCTURE;
m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2, 0);
m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2 + 1, 1);
m_pCurrentFrame->m_PicOrderCounterAccumulated = 2*(m_PicOrderCnt + m_PicOrderCnt_Accu);
m_pCurrentFrame->m_bottom_field_flag[0] = 0;
m_pCurrentFrame->m_bottom_field_flag[1] = 0;
break;
case 1:
m_pCurrentFrame->m_PictureStructureForDec = m_pCurrentFrame->m_PictureStructureForRef = FLD_STRUCTURE;
m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2, 0);
m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2 + 1, 1);
m_pCurrentFrame->m_PicOrderCounterAccumulated = 2*(m_PicOrderCnt + m_PicOrderCnt_Accu);
m_pCurrentFrame->m_bottom_field_flag[0] = 0;
m_pCurrentFrame->m_bottom_field_flag[1] = 1;
break;
case 2:
m_pCurrentFrame->m_PictureStructureForDec = m_pCurrentFrame->m_PictureStructureForRef = AFRM_STRUCTURE;
m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2, 0);
m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2 + 1, 1);
m_pCurrentFrame->m_PicOrderCounterAccumulated = 2*(m_PicOrderCnt + m_PicOrderCnt_Accu);
m_pCurrentFrame->m_bottom_field_flag[0] = 0;
m_pCurrentFrame->m_bottom_field_flag[1] = 0;
break;
default:return UMC_ERR_UNSUPPORTED;
}
m_pCurrentFrame->InitRefPicListResetCount(0);
m_pCurrentFrame->InitRefPicListResetCount(1);
m_PicOrderCnt++;
if (m_pCurrentFrame->m_bIsIDRPic)
m_cpb.IncreaseRefPicListResetCount(m_pCurrentFrame);
// fprintf(stderr, "idx=%d frnm=%d POC=%d type=%d\n", frame_index, m_uFrames_Num, m_pCurrentFrame->PicOrderCnt(0,3), m_pCurrentFrame->m_PicCodType);
if( m_Analyse & ANALYSE_ME_ADAPTIVE_B ){
/* fprintf(stderr, "POCs*** %d ****: ", m_pCurrentFrame->PicOrderCnt(0,3));
for( Ipp32s i = 0; i<=profile_frequency; i++ )
if( eFrameSeq[i] )
fprintf(stderr," %d", eFrameSeq[i]->PicOrderCnt(0,3));
else
fprintf(stderr," %s", "NULL");
fprintf(stderr,"\n");
if( frame_index == 0 && (eFrameSeq[0] == NULL || eFrameSeq[1] == NULL || eFrameSeq[2] == NULL)){
fprintf(stderr,"ALERT3!!!");
}
*/
if( frame_index == 0 && eFrameSeq[0] != NULL ){
Ipp32s i, lref=0;
eFrameSeq[profile_frequency]=m_pCurrentFrame;
//Check consistency
/* Ipp32s cnull = 0;
if( eFrameSeq[0] == NULL ){
cnull = 1;
}
for(Ipp32s i = 1; i<=profile_frequency; i++ ){
if( eFrameSeq[i] == NULL ) cnull=1;
if( cnull && eFrameSeq[i] != NULL ) fprintf(stderr, "ALERT1!!!\n");
if( eFrameSeq[i] != NULL && eFrameSeq[i-1] != NULL){
if( eFrameSeq[i]->PicOrderCnt(0,3) - eFrameSeq[i-1]->PicOrderCnt(0,3) != 2 )
fprintf(stderr, "ALERT2!!!\n");
}
}
*/
//Try PP coding first
if( eFrameSeq[1] != NULL && eFrameSeq[2] != NULL ){
Ipp32s costPP1, costPP2, costBP1, costBP2, checkB=0;
EnumPicCodType pc = PREDPIC;
m_pCurrentFrame = eFrameSeq[1];
costPP1 = ME_EstimateFrame( pc, REFERENCE_PIC, eFrameSeq[0], NULL);
//If we have a lot of Intra, don't try B
// fprintf(stderr," Intra check: costPP1=%d intra %d all %d\n",costPP1, eFrameSeq[1]->numIntraMBs, eFrameSeq[1]->numMBs);
if( eFrameSeq[1]->numIntraMBs < ((eFrameSeq[1]->numMBs)>>1) ){
m_pCurrentFrame = eFrameSeq[2];
costPP2 = ME_EstimateFrame( pc, REFERENCE_PIC, eFrameSeq[1], NULL);
m_pCurrentFrame = eFrameSeq[2];
costBP1 = ME_EstimateFrame( pc, REFERENCE_PIC, eFrameSeq[0], NULL);
pc = BPREDPIC;
m_pCurrentFrame = eFrameSeq[1];
costBP2 = ME_EstimateFrame( pc, DISPOSABLE_PIC, eFrameSeq[0], eFrameSeq[2]);
if( costPP1+costPP2 >= costBP1+costBP2 ) checkB = 1;
// fprintf(stderr," CostCheck: PP1=%d PP2=%d BP1=%d BP2=%d ALL: PP=%d BP=%d\n", costPP1, costPP2, costBP1, costBP2, costPP1+costPP2, costBP1+costBP2 );
}
if( checkB ){
EnumPicCodType pc = PREDPIC;
Ipp32s prevCostPP = costBP1;
Ipp32s i,m,k;
for( i=3; i<=profile_frequency && eFrameSeq[i];i++){
Ipp32s costP1, costP2;
m_pCurrentFrame = eFrameSeq[i];
costP1 = ME_EstimateFrame( pc, REFERENCE_PIC, eFrameSeq[i-1], NULL);
//m_pCurrentFrame = eFrameSeq[i];
costP2 = ME_EstimateFrame( pc, REFERENCE_PIC, eFrameSeq[0], NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -