📄 encoder_mpeg2.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) 2002-2005 Intel Corporation. All Rights Reserved.//*/#include <math.h>#include "ipps.h"#include "ippcc.h"#include "mpeg2_defs.h"#include "vm_time.h"ippMPEG2VideoEncoder::ippMPEG2VideoEncoder (){ picture_structure = FRAME_PICTURE; vbv_delay = 19887; ByteCount = 0; onlyIFrames = 0; numEncodedFrames = 0; threadSpec = NULL; threads = NULL; m_numThreads = 0; vlcTableB15 = 0; vlcTableB5c_e = 0; m_lpbReference = NULL; tmpFrame = NULL; // YUV frames buffer frames_buff = NULL;}unsigned int ThreadCallRoutine(void* ptr){ threadInfo* th = (threadInfo*)ptr; th->m_lpOwner->ThreadWorkingRoutine(th); return 0;}#ifdef MPEG2_DEBUG_CODE#define warning(Message) \ vm_string_printf(__VM_STRING(Message))#else#define warning(Message) 0#endifIppStatus ippMPEG2VideoEncoder::Init(int Width, int Height, int _BitRate, ippMPEG2EncoderParams *info){ int i; int MBcountH; int MBcountV; int MBcount; int chroma_format; static const double ratetab[8]= {24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0}; ippMPEG2EncoderParams DefaultParams; if (Width <= 0 || Height <= 0) { return ippStsBadArgErr; } BitRate = _BitRate; if (NULL == info) { info = &DefaultParams; } encodeInfo = *info; if(encodeInfo.chroma_format < CHROMA420 || encodeInfo.chroma_format > CHROMA444) { warning("chroma_format fixed to CHROMA420\n"); encodeInfo.chroma_format = CHROMA420; } chroma_format = encodeInfo.chroma_format; BlkWidth_c = (chroma_format != CHROMA444) ? 8 : 16; BlkStride_c = 16; BlkHeight_c = (chroma_format == CHROMA420) ? 8 : 16; chroma_fld_flag = (chroma_format == CHROMA420) ? 0 : 1; DC_Tbl[0] = Y_DC_Tbl; DC_Tbl[1] = Cr_DC_Tbl; DC_Tbl[2] = Cr_DC_Tbl; switch (chroma_format) { case CHROMA420: block_count = 6; func_getdiff_frame_c = ippiGetDiff8x8_8u16s_C1; func_getdiff_field_c = ippiGetDiff8x4_8u16s_C1; func_getdiffB_frame_c = ippiGetDiff8x8B_8u16s_C1; func_getdiffB_field_c = ippiGetDiff8x4B_8u16s_C1; func_mc_frame_c = ippiMC8x8_8u_C1; func_mc_field_c = ippiMC8x4_8u_C1; func_mcB_frame_c = ippiMC8x8B_8u_C1; func_mcB_field_c = ippiMC8x4B_8u_C1; break; case CHROMA422: block_count = 8; func_getdiff_frame_c = ippiGetDiff8x16_8u16s_C1; func_getdiff_field_c = ippiGetDiff8x8_8u16s_C1; func_getdiffB_frame_c = ippiGetDiff8x16B_8u16s_C1; func_getdiffB_field_c = ippiGetDiff8x8B_8u16s_C1; func_mc_frame_c = ippiMC8x16_8u_C1; func_mc_field_c = ippiMC8x8_8u_C1; func_mcB_frame_c = ippiMC8x16B_8u_C1; func_mcB_field_c = ippiMC8x8B_8u_C1; break; case CHROMA444: block_count = 12; func_getdiff_frame_c = ippiGetDiff16x16_8u16s_C1; func_getdiff_field_c = ippiGetDiff16x8_8u16s_C1; func_getdiffB_frame_c = ippiGetDiff16x16B_8u16s_C1; func_getdiffB_field_c = ippiGetDiff16x8B_8u16s_C1; func_mc_frame_c = ippiMC16x16_8u_C1; func_mc_field_c = ippiMC16x8_8u_C1; func_mcB_frame_c = ippiMC16x16B_8u_C1; func_mcB_field_c = ippiMC16x8B_8u_C1; break; } for (i = 0; i < 4; i++) { frm_dct_step[i] = BlkStride_l*sizeof(Ipp16s); fld_dct_step[i] = 2*BlkStride_l*sizeof(Ipp16s); } for (i = 4; i < block_count; i++) { frm_dct_step[i] = BlkStride_c*sizeof(Ipp16s); fld_dct_step[i] = BlkStride_c*sizeof(Ipp16s) << chroma_fld_flag; } frm_diff_off[0] = 0; frm_diff_off[1] = 8; frm_diff_off[2] = BlkStride_l*8; frm_diff_off[3] = BlkStride_l*8 + 8; frm_diff_off[4] = OFF_U; frm_diff_off[5] = OFF_V; frm_diff_off[6] = OFF_U + BlkStride_c*8; frm_diff_off[7] = OFF_V + BlkStride_c*8; frm_diff_off[8] = OFF_U + 8; frm_diff_off[9] = OFF_V + 8; frm_diff_off[10] = OFF_U + BlkStride_c*8 + 8; frm_diff_off[11] = OFF_V + BlkStride_c*8 + 8; fld_diff_off[0] = 0; fld_diff_off[1] = 8; fld_diff_off[2] = BlkStride_l; fld_diff_off[3] = BlkStride_l + 8; fld_diff_off[4] = OFF_U; fld_diff_off[5] = OFF_V; fld_diff_off[6] = OFF_U + BlkStride_c; fld_diff_off[7] = OFF_V + BlkStride_c; fld_diff_off[8] = OFF_U + 8; fld_diff_off[9] = OFF_V + 8; fld_diff_off[10] = OFF_U + BlkStride_c + 8; fld_diff_off[11] = OFF_V + BlkStride_c + 8; encodeInfo.mpeg1 = !!encodeInfo.mpeg1; encodeInfo.prog_seq = encodeInfo.mpeg1 || encodeInfo.prog_seq; encodeInfo.progressive_frame = encodeInfo.progressive_frame || encodeInfo.prog_seq; encodeInfo.FieldPicture = encodeInfo.FieldPicture && !encodeInfo.prog_seq; if(encodeInfo.IPDistance < 1) encodeInfo.IPDistance = 1; if(encodeInfo.gopSize < 1) encodeInfo.gopSize = 1; if(encodeInfo.gopSize > 132) encodeInfo.gopSize = 132; if(encodeInfo.IPDistance > encodeInfo.gopSize) encodeInfo.IPDistance = encodeInfo.gopSize; if(encodeInfo.aspectRatio < 1 || encodeInfo.aspectRatio > 15) { warning("aspectRatio fixed to square sample\n"); encodeInfo.aspectRatio = 1; } if (ippStsOk != encodeInfo.Profile_and_Level_Checks()) { warning(encodeInfo.err_warn_message); } if (ippStsOk != encodeInfo.RelationChecks()) { warning(encodeInfo.err_warn_message); } encodeInfo.intra_dc_precision = 1; encodeInfo.repeat_first_field = 0; picture_structure = FRAME_PICTURE; onlyIFrames = 0; ByteCount = 0; M = encodeInfo.IPDistance; N = encodeInfo.gopSize; srcYFrameHSize = Width; srcYFrameVSize = Height; srcUVFrameHSize = (chroma_format == CHROMA444) ? srcYFrameHSize : (srcYFrameHSize >> 1); srcUVFrameVSize = (chroma_format == CHROMA420) ? (srcYFrameVSize >> 1) : srcYFrameVSize; srcYFrameSize = srcYFrameHSize*srcYFrameVSize; srcUVFrameSize = srcUVFrameHSize*srcUVFrameVSize; srcYUVFrameSize = srcYFrameSize + 2*srcUVFrameSize; MBcountH = (srcYFrameHSize + 15)/16; MBcountV = (srcYFrameVSize + 15)/16; if(!encodeInfo.prog_seq) { MBcountV = (MBcountV + 1) & ~1; } MBcount = MBcountH * MBcountV; YFrameHSize = MBcountH * 16; YFrameVSize = MBcountV * 16; UVFrameHSize = (chroma_format == CHROMA444) ? YFrameHSize : (YFrameHSize >> 1); UVFrameVSize = (chroma_format == CHROMA420) ? (YFrameVSize >> 1) : YFrameVSize; YFrameSize = YFrameHSize*YFrameVSize; UVFrameSize = UVFrameHSize*UVFrameVSize; YUVFrameSize = YFrameSize + 2*UVFrameSize; block_offset_frm[0] = block_offset_frm_ref[0] = 0; block_offset_frm[1] = block_offset_frm_ref[1] = 8; block_offset_frm[2] = block_offset_frm_ref[2] = 8*YFrameHSize; block_offset_frm[3] = block_offset_frm_ref[3] = 8*YFrameHSize + 8; block_offset_frm[4] = block_offset_frm_ref[4] = 0; block_offset_frm[5] = block_offset_frm_ref[5] = 0; block_offset_frm[6] = block_offset_frm_ref[6] = 8*UVFrameHSize; block_offset_frm[7] = block_offset_frm_ref[7] = 8*UVFrameHSize; block_offset_frm[8] = block_offset_frm_ref[8] = 8; block_offset_frm[9] = block_offset_frm_ref[9] = 8; block_offset_frm[10] = block_offset_frm_ref[10] = 8*UVFrameHSize + 8; block_offset_frm[11] = block_offset_frm_ref[11] = 8*UVFrameHSize + 8; block_offset_fld[0] = block_offset_fld_ref[0] = 0; block_offset_fld[1] = block_offset_fld_ref[1] = 8; block_offset_fld[2] = block_offset_fld_ref[2] = YFrameHSize; block_offset_fld[3] = block_offset_fld_ref[3] = YFrameHSize + 8; block_offset_fld[4] = block_offset_fld_ref[4] = 0; block_offset_fld[5] = block_offset_fld_ref[5] = 0; block_offset_fld[6] = block_offset_fld_ref[6] = UVFrameHSize; block_offset_fld[7] = block_offset_fld_ref[7] = UVFrameHSize; block_offset_fld[8] = block_offset_fld_ref[8] = 8; block_offset_fld[9] = block_offset_fld_ref[9] = 8; block_offset_fld[10] = block_offset_fld_ref[10] = UVFrameHSize + 8; block_offset_fld[11] = block_offset_fld_ref[11] = UVFrameHSize + 8; IntraQMatrix = encodeInfo.IntraQMatrix; NonIntraQMatrix = (encodeInfo.CustomNonIntraQMatrix) ? encodeInfo.NonIntraQMatrix : NULL; if(encodeInfo.frame_rate_code < 1 || encodeInfo.frame_rate_code > 8) { warning("frame_rate_code fixed to 5 (30 fps)\n"); encodeInfo.frame_rate_code = 5; } FrameRate = ratetab[encodeInfo.frame_rate_code - 1]; { double pixrate = FrameRate * YUVFrameSize * 8; if((double)BitRate > pixrate) BitRate = (int)(pixrate); // too high if((double)BitRate < pixrate/500) BitRate = (int)(pixrate/500); // too low if (_BitRate != BitRate) warning("BitRate value fixed\n"); BitRate = (BitRate+399)/400*400; // 400 bps step } rc_ave_frame_bits = BitRate / FrameRate; if(encodeInfo.VBV_BufferSize <= (int)(rc_ave_frame_bits / 16384 * 4) ) { // avoid too small encodeInfo.VBV_BufferSize = (int)(rc_ave_frame_bits / 16384 * 8); } encodeInfo.VBV_BufferSize = min(encodeInfo.VBV_BufferSize, (encodeInfo.mpeg1 ? 0x3fe : 0x3fffe)); quantiser_scale_value = 0; if (N == 1 && M == 1) { onlyIFrames = 1; } // error checking if ((0 == encodeInfo.gopSize) || (encodeInfo.IPDistance > encodeInfo.gopSize)) { return ippStsBadArgErr; } // allocate reference frames { if (m_lpbReference) { delete m_lpbReference; } m_lpbReference = new Ipp8u[2*YUVFrameSize + 16]; if (NULL == m_lpbReference) { return ippStsMemAllocErr; } YRefFrameF = (Ipp8u*)(((size_t)m_lpbReference + 15) &~ 15); URefFrameF = YRefFrameF + YFrameSize; VRefFrameF = URefFrameF + UVFrameSize; YRefFrameB = VRefFrameF + UVFrameSize; URefFrameB = YRefFrameB + YFrameSize; VRefFrameB = URefFrameB + UVFrameSize; } m_numThreads = info->numThreads; if (m_numThreads != 1) { if (m_numThreads < 1) { m_numThreads = 1; } int max_threads = MBcountV; if (!encodeInfo.prog_seq || encodeInfo.FieldPicture) { max_threads = MBcountV/2; } if (m_numThreads > max_threads) { m_numThreads = max_threads; } } threadSpec = (threadSpecificData*)ippsMalloc_8u(m_numThreads*sizeof(threadSpecificData)); if (m_numThreads > 1) { threads = new threadInfo[m_numThreads - 1]; for (i = 0; i < m_numThreads - 1; i++) { vm_event_set_invalid(&threads[i].start_event); if (VM_OK != vm_event_init(&threads[i].start_event, 0, 0)) return ippStsMemAllocErr; vm_event_set_invalid(&threads[i].stop_event); if (VM_OK != vm_event_init(&threads[i].stop_event, 0, 0)) return ippStsMemAllocErr; vm_event_set_invalid(&threads[i].quit_event); if (VM_OK != vm_event_init(&threads[i].quit_event, 0, 0)) return ippStsMemAllocErr; vm_thread_set_invalid(&threads[i].thread); if (0 == vm_thread_create(&threads[i].thread, ThreadCallRoutine, &threads[i])) { return ippStsMemAllocErr; } threads[i].numTh = i + 1; threads[i].m_lpOwner = this; } } pMBInfo = (MBInfo *)ippsMalloc_8u(MBcount*sizeof(MBInfo)); int mb_shift = (encodeInfo.prog_seq) ? 4 : 5; for(i = 0; i < m_numThreads; i++) { threadSpec[i].pDiff_ = (short*)ippsMalloc_8u(3*256*sizeof(short)); threadSpec[i].pDiff1_ = (short*)ippsMalloc_8u(3*256*sizeof(short)); threadSpec[i].pMBlock_ = (short*)ippsMalloc_8u(3*256*sizeof(short)); threadSpec[i].start_row = ((YFrameVSize>>mb_shift)*i/m_numThreads) << mb_shift; threadSpec[i].me_matrix_size = 0; threadSpec[i].me_matrix_buff = NULL; threadSpec[i].me_matrix_id = 0; } if (encodeInfo.CustomIntraQMatrix) { int i; InvIntraQMatrix = _InvIntraQMatrix; for (i = 0; i < 64; i++) { InvIntraQMatrix[i] = 1.f / (Ipp32f)IntraQMatrix[i]; } } else { InvIntraQMatrix = NULL; } if (encodeInfo.CustomNonIntraQMatrix) { int i; InvNonIntraQMatrix = _InvNonIntraQMatrix; for (i = 0; i < 64; i++) { InvNonIntraQMatrix[i] = 1.f / (Ipp32f)NonIntraQMatrix[i]; } } else { InvNonIntraQMatrix = NULL; } ippiCreateRLEncodeTable(Table15, &vlcTableB15); ippiCreateRLEncodeTable(dct_coeff_next_RL, &vlcTableB5c_e); // initialize rate control InitRateControl(); cpu_freq = (double)(int)(GET_FREQUENCY); motion_estimation_time = 0; // frames list numEncodedFrames = 0; m_GOP_Start = 0; B_count = 0; m_bFirstFrame = true; // YUV frames buffer buff_size = encodeInfo.IPDistance + 1; frames_buff = NULL; buff_ind = 0; num_btype = 0; num_new = 0; curr_gop = 0; return ippStsOk;}IppStatus ippMPEG2VideoEncoder::GetInfo(int *pWidth, int *pHeight, double *pFrameRate, int *pBitRate, ippMPEG2EncoderParams *Params){ if (pWidth) *pWidth = srcYFrameHSize; if (pHeight) *pHeight = srcYFrameVSize; if (pFrameRate) *pFrameRate = FrameRate; if (pBitRate) *pBitRate = BitRate; if (Params) *Params = encodeInfo; return ippStsOk;}IppStatus ippMPEG2VideoEncoder::Close(){ int i; if (!threadSpec) { return ippStsNullPtrErr; } if (threads) { // let all threads to exit for (i = 0; i < m_numThreads - 1; i++) { vm_event_signal(&threads[i].quit_event); vm_event_signal(&threads[i].start_event); } for (i = 0; i < m_numThreads - 1; i++) { if (vm_thread_is_valid(&threads[i].thread)) { vm_thread_wait(&threads[i].thread); vm_thread_set_invalid(&threads[i].thread); vm_thread_close(&threads[i].thread); } if (vm_event_is_valid(&threads[i].start_event)) { vm_event_destroy(&threads[i].start_event); vm_event_set_invalid(&threads[i].start_event); } if (vm_event_is_valid(&threads[i].stop_event)) { vm_event_destroy(&threads[i].stop_event); vm_event_set_invalid(&threads[i].stop_event); } if (vm_event_is_valid(&threads[i].quit_event)) { vm_event_destroy(&threads[i].quit_event); vm_event_set_invalid(&threads[i].quit_event); } } delete threads; } for(i = 0; i < m_numThreads; i++) { if(threadSpec[i].pDiff_) { ippsFree(threadSpec[i].pDiff_); threadSpec[i].pDiff_ = NULL; } if(threadSpec[i].pDiff1_) { ippsFree(threadSpec[i].pDiff1_); threadSpec[i].pDiff1_ = NULL; } if(threadSpec[i].pMBlock_) { ippsFree(threadSpec[i].pMBlock_); threadSpec[i].pMBlock_ = NULL; } if (threadSpec[i].me_matrix_buff) { delete threadSpec[i].me_matrix_buff; threadSpec[i].me_matrix_buff = NULL; } } if(pMBInfo) { ippsFree(pMBInfo); pMBInfo = NULL; } if(threadSpec) { ippsFree(threadSpec); threadSpec = NULL; } if(vlcTableB15) { ippiHuffmanTableFree_32s(vlcTableB15); vlcTableB15 = NULL; } if(vlcTableB5c_e) { ippiHuffmanTableFree_32s(vlcTableB5c_e); vlcTableB5c_e = NULL; } if (m_lpbReference) { delete m_lpbReference; m_lpbReference = NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -