📄 umc_h264_gen_enc.cpp
字号:
//// INTEL CORPORATION PROPRIETARY INFORMATION// This software is supplied under the terms of a license agreement or// nondisclosure agreement with Intel Corporation and may not be copied// or disclosed except in accordance with the terms of that agreement.// Copyright (c) 2004 - 2005 Intel Corporation. All Rights Reserved.//#if defined _WIN32#include <windows.h>#undef true#undef false#endif#include <string.h>#include "umc_h264_video_encoder.h"#include "umc_h264_gen_enc.h"#include "umc_h264_crc.h"#include "umc_video_data.h"#ifdef SAVE_RECON#define RAW_RECON_FILE "im.raw"#endif // SAVE_RECON#if defined(CALC_PSNR) || defined(SAVE_RECON)#include <stdio.h>#include <math.h>#endif#ifdef CALC_PSNRstatic unsigned int num_calc_psnr = 0;static double total_psnr = 0.0;static unsigned int total_bits = 0;bool g_first;#if defined(_WIN32)#define PSNR_OUTPUT_FILE_NAME "h264psnr.txt"#else#define PSNR_OUTPUT_FILE_NAME "h264psnr.txt"#endif#endif // CALC_PSNRnamespace UMC{//// Constructor for the EncoderH264 class.//H264VideoEncoder::H264VideoEncoder(Status &status) : // m_implementation_id gets refined in GetBackdoorEncoderOptions m_input_format(), m_output_format(), m_pBitStream(NULL), m_bBuffersAllocated(false), profile_frequency(1), m_iProfileIndex(0), m_bScratchBufferAllocated(false), m_noisepf(NULL), m_pAllocEncoderInst(NULL), m_bs1(NULL), m_uIntraFrameInterval(0), m_bKeyFrameIntervalPending(false), m_deblockingFilter(), m_uLastXmittedQP(0), m_Intra_MB_Counter(0), m_MB_Counter(0), m_trd(0), m_trb(0), m_previous_tr(0), m_current_tr(0), m_PicOrderCnt(0), m_pReconstructDisp(NULL), m_rate_control(NULL){ status = UMC_OK;#ifdef CALC_PSNR g_first = true;#endif#ifdef SAVE_RECON // clear outfile FILE *f; f = fopen(RAW_RECON_FILE, "wb"); fclose(f);#endif m_bQPMapIsReady = false; // Initialize the BRCState local variables based on the default // settings in m_info. // If these assertions fail, then uTargetFrmSize needs to be set to // something other than 0. // Initialize the sequence parameter set structure. m_SeqParamSet.profile_idc = 0; m_SeqParamSet.level_idc = 0; m_SeqParamSet.constraint_set0_flag = 0; m_SeqParamSet.constraint_set1_flag = 0; m_SeqParamSet.constraint_set2_flag = 0; m_SeqParamSet.seq_parameter_set_id = 0; m_SeqParamSet.log2_max_frame_num = 0; m_SeqParamSet.pic_order_cnt_type = 0; m_SeqParamSet.delta_pic_order_always_zero_flag = 0; m_SeqParamSet.frame_mbs_only_flag = 0; m_SeqParamSet.gaps_in_frame_num_value_allowed_flag = 0; m_SeqParamSet.mb_adaptive_frame_field_flag = 0; m_SeqParamSet.direct_8x8_inference_flag = 0; m_SeqParamSet.vui_parameters_present_flag = 0; m_SeqParamSet.log2_max_pic_order_cnt_lsb = 0; m_SeqParamSet.offset_for_non_ref_pic = 0; m_SeqParamSet.offset_for_top_to_bottom_field = 0; m_SeqParamSet.num_ref_frames_in_pic_order_cnt_cycle = 0; m_SeqParamSet.poffset_for_ref_frame = NULL; m_SeqParamSet.num_ref_frames = 0; m_SeqParamSet.frame_width_in_mbs = 0; m_SeqParamSet.frame_height_in_mbs = 0; 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; // Initialize the picture parameter set structure. m_PicParamSet.pic_parameter_set_id = 0; m_PicParamSet.seq_parameter_set_id = 0; m_PicParamSet.entropy_coding_mode = 0; m_PicParamSet.pic_order_present_flag = 0; m_PicParamSet.weighted_pred_flag = 0; m_PicParamSet.weighted_bipred_idc = 0; m_PicParamSet.pic_init_qp = 0; m_PicParamSet.pic_init_qs = 0; m_PicParamSet.chroma_qp_index_offset = 0; m_PicParamSet.deblocking_filter_variables_present_flag = 0; m_PicParamSet.constrained_intra_pred_flag = 0; m_PicParamSet.redundant_pic_cnt_present_flag = 0; m_PicParamSet.num_slice_groups = 0; m_PicParamSet.SliceGroupInfo.slice_group_map_type = 0; m_PicParamSet.SliceGroupInfo.t3.pic_size_in_map_units = 0; m_PicParamSet.SliceGroupInfo.t3.pSliceGroupIDMap = NULL; m_PicParamSet.num_ref_idx_l0_active = 0; m_PicParamSet.num_ref_idx_l1_active = 0; // Initialize the slice header structure. m_SliceHeader.pic_parameter_set_id = 0; m_SliceHeader.field_pic_flag = 0; m_SliceHeader.bottom_field_flag = 0; m_SliceHeader.direct_spatial_mv_pred_flag = 1; m_SliceHeader.num_ref_idx_active_override_flag = 0; m_SliceHeader.cabac_init_idc = 0; m_SliceHeader.slice_qp_delta = 0; m_SliceHeader.sp_for_switch_flag = 0; m_SliceHeader.slice_qs_delta = 0; m_SliceHeader.disable_deblocking_filter_idc = 0; m_SliceHeader.slice_alpha_c0_offset = 0; m_SliceHeader.slice_beta_offset = 0; m_SliceHeader.first_mb_in_slice = 0; m_SliceHeader.frame_num = 0; m_SliceHeader.slice_type = INTRASLICE; m_SliceHeader.idr_pic_id = 0; m_SliceHeader.pic_order_cnt_lsb = 0; m_SliceHeader.delta_pic_order_cnt_bottom = 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.num_ref_idx_l0_active = 0; m_SliceHeader.num_ref_idx_l1_active = 0; m_SliceHeader.slice_group_change_cycle = 0; eFrameType[0] = PREDPIC;#ifdef _DEBUG ZeroTotalBits();#endif if (UMC_OK == status) { // Create noise reduction filter object m_noisepf = new CNoiseReductionFilter( true,true,false); if (NULL == m_noisepf) { status = UMC_FAILED_TO_ALLOCATE_BUFFER; } } return;}//========================================================================//========================================================================StatusH264VideoEncoder::Start_Sequence ( const H264_Image_Format &src_fmt, const H264_Image_Format &dst_fmt ){ Status Status = UMC_OK; // Save our transformation formats in the base H264_Encoder class m_input_format = src_fmt; m_output_format = dst_fmt; // Set up for the 8 bit/default frame rate m_uTRWrapAround = TR_WRAP; m_uFrames_Num = 0; m_uPic_Count_Base = 0; m_uFrameCounter = 0; m_info.dimensions = m_input_format.dimensions; sDimensions desiredPaddedSize; desiredPaddedSize.width = (m_info.dimensions.width + 15) & ~15; desiredPaddedSize.height = (m_info.dimensions.height + 15) & ~15; uWidthInMBs= desiredPaddedSize.width >> 4; uHeightInMBs = desiredPaddedSize.height >> 4; uWidthIn4x4Blocks = uWidthInMBs<<2; uHeightIn4x4Blocks = uHeightInMBs<<2; uPitch = CalcPitchFromWidth(desiredPaddedSize.width); // 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_bKeyFrameIntervalPending = false; if ( H264_KFCM_INTERVAL == m_info.key_frame_controls.method ) m_uIntraFrameInterval = m_info.key_frame_controls.interval; else m_uIntraFrameInterval = 0; if (!m_noisepf->Start_Sequence( m_input_format.dimensions.width, m_input_format.dimensions.height)) { Status = UMC_OPERATION_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"//StatusH264VideoEncoder::Encode ( const H264_Image &src, H264_Image &dst, const H264_Encoder_Compression_Flags flags, H264_Encoder_Compression_Notes ¬es){ Status ps = UMC_OK ; EnumPicCodType ePictureType = DetermineFrameType( m_iProfileIndex ); m_pCurrentFrame = 0; m_iProfileIndex++; m_field_index = 0; if (m_iProfileIndex == profile_frequency) m_iProfileIndex = 0; // last frame should be P or I, but not B frame. if ((m_info.numFramesToEncode == m_PicOrderCnt + 1) && (ePictureType == BPREDPIC)) { ePictureType = PREDPIC; } dst.size = 0; if (!(flags & H264_ECF_LAST_FRAME)) { m_pCurrentFrame = m_cpb.InsertFrame(src, ePictureType, m_info.Num_Slices); if(m_pCurrentFrame) { m_pCurrentFrame->m_PictureStructureForDec = m_pCurrentFrame->m_PictureStructureForRef = FRM_STRUCTURE; m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2, 0); m_pCurrentFrame->setPicOrderCnt(m_PicOrderCnt*2, 1); m_PicOrderCnt++; m_pCurrentFrame->m_bottom_field_flag[0] = 0; m_pCurrentFrame->m_bottom_field_flag[1] = 0; } else { return UMC_BAD_FORMAT; } } if (UMC_OK != ps) goto done; m_pCurrentFrame = m_cpb.findOldestToEncode(&m_dpb, m_info.num_ref_to_start_code_B_slice); if (m_pCurrentFrame) { m_pCurrentFrame->setFrameNum(m_uFrameCounter); m_uFrameCounter++; // Increment for next time through // perform noise reduction on the YUV12 video buffer m_noisepf->DoFiltering( m_pCurrentFrame->m_pYPlane, m_pCurrentFrame->m_pUPlane, m_pCurrentFrame->m_pVPlane, m_pCurrentFrame->m_pitch, m_pCurrentFrame->m_pitch, src.format.dimensions.width, src.format.dimensions.height); MoveFromCPBToDPB(); notes &= ~H264_ECN_NO_FRAME; } else { dst.size=0; cnotes |= H264_ECN_NO_FRAME; return UMC_NOT_ENOUGH_DATA; } ePictureType = m_pCurrentFrame->m_PicCodType; // ePictureType is a reference variable. It is updated by // CompressFrame if the frame is internally forced to a key frame. ps = CompressFrame(ePictureType, dst); if (dst.size > 0) { dst.sequence_number = m_pCurrentFrame->GetSequenceNumber(); if (ePictureType == INTRAPIC) { // Tell the environment we just generated a key frame notes |= H264_ECN_KEY_FRAME; } else if (ePictureType == BPREDPIC) { // Tell the environment we just generated a B frame notes |= H264_ECN_B_FRAME; } } // this is "sticky" for the duration of the TR for all layers m_info.m_do_suppress_B_for_this_TR = false; if (ps == UMC_OK && dst.size == 0 && (flags & H264_ECF_LAST_FRAME)) { notes |= H264_ECN_NO_FRAME; }done: m_pCurrentFrame->setWasEncoded(); CleanDPB(); if(ps==UMC_OK) m_info.numEncodedFrames++; return ps;}//// This function frees the encoder's "dimension-dependent" allocations.//StatusH264VideoEncoder::End_Sequence(){#ifdef SAVE_RECON // This is only needed if the recon output is supposed to be used // for anything, for instance viewing or comparisons // This code writes a reconstructed frame for the last frame (decode // order) in the sequence, when B frames are in use Write_Order_Frame(DISPOSABLE_PIC, 0); // save last frame#endif // SAVE_RECON Status ps = UMC_OK; if (m_bBuffersAllocated) { Deallocate_Buffers(); m_bBuffersAllocated = false; } return ps;}/********************************************************************** * EncoderH264 destructor. **********************************************************************/H264VideoEncoder::~H264VideoEncoder(){ Close(); Free_Core_Memory(); // release the noise reduction prefilter delete m_noisepf; m_noisepf = NULL; if (m_bBuffersAllocated) { Deallocate_Buffers(); m_bBuffersAllocated = false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -