📄 umc_mpeg2_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) 2002-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_MPEG2_VIDEO_ENCODER)
#include "ipps.h"
#include "umc_mpeg2_enc_defs.h"
#include "vm_time.h"
#include "vm_sys_info.h"
using namespace UMC;
static const Ipp64f ratetab[8]=
{24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0};
MPEG2VideoEncoderBase::MPEG2VideoEncoderBase ()
{
m_Inited = 0;
picture_structure = FRAME_PICTURE;
top_field_first = 0; // 1 when !progressive
repeat_first_field = 0;
vbv_delay = 19887;
onlyIFrames = 0;
encodeInfo.lFlags = FLAG_VENC_REORDER;
frame_loader = NULL;
pMBInfo = 0;
threadsAllocated = 0;
threadSpec = NULL;
threads = NULL;
vlcTableB15 = 0;
vlcTableB5c_e = 0;
m_lpbReference = NULL;
mid_Reference = MID_INVALID;
pRotFrames[0] = RotatingFrames;
pRotFrames[1] = RotatingFrames+2;
tmpFrame_buf = NULL;
mid_tmpFrame_buf = MID_INVALID;
tmpFrame = NULL;
VideoData_buff = NULL;
frames_buff = NULL;
is_frames_buff_locked = 0;
mid_frames_buff = MID_INVALID;
buff_size = 0;
quantiser_scale_value = -1;
intra_dc_precision = 0; // 8 bit
varThreshold = 0;
prqscale[0] = prqscale[1] = prqscale[2] = 0;
prsize[0] = prsize[1] = prsize[2] = 0;
pMotionData = NULL;
MotionDataCount = 0;
}
MPEG2VideoEncoderBase::~MPEG2VideoEncoderBase ()
{
Close();
}
static Ipp32u VM_THREAD_CALLCONVENTION ThreadWorkingRoutine(void* ptr)
{
threadInfo* th = (threadInfo*)ptr;
for (;;) {
// wait for start
if (VM_OK != vm_event_wait(&th->start_event)) {
vm_debug_trace(VM_DEBUG_PROGRESS, VM_STRING("ThreadWorkingRoutine result wait start_event\n"));
}
if (VM_TIMEOUT != vm_event_timed_wait(&th->quit_event, 0)) {
break;
}
switch (th->m_lpOwner->picture_coding_type) {
case I_PICTURE:
th->m_lpOwner->encodeI(th->numTh);
break;
case P_PICTURE:
th->m_lpOwner->encodeP(th->numTh);
break;
case B_PICTURE:
th->m_lpOwner->encodeB(th->numTh);
break;
}
if (VM_OK != vm_event_signal(&th->stop_event)) {
vm_debug_trace(VM_DEBUG_PROGRESS, VM_STRING("ThreadWorkingRoutine result signal stop_event\n"));
}
//vm_time_sleep(0);
}
return 0;
}
Status MPEG2VideoEncoderBase::Init(BaseCodecParams *params)
{
Ipp32s i, j;
Ipp32s sizeChanged = !m_Inited;
VideoEncoderParams *VideoParams = DynamicCast<VideoEncoderParams>(params);
if(VideoParams != 0) { // at least VideoEncoder parameters
MPEG2EncoderParams *info = DynamicCast<MPEG2EncoderParams>(params);
if (VideoParams->info.clip_info.width <= 0 || VideoParams->info.clip_info.height <= 0) {
return UMC_ERR_INVALID_PARAMS;
}
// trying to support size change
sizeChanged = sizeChanged ||
(VideoParams->info.clip_info.width != encodeInfo.info.clip_info.width) ||
(VideoParams->info.clip_info.height != encodeInfo.info.clip_info.height);
// good to have more checks before overwriting
if(NULL != info) { // Mpeg2 encoder parameters
// trying to support chroma_format change
sizeChanged = sizeChanged ||
(info->info.color_format != encodeInfo.info.color_format);
encodeInfo = *info;
} else
*(VideoEncoderParams*) &encodeInfo = *VideoParams;
} else if (NULL != params) {
*(BaseCodecParams*) &encodeInfo = *params;
} else if (!m_Inited) { // 0 when initialized means Reset
return UMC_ERR_NULL_PTR;
}
if(params == NULL) { // Reset or SetParams(0)
m_FirstFrame = 1;
B_count = 0;
closed_gop = 1;
buff_ind = 0;
num_btype = 0;
num_new = -1;
curr_gop = 0;
return UMC_OK;
}
BaseCodec::Init(params); // to prepare allocator
SetAspectRatio(encodeInfo.info.aspect_ratio_width, encodeInfo.info.aspect_ratio_height);
// FrameRate to code and extensions and back to exact value
if(UMC_OK != SetFrameRate(encodeInfo.info.framerate, encodeInfo.mpeg1))
{
vm_debug_trace(VM_DEBUG_WARNING, VM_STRING("invalid frame rate set to 30 fps\n"));
frame_rate_code = 5;
frame_rate_extension_n = 0;
frame_rate_extension_d = 0;
encodeInfo.info.framerate = 30;
}
encodeInfo.info.framerate = ratetab[frame_rate_code - 1]*(frame_rate_extension_n+1)/(frame_rate_extension_d+1);
encodeInfo.Profile_and_Level_Checks();
encodeInfo.RelationChecks();
#undef VM_DEBUG_FUNC_NAME
#define VM_DEBUG_FUNC_NAME VM_STRING("Init")
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.numThreads);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.clip_info.width);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.clip_info.height);
vm_debug_trace_f(VM_DEBUG_INFO, encodeInfo.info.framerate);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.bitrate);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.gopSize);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.IPDistance);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.profile);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.level);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.aspect_ratio_width);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.aspect_ratio_height);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.video_format);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.interlace_type);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.FieldPicture);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.color_format);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.frame_pred_frame_dct[0]);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.frame_pred_frame_dct[1]);
vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.frame_pred_frame_dct[2]);
#undef VM_DEBUG_FUNC_NAME
#define VM_DEBUG_FUNC_NAME NULL
// allocate ranges, compute search ranges and f_code
if (pMotionData && MotionDataCount < encodeInfo.IPDistance) {
MP2_FREE(pMotionData);
pMotionData = 0;
MotionDataCount = 0;
}
if (pMotionData == 0) {
pMotionData = MP2_ALLOC(MotionData, encodeInfo.IPDistance);
if( !pMotionData )
return UMC_ERR_ALLOC;
MotionDataCount = encodeInfo.IPDistance;
}
for (i = 0; i < encodeInfo.IPDistance; i++) {
for (j = 0; j < 2; j++) { // x/y
if (i==0) { // P
pMotionData[i].searchRange[0][j] = encodeInfo.rangeP[j];
RANGE_TO_F_CODE(pMotionData[i].searchRange[0][j], pMotionData[i].f_code[0][j]);
pMotionData[i].searchRange[0][j] = 4 << pMotionData[i].f_code[0][j];
pMotionData[i].f_code[1][j] = 15;
pMotionData[i].searchRange[1][j] = 0;
} else { // B
pMotionData[i].searchRange[0][j] =
(encodeInfo.rangeB[0][0]*(encodeInfo.IPDistance-i) + encodeInfo.rangeB[1][0]*(i-1))/(encodeInfo.IPDistance-1);
pMotionData[i].searchRange[1][j] =
(encodeInfo.rangeB[1][0]*(encodeInfo.IPDistance-i) + encodeInfo.rangeB[0][0]*(i-1))/(encodeInfo.IPDistance-1);
RANGE_TO_F_CODE(pMotionData[i].searchRange[0][j], pMotionData[i].f_code[0][j]);
pMotionData[i].searchRange[0][j] = 4 << pMotionData[i].f_code[0][j];
RANGE_TO_F_CODE(pMotionData[i].searchRange[1][j], pMotionData[i].f_code[1][j]);
pMotionData[i].searchRange[1][j] = 4 << pMotionData[i].f_code[1][j];
}
}
}
if (encodeInfo.info.interlace_type == PROGRESSIVE ||
encodeInfo.info.interlace_type == INTERLEAVED_BOTTOM_FIELD_FIRST)
top_field_first = 0;
else
top_field_first = 1;
if(!m_Inited) { // only first call
DC_Tbl[0] = Y_DC_Tbl;
DC_Tbl[1] = Cr_DC_Tbl;
DC_Tbl[2] = Cr_DC_Tbl;
ippiCreateRLEncodeTable(Table15, &vlcTableB15);
ippiCreateRLEncodeTable(dct_coeff_next_RL, &vlcTableB5c_e);
for(i=0; i<4; i++) {
RotatingFrames[i] = new VideoData;
}
}
// chroma format dependent
BlkWidth_c = (encodeInfo.info.color_format != YUV444) ? 8 : 16;
BlkStride_c = 16;//BlkWidth_c;
BlkHeight_c = (encodeInfo.info.color_format == YUV420) ? 8 : 16;
chroma_fld_flag = (encodeInfo.info.color_format == YUV420) ? 0 : 1;
switch (encodeInfo.info.color_format) {
case YUV420:
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 YUV422:
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 YUV444:
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;
// frame size dependent
// macroblock aligned size
MBcountH = (encodeInfo.info.clip_info.width + 15)/16;
MBcountV = (encodeInfo.info.clip_info.height + 15)/16;
if(encodeInfo.info.interlace_type != PROGRESSIVE) {
MBcountV = (MBcountV + 1) & ~1;
}
MBcount = MBcountH * MBcountV;
YFrameHSize = MBcountH * 16;
YFrameVSize = MBcountV * 16;
UVFrameHSize = (encodeInfo.info.color_format == YUV444) ? YFrameHSize : (YFrameHSize >> 1);
UVFrameVSize = (encodeInfo.info.color_format == YUV420) ? (YFrameVSize >> 1) : YFrameVSize;
YFrameSize = YFrameHSize*YFrameVSize;
UVFrameSize = UVFrameHSize*UVFrameVSize;
YUVFrameSize = YFrameSize + 2*UVFrameSize;
encodeInfo.m_SuggestedInputSize = YUVFrameSize;
block_offset_frm[0] = 0;
block_offset_frm[1] = 8;
block_offset_frm[2] = 8*YFrameHSize;
block_offset_frm[3] = 8*YFrameHSize + 8;
block_offset_frm[4] = 0;
block_offset_frm[5] = 0;
block_offset_frm[6] = 8*UVFrameHSize;
block_offset_frm[7] = 8*UVFrameHSize;
block_offset_frm[8] = 8;
block_offset_frm[9] = 8;
block_offset_frm[10] = 8*UVFrameHSize + 8;
block_offset_frm[11] = 8*UVFrameHSize + 8;
block_offset_fld[0] = 0;
block_offset_fld[1] = 8;
block_offset_fld[2] = YFrameHSize;
block_offset_fld[3] = YFrameHSize + 8;
block_offset_fld[4] = 0;
block_offset_fld[5] = 0;
block_offset_fld[6] = UVFrameHSize;
block_offset_fld[7] = UVFrameHSize;
block_offset_fld[8] = 8;
block_offset_fld[9] = 8;
block_offset_fld[10] = UVFrameHSize + 8;
block_offset_fld[11] = UVFrameHSize + 8;
// verify bitrate
{
Ipp32s BitRate = encodeInfo.info.bitrate;
Ipp64f pixrate = encodeInfo.info.framerate * YUVFrameSize * 8;
if((Ipp64f)encodeInfo.info.bitrate > pixrate)
BitRate = (Ipp32s)(pixrate); // too high
if(BitRate != 0 && (Ipp64f)encodeInfo.info.bitrate < pixrate/500)
BitRate = (Ipp32s)(pixrate/500); // too low
if ((Ipp32s)encodeInfo.info.bitrate != BitRate) {
vm_debug_trace1(VM_DEBUG_WARNING, VM_STRING("BitRate value fixed to %d\n"), (BitRate+399)/400*400);
}
encodeInfo.info.bitrate = (BitRate+399)/400*400; // 400 bps step
}
if(sizeChanged) {
if (pMBInfo != 0)
MP2_FREE(pMBInfo);
pMBInfo = MP2_ALLOC(MBInfo, MBcount);
if (pMBInfo == 0) {
return UMC_ERR_ALLOC;
}
ippsZero_8u((Ipp8u*)pMBInfo, sizeof(MBInfo)*MBcount);
if (tmpFrame_buf) {
m_pMemoryAllocator->Free(mid_tmpFrame_buf);
tmpFrame_buf = NULL;
}
if (tmpFrame) {
delete tmpFrame;
tmpFrame = NULL;
}
// allocate reference frames
if (m_lpbReference != NULL)
m_pMemoryAllocator->Free(mid_Reference);
if (UMC_OK != m_pMemoryAllocator->Alloc(&mid_Reference,
#ifdef ME_REF_ORIGINAL
4*YUVFrameSize + ALIGN_VALUE,
#else
2*YUVFrameSize + ALIGN_VALUE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -