📄 h263_enc_misc.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) 2005-2007 Intel Corporation. All Rights Reserved.
//
// Description: class ippVideoEncoderH263
// Contents:
// ~ippVideoEncoderH263
// ippVideoEncoderH263(h263e_Param)
// Close
// Init
// ExpandFrame
//
*/
#include <math.h>
#include "h263_enc.hpp"
ippVideoEncoderH263::ippVideoEncoderH263(h263e_Param *par)
{
Init(par);
}
ippVideoEncoderH263::~ippVideoEncoderH263()
{
Close();
}
void ippVideoEncoderH263::Close()
{
if (mIsInit) {
// free
if (mMBinfo)
delete [] mMBinfo;
if (mbsAlloc && cBS.mBuffer)
ippsFree(cBS.mBuffer);
if (mBuffer_1)
ippsFree(mBuffer_1);
if (mBuffer_2)
ippsFree(mBuffer_2);
if (mMEfastSAD)
ippsFree(mMEfastSAD);
if (mRTPdata.GOBstartPos)
ippsFree(mRTPdata.GOBstartPos);
if (mRTPdata.MBpos)
ippsFree(mRTPdata.MBpos);
if (mRTPdata.MBquant)
ippsFree(mRTPdata.MBquant);
if (mRTPdata.MBpredMV)
ippsFree(mRTPdata.MBpredMV);
if (mRTPdata.MBpredMV1)
ippsFree(mRTPdata.MBpredMV1);
if (mFrame)
delete [] mFrame;
}
mIsInit = false;
}
Ipp32s ippVideoEncoderH263::Init(h263e_Param *par)
{
Ipp32s i, j;
IppStatus stsAlloc = ippStsNoErr;
// check parameters correctness
if (par->Width < 1 || par->Width > 8191) {
ErrorMessage(VM_STRING("Width must be between 1 and 8191"));
return H263_STS_ERR_PARAM;
}
if (par->Width & 1) {
ErrorMessage(VM_STRING("Width must be a even"));
return H263_STS_ERR_PARAM;
}
if (par->Height < 1 || par->Height > 8191) {
ErrorMessage(VM_STRING("Height must be between 1 and 8191"));
return H263_STS_ERR_PARAM;
}
if (par->Height & 1) {
ErrorMessage(VM_STRING("Height must be a even"));
return H263_STS_ERR_PARAM;
}
if (!par->RateControl && (par->quantIPic < 1 || par->quantIPic > 31)) {
ErrorMessage(VM_STRING("quantIPic must be between 1 and 31"));
return H263_STS_ERR_PARAM;
}
if (!par->RateControl && (par->quantPPic < 1 || par->quantPPic > 31)) {
ErrorMessage(VM_STRING("quantPPic must be between 1 and 31"));
return H263_STS_ERR_PARAM;
}
/*
if (!par->RateControl && (par->quantBPic < 1 || par->quantBPic > 31)) {
ErrorMessage(VM_STRING("quantBPic must be between 1 and 31"));
return H263_STS_ERR_PARAM;
}
*/
if (par->IPicdist < 1) {
ErrorMessage(VM_STRING("IPicdist must be positive"));
return H263_STS_ERR_PARAM;
}
if (par->RateControl && par->BitRate <= 0) {
ErrorMessage(VM_STRING("BitRate must be positive"));
return H263_STS_ERR_PARAM;
}
if (par->SceneChangeThreshold < 0 || par->SceneChangeThreshold > 100) {
ErrorMessage(VM_STRING("SceneChangeThreshold must be between 0 and 100"));
return H263_STS_ERR_PARAM;
}
if (0) { // ??? tmp
if (par->TimeResolution != 30000) {
ErrorMessage(VM_STRING("TimeResolution must equal 30000 in the current implementation")); // ???
return H263_STS_ERR_PARAM;
}
if ((par->TimeIncrement % 1001) || par->TimeIncrement < 1001 || par->TimeIncrement > 256 * 1001) {
ErrorMessage(VM_STRING("TimeIncrement must equal i*1001 (i=1,256) in the current implementation")); // ???
return H263_STS_ERR_PARAM;
}
} else {
if (par->TimeResolution < 1) {
ErrorMessage(VM_STRING("TimeResolution must be positive"));
return H263_STS_ERR_PARAM;
}
if (par->TimeIncrement < 1) {
ErrorMessage(VM_STRING("TimeIncrement must be positive"));
return H263_STS_ERR_PARAM;
}
if (par->PPicdist < 1) {
ErrorMessage(VM_STRING("PPicdist must be positive"));
return H263_STS_ERR_PARAM;
}
if (par->IPicdist % par->PPicdist != 0) {
ErrorMessage(VM_STRING("IPicdist must be an integer multiple of PPicdist"));
return H263_STS_ERR_PARAM;
}
if (par->PPicsearchWidth < 1 || par->PPicsearchWidth > IPP_MIN(1023, par->Width)) {
ErrorMessage(VM_STRING("PPicsearchWidth must be between 1 and MIN(1023, Width)"));
return H263_STS_ERR_PARAM;
}
if (par->PPicsearchHeight < 1 || par->PPicsearchHeight > IPP_MIN(1023, par->Height)) {
ErrorMessage(VM_STRING("PPicsearchWidth must be between 1 and MIN(1023, Height)"));
return H263_STS_ERR_PARAM;
}
/*
if (par->BPicsearchWidthForw < 1 || par->BPicsearchWidthForw > IPP_MIN(1023, par->Width)) {
ErrorMessage(VM_STRING("BPicsearchWidthForw must be between 1 and MIN(1023, Width)"));
return H263_STS_ERR_PARAM;
}
if (par->BPicsearchHeightForw < 1 || par->BPicsearchHeightForw > IPP_MIN(1023, par->Height)) {
ErrorMessage(VM_STRING("BPicsearchWidthForw must be between 1 and MIN(1023, Height)"));
return H263_STS_ERR_PARAM;
}
if (par->BPicsearchWidthBack < 1 || par->BPicsearchWidthBack > IPP_MIN(1023, par->Width)) {
ErrorMessage(VM_STRING("BPicsearchWidthBack must be between 1 and MIN(1023, Width)"));
return H263_STS_ERR_PARAM;
}
if (par->BPicsearchHeightBack < 1 || par->BPicsearchHeightBack > IPP_MIN(1023, par->Height)) {
ErrorMessage(VM_STRING("BPicsearchWidthBack must be between 1 and MIN(1023, Height)"));
return H263_STS_ERR_PARAM;
}
*/
}
Close();
memset(&mVideoSequence, 0, sizeof(mVideoSequence));
memset(&mVideoPicture, 0, sizeof(mVideoPicture));
mVideoSequence.pic_time_increment_resolution = par->TimeResolution;
mVideoSequence.fixed_pic_time_increment = par->TimeIncrement;
{
Ipp64f finc = mVideoSequence.fixed_pic_time_increment * 0.001;
if (finc == (Ipp32s)finc || mVideoSequence.pic_time_increment_resolution != 30000) {
mVideoPicture.PCF = 1;
mVideoPicture.temporal_reference_increment = 1;
if (finc == (Ipp32s)finc) {
mVideoPicture.clock_conversion_code = 1000;
mVideoPicture.clock_divisor = (Ipp32s)finc;
} else {
mVideoPicture.clock_conversion_code = 1001;
mVideoPicture.clock_divisor = mVideoSequence.fixed_pic_time_increment / mVideoPicture.clock_conversion_code;
}
if (mVideoPicture.clock_divisor > 127) {
mVideoPicture.temporal_reference_increment = mVideoPicture.clock_divisor;
mVideoPicture.clock_divisor = 1;
if (mVideoPicture.temporal_reference_increment > 1023) {
Ipp64f fcld = sqrt((Ipp64f)mVideoPicture.temporal_reference_increment);
Ipp32s tinc, cld, prod, bestdiff;
finc = fcld;
if (fcld > 127.0) {
finc = finc * fcld / 127.0;
fcld = 127.0;
}
tinc = (Ipp32s)finc + 1;
if (tinc > 1023)
tinc = 1023;
cld = (Ipp32s)fcld;
prod = tinc * cld;
bestdiff = h263e_Abs(mVideoPicture.temporal_reference_increment - prod);
if (cld < 127 && bestdiff > h263e_Abs(mVideoPicture.temporal_reference_increment - prod - tinc))
cld++;
else if (bestdiff > h263e_Abs(mVideoPicture.temporal_reference_increment - prod + cld))
tinc--;
mVideoPicture.temporal_reference_increment = tinc;
mVideoPicture.clock_divisor = cld;
mVideoSequence.fixed_pic_time_increment = par->TimeIncrement = tinc * cld * mVideoPicture.clock_conversion_code;
}
}
} else {
mVideoPicture.PCF = 0;
mVideoPicture.temporal_reference_increment = mVideoSequence.fixed_pic_time_increment / 1001;
// if (mVideoPicture.temporal_reference_increment > 255) // checked earlier
// mVideoPicture.temporal_reference_increment = 255;
}
}
{
Ipp32s picSize = par->Width * par->Height;
// H.263 Spec, Table 1
if (picSize < 25360)
mBPPmax = 64 << 10;
else if (picSize < 101392)
mBPPmax = 256 << 10;
else if (picSize < 405520)
mBPPmax = 512 << 10;
else
mBPPmax = 1024 << 10;
}
//mNumOfFrames = par->NumOfFrames;
// mNumOfFrames = -1; ???
mSkipFrame = 0;
mRateControl = par->RateControl;
mFrameSkipEnabled = par->FrameSkip;
mBitsEncodedTotal = 0;
if (mRateControl) {
mBitRate = par->BitRate;
mBitsDesiredFrame = (Ipp32s)((Ipp64s)mBitRate * par->TimeIncrement / par->TimeResolution);
if (mBitsDesiredFrame > mBPPmax) // ??? mBPPmax can be larger if negotiated by external means
mBitsDesiredFrame = mBPPmax;
mBitsDesiredTotal = 0;
mQuantIPic = mQuantPPic = (par->Width * par->Height / mBitsDesiredFrame) + 1;
h263e_Clip(mQuantIPic, 2, 31); // 3,31 ???
h263e_Clip(mQuantPPic, 2, 31); // 3,31 ???
mQuantBPic = (mQuantPPic * 5 >> 2) + 1;
h263e_Clip(mQuantBPic, 2, 31);
mRCfa = mBitsDesiredFrame;
mRCfap = 10;
// mRCfap = par->TimeResolution / par->TimeIncrement;
mRCqap = 100;
mRCbap = 10;
mRCq = mQuantIPic;
mRCqa = 1. / (Ipp64f)mRCq;
} else {
mQuantIPic = par->quantIPic;
mQuantPPic = par->quantPPic;
// mQuantBPic = par->quantBPic;
}
mIPicdist = par->IPicdist;
mPPicdist = par->PPicdist;
mBPicdist = mPPicdist - 1;
mMEalgorithm = par->MEalgorithm;
mMEaccuracy = par->MEaccuracy;
mMEfastHP = 0; // using fast algorithm for halfpel MVs (faster but with lower PSNR and compression)
mGOBheaders = par->GOBheaders;
mGSTUF = par->GOBheaders >= 2;
mCalcPSNR = par->calcPSNR;
mFrameCount = 0;
mLastIPic = -mIPicdist;
mVideoSequence.aspect_ratio_info = H263e_ASPECT_RATIO_1_1;
mVideoPicture.pic_width = par->Width;
mVideoPicture.pic_height = par->Height;
mVideoPicture.advIntra = par->advIntra ? 1 : 0;
mVideoPicture.UMV = par->UMV;
mVideoPicture.advPred = par->advPred ? 1 : 0;
mVideoPicture.modQuant = par->modQuant ? 1 : 0;
// mVideoPicture.deblockFilt = par->deblockFilt;
mVideoPicture.deblockFilt = 0;
// mVideoSequence.newpred_enable = 0;
//f mVideoSequence.requested_upstream_message_type;
//f mVideoSequence.newpred_segment_type;
// mVideoSequence.reduced_resolution_pic_enable = 0;
// mVideoSequence.scalability = 0;
//f mVideoSequence.ScalabilityParameters;
mVideoPicture.pic_time_increment = 0;
mVideoPicture.pic_rounding_type = 0;
mPPicsearchHor = par->PPicsearchWidth;
mPPicsearchVer = par->PPicsearchHeight;
// calc pic_fcode_forward for PPics
i = IPP_MAX(mPPicsearchHor, mPPicsearchVer);
// j = i << 1;
// mPPicfcodeForw = 1;
// while (j > ((16 << mPPicfcodeForw) - 1))
// mPPicfcodeForw ++;
{
mPPicdist = 1;
mBPicdist = 0;
mVideoSequence.data_partitioned = 0;
// mVideoSequence.scalability = 0;
mVideoPicture.pic_rounding_type = 0;
mVideoPicture.split_screen_indicator = 0;
mVideoPicture.document_camera_indicator = 0;
mVideoPicture.full_picture_freeze_release = 0;
if (par->Width == 128 && par->Height == 96) {
mVideoPicture.source_format = 1;
mVideoPicture.num_gobs_in_pic = 6;
mVideoPicture.num_macroblocks_in_gob = 8;
mVideoPicture.num_MBrows_in_gob = 1;
} else if (par->Width == 176 && par->Height == 144) {
mVideoPicture.source_format = 2;
mVideoPicture.num_gobs_in_pic = 9;
mVideoPicture.num_macroblocks_in_gob = 11;
mVideoPicture.num_MBrows_in_gob = 1;
} else if (par->Width == 352 && par->Height == 288) {
mVideoPicture.source_format = 3;
mVideoPicture.num_gobs_in_pic = 18;
mVideoPicture.num_macroblocks_in_gob = 22;
mVideoPicture.num_MBrows_in_gob = 1;
} else if (par->Width == 704 && par->Height == 576) {
mVideoPicture.source_format = 4;
mVideoPicture.num_gobs_in_pic = 18;
mVideoPicture.num_macroblocks_in_gob = 88;
mVideoPicture.num_MBrows_in_gob = 2;
} else if (par->Width == 1408 && par->Height == 1152) {
mVideoPicture.source_format = 5;
mVideoPicture.num_gobs_in_pic = 18;
mVideoPicture.num_macroblocks_in_gob = 352;
mVideoPicture.num_MBrows_in_gob = 4;
} else {
ErrorMessage(VM_STRING("Currently unsupported picture size"));
return H263_STS_ERR_PARAM;
}
// mVideoPicture.temporal_reference_increment = mVideoSequence.fixed_pic_time_increment / 1001;
if (mMEaccuracy > 2)
mMEaccuracy = 2;
// mBPicsearchHorForw = mBPicsearchVerForw = mBPicsearchHorBack = mBPicsearchVerBack = 0;
mME4mv = 0;
}
#if 0
else {
mBPicsearchHorForw = par->BPicsearchWidthForw;
mBPicsearchVerForw = par->BPicsearchHeightForw;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -