📄 umc_h264_gen_enc.cpp
字号:
#ifdef _DEBUG PrintTotalBits();#endif}// ==================================================================================voidH264VideoEncoder::Deallocate_Buffers(){ if (m_pQPMap) { H264_Free(m_pQPMap); m_pQPMap = NULL; } m_bScratchBufferAllocated = false; if (m_pAllocEncoderInst) { H264_Free(m_pAllocEncoderInst); m_pAllocEncoderInst = NULL; } if (m_bs1) { delete m_bs1; m_bs1 = NULL; } m_cpb.destroy(); m_dpb.destroy(); Free_Core_Memory(); if (m_rate_control) { delete m_rate_control; m_rate_control = NULL; }}// This function is called when the encoder's Start_Sequence function is// called. This signals that dimension dependent variables such as frame// buffers should now be allocated.//StatusH264VideoEncoder::Allocate_Buffers(){ Ipp32s iFrame; Ipp32s iBFrmsShared; Ipp32u uPaddedHeight, uPaddedWidth; Ipp32u padded_width, padded_height; Status status = UMC_OK; uPaddedHeight = (m_info.dimensions.height + 0xf) & ~0xf; uPaddedWidth = (m_info.dimensions.width + 0xf) & ~0xf; m_HeightInMBs = (uPaddedHeight + 15) >> 4; m_WidthInMBs = (uPaddedWidth + 15) >> 4; m_pQPMap = (Ipp8u *)H264_Allocate(m_HeightInMBs * m_WidthInMBs, true ); if (!m_pQPMap) { status = UMC_FAILED_TO_ALLOCATE_BUFFER; goto done; } m_QPMapSize = m_HeightInMBs * m_WidthInMBs; // not sure if this is needed... but delete the FrameList if it exists // Allocate the Reference Frames and // call H264VideoEncoder::Allocate_Core_Memory // In H.263+, we encode and decode the padded frames (padded to the right // and bottom to multiples of 16). The Input frame dimensions are used // for display purposes only. padded_height = ( m_info.dimensions.height + 0xf) & ~0xf; padded_width = ( m_info.dimensions.width + 0xf) & ~0xf; m_HeightInMBs = padded_height >> 4; m_WidthInMBs = padded_width >> 4; m_NumMBs = m_HeightInMBs * m_WidthInMBs; // Allocate space for the bitstream and a bit stream copy (used for IPB) if (!m_bScratchBufferAllocated ) { // Notice the actual non-padded frame dimensions are used. We had this // clarified with the ITU. Ipp32u uSize = GetBsBufferMaxSize( m_info.dimensions.width, m_info.dimensions.height ); // Notice the encoder's internal bitstream buffer is 2x the standard size m_pAllocEncoderInst = (Ipp8u *)H264_Allocate( uSize * 2, true); if (NULL == m_pAllocEncoderInst) { status = UMC_FAILED_TO_ALLOCATE_BUFFER; goto done; } // the bit stream buffer is 32 byte aligned. m_pBitStream = H264_ALIGN(m_pAllocEncoderInst, 32); m_bScratchBufferAllocated = true; } m_pReconstructFrame = new H264EncoderFrame(0,m_info.dimensions.width,m_info.dimensions.height,1,1,status); if (!m_pReconstructFrame) { status = UMC_FAILED_TO_ALLOCATE_BUFFER; goto done; } else if (status != UMC_OK) { delete m_pReconstructFrame; m_pReconstructFrame = NULL; goto done; } // allocate bitstream objects m_bs1 = new CH264pBs( //m_fid, m_pBitStream, GetBsBufferMaxSize(m_info.dimensions.width, m_info.dimensions.height), status); if (!m_bs1) { status = UMC_FAILED_TO_ALLOCATE_BUFFER; goto done; } else if (status != UMC_OK) { delete m_bs1; m_bs1 = NULL; goto done; } Allocate_Core_Memory(m_info.Num_Slices, m_WidthInMBs, m_HeightInMBs, m_bs1);//CConstRateControl(Ipp32u c_width,Ipp32u c_height,Ipp32u c_pitch,Ipp32u target_bps,Ipp32u _qp_min,Ipp32u _qp_max); m_rate_control_method = m_info.rate_controls.method; switch(m_info.rate_controls.method) { case H264_RCM_BITRATE: { m_rate_control = new CH264ConstRateControl(m_info.dst_width,m_info.dst_height,CalcPitchFromWidth(m_info.dst_width), m_info.rate_controls.bitrate,QP_MIN,QP_MAX); if (m_rate_control) { ((CH264ConstRateControl *)m_rate_control)->SetRateControlOptions(&m_info.arco); } } break; case H264_RCM_MPEG2: { BitRate = m_info.rate_controls.bitrate; FrameRate = m_info.FrameRate; qscale[INTRASLICE] = m_info.key_frame_controls.rate_controls.quant; qscale[PREDSLICE] = m_info.rate_controls.quant; qscale[BPREDSLICE] = m_info.B_frame_rate_controls.quant; M = m_info.B_Frame_Rate+1; N = min(m_info.key_frame_controls.interval,m_info.numFramesToEncode); m_rate_control = NULL; InitRateControl((m_info.dimensions.width+15)>>4, (m_info.dimensions.height+15)>>4); } default: m_rate_control = NULL; } // Allocate the input color converted frame queue for the layer // # of frames needed by all layers using this InputFrmQ + 1 for P for ( iFrame = iBFrmsShared = 0; iFrame < profile_frequency; iFrame++ ) { if ( eFrameType[ iFrame ] == BPREDPIC ) { iBFrmsShared++; } } // reset the index into the Profile m_iProfileIndex = 0;done: // if we have an error creating or allocating above then // cleanup any objects that were successfully created. if ( status != UMC_OK ) { Deallocate_Buffers(); } return status;}// Note that if B frames are used they will be written in encode order,// not display (or original source) order.Status H264VideoEncoder::EncodePicture(H264_Image &dst){ Status status = UMC_OK; Ipp16u slice; EnumPicClass ePic_Class; // Determine the Pic_Class. Right now this depends on ePictureType, but that could change // to permit disposable P frames, for example. switch (m_PicType) { case INTRAPIC: if (m_uFrames_Num == 0 && m_PicParamSet.picture_structure != BOTTOM_FIELD) { // Right now, only the first INTRAPIC in a sequence is an IDR Frame ePic_Class = IDR_PIC; } else { ePic_Class = REFERENCE_PIC; } break; case PREDPIC: ePic_Class = REFERENCE_PIC; break; case BPREDPIC: ePic_Class = DISPOSABLE_PIC; break; default: // Unsupport Picture Type VM_ASSERT(false); ePic_Class = IDR_PIC; break; } // Now set-up some things depending on Picture Class switch (ePic_Class) { case IDR_PIC: m_uPic_Count_Base = m_pCurrentFrame->GetSequenceNumber(); // Set the pic cnt base SetSequenceParameters(); // These only get (re)set on IDR pictures. SetPictureParameters(); // Toggle the idr_pic_id on and off so that adjacent IDRs will have different values // This is done here because it is done per frame and not per slice. m_SliceHeader.idr_pic_id ^= 0x1; break; case REFERENCE_PIC: // swap reference frames before encoding the new reference frame. if(m_PicParamSet.picture_structure != BOTTOM_FIELD) { //SwapReferencePtrs(); } break; case DISPOSABLE_PIC: // Do Nothing right now? break; default: // Unsupported Picture Class break; } // reset bitstream object before begin compression m_bs1->Reset(); // Initialization before encoding all rows. if(m_PicParamSet.picture_structure != BOTTOM_FIELD) { SetPictureQuant(); } // Set up the values in the slice header SetSliceHeader( m_pCurrentFrame, ePic_Class ); if(m_PicParamSet.picture_structure != BOTTOM_FIELD) { // Write frame header code into bitstream buffer. status = encodeFrameHeader(m_bs1, dst, (ePic_Class == IDR_PIC)); if (status != UMC_OK) { goto done; } } if(m_info.rate_controls.method == H264_RCM_BITRATE) { int slice_qp = m_rate_control->PictureRateControl( m_pCurrentFrame->m_pYPlane, m_pCurrentFrame->m_pUPlane, m_pCurrentFrame->m_pVPlane, m_pCurrentFrame->GetSequenceNumber(), m_PicType & ((m_info.current_slice_type==INTRASLICE)-1), m_bs1->GetBitsEncoded(), ExMBInfo,m_uFrames_Num/m_info.FrameRate,(m_uFrames_Num+1)/m_info.FrameRate); m_SliceHeader.slice_qp_delta = (Ipp8s)(slice_qp - m_PicParamSet.pic_init_qp); } if (m_PicType == PREDPIC) { m_SliceHeader.slice_type = PREDSLICE; } else if (m_PicType == INTRAPIC) { m_SliceHeader.slice_type = INTRASLICE; } else { // BPREDPIC m_SliceHeader.slice_type = BPREDSLICE; } status = Start_Picture(&ePic_Class, &m_SeqParamSet, &m_PicParamSet, &m_SliceHeader, m_bs1, m_PicType); if (status != UMC_OK) { goto done; } if ((m_SliceHeader.disable_deblocking_filter_idc != 1) && (ePic_Class != DISPOSABLE_PIC)) { // init deblock filter for this frame, must be called after encoder Start_Picture // to get correct MB info pointer m_deblockingFilter.Start_Frame( Get_MBInfoArray_Pointer(), Get_SliceDataBase_Pointer(), m_PicParamSet.mb_width << 4, // width, padded to MB edge m_PicParamSet.mb_height << 4, // height, padded to MB edge m_pCurrentFrame->m_pitch, //???? for fields what is about future frame? was it field or frame? m_pCurrentFrame->m_pYPlane, m_pCurrentFrame->m_pVPlane, m_pCurrentFrame->m_pUPlane ); } for (slice = 0; slice < m_info.Num_Slices; slice++) { EnumSliceType slice_type; // Fill in the slice type in the slice header. if (m_PicType == PREDPIC) { slice_type = PREDSLICE; } else if (m_PicType == INTRAPIC) { slice_type = INTRASLICE; } else { // BPREDPIC slice_type = BPREDSLICE; }re_encode_slice: m_info.current_slice_type = slice_type; // Pass to core encoder // Compress one slice status = Compress_Slice(slice); if ((slice_type == PREDSLICE) || (slice_type == BPREDSLICE)) { if (Intra_Slice_Test()) { // Force this slice to be INTRA slice_type = INTRASLICE; m_pCurrentFrame->SetPicCodType(INTRAPIC); // Reset the RBSP m_bs1->ResetRBSP(); goto re_encode_slice; } } m_bs1->WriteTrailingBits(); // Write RBSP Trailing Bits // Copy Slice RBSP to the end of the output buffer after // Adding start codes and SC emulation prevention. dst.size += m_bs1->EndOfNAL((dst.data + dst.size), (ePic_Class != DISPOSABLE_PIC), ((ePic_Class == IDR_PIC) ? NAL_UT_IDR_SLICE : NAL_UT_SLICE)); if (status != UMC_OK) { m_bMakeNextFrameKey = true; goto done; } } // check for buffer overrun if (!m_bs1->CheckBsLimit()) { status = EncodeDummyFrame(dst); m_bMakeNextFrameKey = true; if (status == UMC_OK) { goto end_of_frame; } else { goto done; } } // inloop deblocking filtering if ((m_SliceHeader.disable_deblocking_filter_idc != 1) && (ePic_Class != DISPOSABLE_PIC)) { // Currently always called here to deblock entire frame, could be // called multiple times to deblock segments of the frame. status = m_deblockingFilter.DeblockSegment(0, 0, m_PicParamSet.mb_width*m_PicParamSet.mb_height); if (status != UMC_OK) goto done; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -