📄 umc_h264_gen_enc.cpp
字号:
#ifdef CALC_PSNR { pYDst = m_pReconstructFrame->m_pYPlane; pUDst = m_pReconstructFrame->m_pUPlane; pVDst = m_pReconstructFrame->m_pVPlane; #define LOG10(a) ( log(a)/log(double(10)) ) double PSNR; double MSE = 0.0; Ipp32u i, j, tmp, uMSE; Ipp8u *p1,*p2; p1 = m_pCurrentFrame->m_pYPlane;#ifdef USE_SMOOTHED_IMAGE_FOR_PSNR p2 = pY;#else p2 = pYDst;#endif uMSE = 0; for (i = 0; i < m_info.dimensions.height; i++) { for (j = 0; j < m_info.dimensions.width; j++) { tmp = (p1[j] - p2[j]); uMSE += (tmp*tmp); } p1 += m_pCurrentFrame->m_pitch;#ifdef USE_SMOOTHED_IMAGE_FOR_PSNR p2 += pitch;#else p2 += m_pReconstructFrame->m_pitch;#endif } if (uMSE) { MSE = double(uMSE); MSE /= m_info.dimensions.Area(); PSNR = 10*LOG10((255.0*255.0)/(MSE)); } else { PSNR = 50.00; // just need some number for the average } total_psnr += PSNR; total_bits += dst.size; num_calc_psnr++; FILE *fp = fopen(PSNR_OUTPUT_FILE_NAME, "a+"); if (fp) { if (g_first) { fprintf(fp, "=======================================================\n"); fprintf(fp, "Defines: "); fprintf(fp, "\n"); fprintf(fp, "TR\tQP\tPSNR\tBits\tAvPSNR\tAvBits\tFr.type\n"); fprintf(fp, "=======================================================\n"); g_first = false; } fprintf(fp,"%d\t%d\t%.2f\t%d\t%.2f\t%d\t%s\n", m_pCurrentFrame->m_FrameNum, m_PicParamSet.pic_init_qp, PSNR,8*dst.size, total_psnr/(double)num_calc_psnr, 8*total_bits/num_calc_psnr, ePictureType == INTRAPIC?"Key": (BPREDPIC == ePictureType)?"B":""); fclose(fp); } }#endif // CALC_PSNR // ------------------------------------------------------------------------ // update states for next frame, etc. // ------------------------------------------------------------------------ // Increment the Frame Number (decode order), not incremented for any frame // directly preceded (in decode order) by a disposable frame. m_uFrames_Num++;done: return status;}//// move all frames in WaitingForRef to ReadyToEncode//StatusH264VideoEncoder::MoveFromCPBToDPB(){ // EnumPicCodType ePictureType; m_cpb.RemoveFrame(m_pCurrentFrame); m_dpb.insertAtCurrent(m_pCurrentFrame); return UMC_OK;}StatusH264VideoEncoder::CleanDPB(){ H264EncoderFrame *pFrm=m_dpb.findNextDisposable(); // EnumPicCodType ePictureType; Status ps = UMC_OK; while(pFrm!=NULL) { m_dpb.RemoveFrame(pFrm); m_cpb.insertAtCurrent(pFrm); pFrm=m_dpb.findNextDisposable(); } while(pFrm!=NULL); return ps;}/************************************************************* * Name: SetSequenceParameters * Description: Fill in the Sequence Parameter Set for this * sequence. Can only change at an IDR picture. *************************************************************/voidH264VideoEncoder::SetSequenceParameters(){ Ipp32u MB_per_frame = 0; Ipp32u MB_per_sec = 0; m_SeqParamSet.profile_idc = 77; // We don't meet any of these contraints yet m_SeqParamSet.constraint_set0_flag = 0; m_SeqParamSet.constraint_set1_flag = 1; m_SeqParamSet.constraint_set2_flag = 0; m_SeqParamSet.constraint_set3_flag = 0; m_SeqParamSet.seq_parameter_set_id = 0; // Frame numbers are mod 256. m_SeqParamSet.log2_max_frame_num = 8; // Setup pic_order_cnt_type based on use of B frames. // Note! pic_order_cnt_type == 1 is not implemented // The following are not transmitted in either case below, and are // just initialized here to be nice. m_SeqParamSet.delta_pic_order_always_zero_flag = 0; m_SeqParamSet.offset_for_non_ref_pic = 0; m_SeqParamSet.poffset_for_ref_frame = NULL; m_SeqParamSet.num_ref_frames_in_pic_order_cnt_cycle = 0; if (m_info.B_Frame_Rate == 0) { m_SeqParamSet.pic_order_cnt_type = 2; m_SeqParamSet.log2_max_pic_order_cnt_lsb = 0; // Right now this only supports simple P frame patterns (e.g. H264PPPP...) } else { m_SeqParamSet.log2_max_pic_order_cnt_lsb = 4; m_SeqParamSet.pic_order_cnt_type = 0; // Right now this only supports simple B frame patterns (e.g. IBBPBBP...) } m_SeqParamSet.num_ref_frames = m_info.num_ref_frames; // Note! NO code after this point supports pic_order_cnt_type == 1 // Always zero because we don't support field encoding m_SeqParamSet.offset_for_top_to_bottom_field = 0; m_SeqParamSet.frame_mbs_only_flag = (m_info.coding_type)? 0: 1; m_SeqParamSet.gaps_in_frame_num_value_allowed_flag = 0; m_SeqParamSet.mb_adaptive_frame_field_flag = 0; // If set to 1, 8x8 blocks in Direct Mode always use 1 MV, // obtained from the "outer corner" 4x4 block, regardless // of how the CoLocated 8x8 is split into subblocks. If this // is 0, then the 8x8 in Direct Mode is subdivided exactly as // the Colocated 8x8, with the appropriate number of derived MVs. m_SeqParamSet.direct_8x8_inference_flag = m_info.use_direct_inference || !m_SeqParamSet.frame_mbs_only_flag ? 1 : 0; // Picture Dimensions in MBs m_SeqParamSet.frame_width_in_mbs = ((m_info.dimensions.width+15)>>4); m_SeqParamSet.frame_height_in_mbs = ((m_info.dimensions.height+15)>>4); // If the width & height in MBs doesn't match the image dimensions then do // some cropping in the decoder if (((m_SeqParamSet.frame_width_in_mbs<<4) != m_info.dimensions.width) || ((m_SeqParamSet.frame_height_in_mbs<<4) != m_info.dimensions.height)) { m_SeqParamSet.frame_cropping_flag = 1; m_SeqParamSet.frame_crop_left_offset = 0; m_SeqParamSet.frame_crop_right_offset = ((m_SeqParamSet.frame_width_in_mbs<<4) - m_info.dimensions.width)>>1; m_SeqParamSet.frame_crop_top_offset = 0; m_SeqParamSet.frame_crop_bottom_offset = ((m_SeqParamSet.frame_height_in_mbs<<4) - m_info.dimensions.height)>>1; } else { m_SeqParamSet.frame_cropping_flag = 0; m_SeqParamSet.frame_crop_left_offset = 0; m_SeqParamSet.frame_crop_right_offset = 0; m_SeqParamSet.frame_crop_top_offset = 0; m_SeqParamSet.frame_crop_bottom_offset = 0; } m_SeqParamSet.vui_parameters_present_flag = 0; // Calculate the Level Based on encoding parameters (assume 30 fps). MB_per_frame = m_SeqParamSet.frame_width_in_mbs * m_SeqParamSet.frame_height_in_mbs; MB_per_sec = (Ipp32u)(MB_per_frame * m_info.FrameRate); if (m_info.level_idc==0) { if ((MB_per_frame <= 99) && (MB_per_sec <= 1485)) { m_SeqParamSet.level_idc = 10; // Level 1 } else if ((MB_per_frame <= 396) && (MB_per_sec <= 2970)) { m_SeqParamSet.level_idc = 11; // Level 1.1 } else if ((MB_per_frame <= 396) && (MB_per_sec <= 5940)) { m_SeqParamSet.level_idc = 12; // Level 1.2 } else if ((MB_per_frame <= 396) && (MB_per_sec <= 11880)) { m_SeqParamSet.level_idc = 20; // Level 2 } else if ((MB_per_frame <= 792) && (MB_per_sec <= 19800)) { m_SeqParamSet.level_idc = 21; // Level 2.1 } else if ((MB_per_frame <= 1620) && (MB_per_sec <= 20250)) { m_SeqParamSet.level_idc = 22; // Level 2.2 } else if ((MB_per_frame <= 1620) && (MB_per_sec <= 40500)) { m_SeqParamSet.level_idc = 30; // Level 3 } else if ((MB_per_frame <= 3600) && (MB_per_sec <= 108000)) { m_SeqParamSet.level_idc = 31; // Level 3.1 } else if ((MB_per_frame <= 5120) && (MB_per_sec <= 216000)) { m_SeqParamSet.level_idc = 32; // Level 3.2 } else if ((MB_per_frame <= 8192) && (MB_per_sec <= 245760)) { m_SeqParamSet.level_idc = 40; // Level 4 } else if ((MB_per_frame <= 19200) && (MB_per_sec <= 491520)) { m_SeqParamSet.level_idc= 50; // Level 5 } else { m_SeqParamSet.level_idc= 51; // Level 5.1 } } else { m_SeqParamSet.level_idc = m_info.level_idc; } // Precalculate these values so we have them for later (repeated) use. m_SeqParamSet.MaxMbAddress = (m_SeqParamSet.frame_width_in_mbs * m_SeqParamSet.frame_height_in_mbs) - 1; SetDPBSize();} // SetSequenceParameters/************************************************************* * Name: SetPictureParameters * Description: Fill in the Picture Parameter Set for this * sequence. Can only change at an IDR picture. *************************************************************/voidH264VideoEncoder::SetPictureParameters(PictureStructure picture_structure){ m_PicParamSet.pic_parameter_set_id = 0; // Assumes that there is only one sequence param set to choose from m_PicParamSet.seq_parameter_set_id = m_SeqParamSet.seq_parameter_set_id; m_PicParamSet.entropy_coding_mode = m_info.entropy_coding_mode; m_PicParamSet.pic_order_present_flag = 0; m_PicParamSet.weighted_pred_flag = 0; // We use implicit weighted prediction (2) when B frame rate can // benefit from it. When B_Frame_rate == 0 or 1, it doesn't matter, // so we do what is faster (0). m_PicParamSet.weighted_bipred_idc = m_info.use_implicit_weighted_bipred ? 2 : 0; // Default to P frame constant quality at time of an IDR m_PicParamSet.pic_init_qp = m_info.rate_controls.quant; m_PicParamSet.pic_init_qs = 26; // Not used m_PicParamSet.chroma_qp_index_offset = 0; m_PicParamSet.deblocking_filter_variables_present_flag = 1; m_PicParamSet.constrained_intra_pred_flag = 0; // We don't do redundant slices... m_PicParamSet.redundant_pic_cnt_present_flag = 0; // In the future, if flexible macroblock ordering is // desired, then a macroblock allocation map will need // to be coded and the value below updated accordingly. m_PicParamSet.num_slice_groups = 1; // Hard coded for now m_PicParamSet.SliceGroupInfo.slice_group_map_type = 0; m_PicParamSet.SliceGroupInfo.t3.pic_size_in_map_units = 0; m_PicParamSet.SliceGroupInfo.t3.pSliceGroupIDMap = NULL; // I guess these ned to be 1 or greater since they are written as "minus1". // TODO VSI, what actually goes here??? m_PicParamSet.num_ref_idx_l0_active = (picture_structure != FRAME_PICTURE)? 2 : 1; m_PicParamSet.num_ref_idx_l1_active = 1; m_PicParamSet.mb_width = m_SeqParamSet.frame_width_in_mbs; m_PicParamSet.mb_height = (picture_structure != FRAME_PICTURE)? m_SeqParamSet.frame_height_in_mbs/2 : m_SeqParamSet.frame_height_in_mbs; m_PicParamSet.picture_structure = picture_structure;} // SetPictureParameters/************************************************************* * Name: SetSliceHeader * Description: Given the ePictureType and m_info * fill in the slice header for this slice ************************************************************/voidH264VideoEncoder::SetSliceHeader( H264EncoderFrame * m_pCurrentFrame, EnumPicClass // ePictureClass){ int frame_num = m_pCurrentFrame->m_FrameNum; // Right now, we always work with frame nums modulo 256 m_SliceHeader.frame_num = frame_num % m_uTRWrapAround; // Assumes there is only one picture parameter set to choose from m_SliceHeader.pic_parameter_set_id = m_PicParamSet.pic_parameter_set_id; m_SliceHeader.field_pic_flag = (Ipp8u)(m_PicParamSet.picture_structure != 0); m_SliceHeader.bottom_field_flag = (Ipp8u)(m_PicParamSet.picture_structure == BOTTOM_FIELD); m_SliceHeader.direct_spatial_mv_pred_flag = m_info.use_spatial_direct_pred; m_SliceHeader.num_ref_idx_l0_active = m_PicParamSet.num_ref_idx_l0_active; m_SliceHeader.num_ref_idx_l1_active = m_PicParamSet.num_ref_idx_l1_active; m_SliceHeader.num_ref_idx_active_override_flag = ( (m_SliceHeader.num_ref_idx_l0_active != m_PicParamSet.num_ref_idx_l0_active) || (m_SliceHeader.num_ref_idx_l1_active != m_PicParamSet.num_ref_idx_l1_active) ); //m_TopPicOrderCnt = m_PicOrderCnt; //m_BottomPicOrderCnt = m_TopPicOrderCnt + 1; // ???? if (m_SeqParamSet.pic_order_cnt_type == 0) { m_SliceHeader.pic_order_cnt_lsb = m_pCurrentFrame->PicOrderCnt(m_field_index) & ~(1 << m_SeqParamSet.log2_max_pic_order_cnt_lsb); } m_SliceHeader.adaptive_ref_pic_marking_mode_flag=0; // We don't do redundant slices... // Right now we disable the block edge filter only if the global encoder option // says so. m_info.slice_parms.disable_deblocking_filter_idc = m_info.Deblocking_Filter_Mode; if (m_info.Deblocking_Filter_Mode == 1) { m_info.slice_parms.slice_alpha_c0_offset = -51; m_info.slice_parms.slice_beta_offset = -51; } else { m_info.slice_parms.slice_alpha_c0_offset = (Ipp8s)(m_info.Deblocking_Filter_Alpha)<<1; m_info.slice_parms.slice_beta_offset = (Ipp8s)(m_info.Deblocking_Filter_Beta)<<1; } m_SliceHeader.disable_deblocking_filter_idc = m_info.slice_parms.disable_deblocking_filter_idc;} // SetSliceHeader/************************************************************* * Name: encodeFrameHeader * Description: Write out the frame header to the bit stream. ************************************************************/StatusH264VideoEncoder::encodeFrameHeader(CH264pBs *bs, H264_Image &dst, bool bIDR_Pic){ Status ps = UMC_OK; // First, write a picture delimiter for the frame. ps = bs->PutPicDelimiter(m_PicType); bs->WriteTrailingBits(); // Write RBSP Trailing Bits // Copy PicDelimiter RBSP to the end of the output buffer after // Adding start codes and SC emulation prevention. dst.size += bs->EndOfNAL((dst.data + dst.size), 0, NAL_UT_PD); // If this is an IDR picture, write the seq and pic parameter sets if (bIDR_Pic) { // Write the seq_parameter_set_rbsp ps = bs->PutSeqParms(m_SeqParamSet); bs->WriteTrailingBits(); // Write RBSP Trailing Bits // Copy Sequence Parms RBSP to the end of the output buffer after // Adding start codes and SC emulation prevention. dst.size += bs->EndOfNAL((dst.data + dst.size), 1, NAL_UT_SPS); ps = bs->PutPicParms(m_PicParamSet, m_SeqParamSet); bs->WriteTrailingBits(); // Write RBSP Trailing Bits // Copy Picture Parms RBSP to the end of the output buffer after // Adding start codes and SC emulation prevention. dst.size += bs->EndOfNAL((dst.data + dst.size), 1, NAL_UT_PPS); } return ps;}// ===========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -