📄 umc_vc1_enc_brc_gop.cpp
字号:
m_Quant.IHalf = 0;
m_Quant.IQuant = (m_Quant.IQuant + curQuant + 1)/2;
//m_Quant.LimIQuant = (m_Quant.LimIQuant + m_Quant.IQuant - 1)/2;
//VC1_QUANT_CLIP(m_Quant.LimIQuant,0);
VC1_QUANT_CLIP(m_Quant.IQuant, m_Quant.LimIQuant);
}
break;
case(VC1_P_FRAME):
{
//new quant calculation
curQuant = (Ipp32s)(ratio * m_Quant.PQuant - 0.5);
VC1_QUANT_CLIP(curQuant, 0);
if(curQuant != m_Quant.PQuant)
m_Quant.PHalf = 0;
m_Quant.PQuant = (m_Quant.PQuant + curQuant + 1)/2;
m_Quant.LimPQuant = (m_Quant.LimPQuant + m_Quant.PQuant - 1)/2;
VC1_QUANT_CLIP(m_Quant.LimPQuant,0);
VC1_QUANT_CLIP(m_Quant.PQuant, m_Quant.LimPQuant);
}
break;
}
};
void VC1BRC_IP::GetQuant(Ipp32u picType, Ipp8u* PQuant, bool* Half)
{
m_picType = picType;
switch (picType)
{
case(VC1_I_FRAME):
m_CurQuant.PQIndex = m_Quant.IQuant;
m_CurQuant.HalfPQ = m_Quant.IHalf;
break;
case(VC1_P_FRAME):
m_CurQuant.PQIndex = m_Quant.PQuant + m_failPQuant;
m_CurQuant.HalfPQ = m_Quant.PHalf;
if(m_encMode != VC1_BRC_CONST_QUANT_MODE)
if(m_poorRefFrame)
{//correct quant for next B frame
if(m_CurQuant.PQIndex > 9)
{
m_CurQuant.PQIndex--;
m_CurQuant.HalfPQ = 1;
m_Quant.PQuant--;
m_Quant.PHalf = 0;
}
else
{
m_CurQuant.HalfPQ = 0;
m_Quant.PHalf = 0;
}
}
VC1_QUANT_CLIP(m_CurQuant.PQIndex, m_Quant.LimPQuant);
break;
default:
break;
}
if(m_CurQuant.PQIndex > 8)
m_CurQuant.HalfPQ = 0;
#ifdef VC1_BRC_DEBUG
printf("cur quant %d\n", m_CurQuant.PQIndex);
printf("half quant %d\n", m_CurQuant.HalfPQ);
#endif
*PQuant = m_CurQuant.PQIndex;
*Half = m_CurQuant.HalfPQ;
}
////////////////////////////////////////////
// VC1BRC_IPB
////////////////////////////////////////////
VC1BRC_IPB::VC1BRC_IPB() : m_I_GOPSize(0), m_P_GOPSize(0), m_B_GOPSize(0),
m_needISize(0), m_needPSize(0), m_needBSize(0),
m_INum(0), m_PNum(0), m_BNum(0),
m_CurrINum(0), m_CurrPNum(0), m_CurrBNum(0),
m_frameInGOP(0), m_currFrameInGOP(0),
m_poorRefFrame(0), m_GOPHalfFlag(0),
m_currISize(0), m_currPSize(0), m_currBSize(0),
m_GOPSize(0), m_currGOPSize(0), m_nextGOPSize(0),
m_IP_size((Ipp32f)(VC1_P_SIZE)), m_IB_size((Ipp32f)(VC1_B_SIZE)),
m_failPQuant(0), m_failBQuant(0), m_failGOP(0),
m_AveragePQuant(0),m_AverageIQuant(0), m_AverageBQuant(0)
{
};
VC1BRC_IPB::~VC1BRC_IPB()
{
};
UMC::Status VC1BRC_IPB::Init(Ipp32u yuvFSize, Ipp32u bitrate, Ipp64f framerate,
Ipp32u mode, Ipp32u GOPLength,Ipp32u BFrLength,
Ipp32u doubleQuant)
{
UMC::Status VC1Sts = UMC::UMC_OK;
m_bitrate = bitrate;
m_framerate = framerate;
m_GOPLength = GOPLength;
m_BFrLength = BFrLength;
m_INum = 1;
m_PNum = (GOPLength - 1)/BFrLength;
m_BNum = m_PNum*BFrLength;
m_IdealFrameSize = (Ipp32u)(bitrate/framerate/8);
m_frameInGOP = m_INum + m_PNum + m_BNum;
m_GOPSize = m_IdealFrameSize * m_frameInGOP;
m_nextGOPSize = m_GOPSize;
m_needISize = (Ipp32s)(m_GOPSize/(1 + m_IP_size*m_PNum + m_IB_size*m_BNum));
m_needPSize = (Ipp32s)(m_IP_size*m_needISize);
m_needBSize = (Ipp32s)(m_IB_size*m_needISize);
m_currISize = m_needISize;
m_currPSize = m_needPSize;
m_currBSize = m_needBSize;
if(!doubleQuant)
{
Ipp32s AverageCompression = (Ipp32s)((yuvFSize)/m_needISize)/3;
VC1_QUANT_CLIP(AverageCompression, 0);
m_CurQuant.PQIndex = m_Quant.IQuant = AverageCompression;
AverageCompression = (Ipp32s)((yuvFSize)/m_needPSize)/5;
VC1_QUANT_CLIP(AverageCompression, 0);
m_Quant.PQuant = AverageCompression;
if(m_Quant.PQuant > 2)
m_Quant.PQuant -= 2;
AverageCompression = (Ipp32s)((yuvFSize)/m_needBSize)/6;
VC1_QUANT_CLIP(AverageCompression, 0);
m_Quant.BQuant = AverageCompression;
if(m_Quant.BQuant > 2)
m_Quant.BQuant -= 2;
}
else
{
if(doubleQuant > (VC1_MAX_QUANT*2))
return UMC::UMC_ERR_ALLOC;
m_encMode = VC1_BRC_CONST_QUANT_MODE;
m_CurQuant.PQIndex = m_Quant.IQuant = m_Quant.PQuant = m_Quant.BQuant = (doubleQuant>>1);
m_CurQuant.HalfPQ = m_Quant.IHalf = m_Quant.PHalf = m_Quant.BHalf = doubleQuant&0x1;
}
switch(m_encMode)
{
case VC1_BRC_HIGHT_QUALITY_MODE:
case VC1_BRC_CONST_QUANT_MODE:
m_ratio_min = (Ipp32f)(0.6);
m_buffer_overflow = (Ipp32f)(1.1);
break;
default:
m_ratio_min = (Ipp32f)(0.6);
m_buffer_overflow = (Ipp32f)(1.1);
break;
}
return VC1Sts;
};
void VC1BRC_IPB::Close()
{
Reset();
}
void VC1BRC_IPB::Reset()
{
m_CurrINum = m_CurrPNum = m_CurrBNum = 0;
m_SizeAbberation = 0;
//Frames parameters
m_currSize = 0;
//Flags
m_recoding = 0;
m_poorRefFrame = 0;
m_GOPHalfFlag = 1;
m_failPQuant = 0;
m_failBQuant = 0;
m_failGOP = 0;
//Picture params
m_picType = VC1_I_FRAME;
m_GOPSize = m_IdealFrameSize * m_frameInGOP;
m_nextGOPSize = m_GOPSize;
m_needISize = (Ipp32s)(m_GOPSize/(1 + m_IP_size*m_PNum + m_IB_size*m_BNum));
m_needPSize = (Ipp32s)(m_IP_size*m_needISize);
m_needBSize = (Ipp32s)(m_IB_size*m_needISize);
m_currISize = m_needISize;
m_currPSize = m_needPSize;
m_currBSize = m_needBSize;
};
UMC::Status VC1BRC_IPB::CheckFrameCompression(Ipp32u picType, Ipp32u currSize, UMC::Status HRDSts)
{
UMC::Status UMCSts = UMC::UMC_OK;
Ipp32s Sts = 0;
Ipp32f ratio = 0;
if(m_recoding)
m_poorRefFrame &= 0x2;
if(currSize < 0)
return UMC::UMC_ERR_INVALID_PARAMS;
m_currSize = currSize;
switch (picType)
{
case(VC1_I_FRAME):
#ifdef VC1_GOP_DEBUG
printf("I ");
#endif
m_currISize = currSize;
ratio = ((Ipp32f)m_currISize/(Ipp32f)m_needISize);
if(ratio < VC1_POOR_REF_FRAME)
m_poorRefFrame = ((m_poorRefFrame<<1) + 1)&0x3;
else
m_poorRefFrame = (m_poorRefFrame<<1)&0x3;
break;
case(VC1_P_FRAME):
#ifdef VC1_GOP_DEBUG
printf("P ");
#endif
m_currPSize = currSize;
ratio = ((Ipp32f)m_currPSize/(Ipp32f)m_needPSize);
if(ratio < VC1_POOR_REF_FRAME)
m_poorRefFrame = ((m_poorRefFrame<<1) + 1)&0x3;
else
m_poorRefFrame = (m_poorRefFrame<<1)&0x3;
break;
case(VC1_B_FRAME):
#ifdef VC1_GOP_DEBUG
printf("B ");
#endif
m_currBSize = currSize;
ratio = ((Ipp32f)m_currBSize/(Ipp32f)m_needBSize);
break;
}
#ifdef VC1_BRC_DEBUG
printf("current ratio = %f\n", ratio);
#endif
#ifdef VC1_GOP_DEBUG
printf("current ratio = %f %d %d %d\n", ratio, m_CurQuant.PQIndex, m_CurQuant.HalfPQ, currSize);
#endif
if(m_failGOP)
HRDSts = UMC::UMC_ERR_NOT_ENOUGH_BUFFER;
switch(m_encMode)
{
case VC1_BRC_HIGHT_QUALITY_MODE:
CheckFrame_QualityMode(picType, ratio, HRDSts);
break;
case VC1_BRC_CONST_QUANT_MODE:
break;
default:
break;
}
m_recoding++;
#ifdef VC1_BRC_DEBUG
printf("coded size %d\n", currSize);
#endif
return UMCSts;
};
void VC1BRC_IPB::CompleteFrame(Ipp32u picType)
{
UMC::Status UMCSts = UMC::UMC_OK;
Ipp32f ratioI = 0;
Ipp32f ratioP = 0;
Ipp32f ratioB = 0;
Ipp32s prefINeedSize = m_needISize;
Ipp32s prefPNeedSize = m_needPSize;
Ipp32s prefBNeedSize = m_needBSize;
#ifdef BRC_TEST
if(BRCFileSizeTest.RES_File)
fprintf(BRCFileSizeTest.RES_File, "%d,",m_currSize);
#endif
if(m_encMode == VC1_BRC_CONST_QUANT_MODE)
return;
m_currFrameInGOP++;
m_currGOPSize += m_currSize;
switch (picType)
{
case VC1_I_FRAME:
m_I_GOPSize += m_currSize;
m_CurrINum++;
m_AverageIQuant = m_CurQuant.PQIndex;
break;
case VC1_P_FRAME:
m_P_GOPSize += m_currSize;
m_CurrPNum++;
m_AveragePQuant += (m_CurQuant.PQIndex*2 + m_CurQuant.HalfPQ);
break;
case VC1_B_FRAME:
m_B_GOPSize += m_currSize;
m_CurrBNum++;
m_AverageBQuant += (m_CurQuant.PQIndex*2 + m_CurQuant.HalfPQ);
break;
}
if(m_GOPHalfFlag
&&((m_currGOPSize > m_GOPSize/2) || m_currFrameInGOP == m_frameInGOP/2)
|| (m_currFrameInGOP == 1) || m_failPQuant || m_failBQuant)
{
Ipp32s PBSize = m_nextGOPSize - m_currGOPSize;
if(m_currFrameInGOP != 1)
{
m_GOPHalfFlag = 0;
}
if((PBSize > m_IdealFrameSize) && (m_currFrameInGOP != m_frameInGOP))
{
m_needPSize = (Ipp32s)(PBSize/((m_PNum - m_CurrPNum)
+ (m_IB_size/m_IP_size)*(m_BNum - m_CurrBNum)));
m_needBSize = (Ipp32s)(m_needPSize*(m_IB_size/m_IP_size));
}
else
{
m_failGOP = 1;
if(m_needPSize > m_IdealFrameSize/2)
m_needPSize = (Ipp32s)(m_needPSize*0.75);
if(m_needBSize > m_IdealFrameSize/2)
m_needBSize = (Ipp32s)(m_needBSize*0.75);
}
//printf("prefPNeedSize = %d, m_needPSize = %d, m_IdealFrameSize = %d\n", prefPNeedSize, m_needPSize, m_IdealFrameSize);
//printf("prefBNeedSize = %d, m_needBSize = %d, m_IdealFrameSize = %d\n", prefBNeedSize, m_needBSize, m_IdealFrameSize);
ratioP = ((Ipp32f)prefPNeedSize/(Ipp32f)m_needPSize);
ratioB = ((Ipp32f)prefBNeedSize/(Ipp32f)m_needBSize);
if(m_needPSize < (m_IdealFrameSize>>2))
ratioP = 1;
if(m_needBSize < (m_IdealFrameSize>>2))
ratioB = 1;
QuantForNewGOP(VC1_P_FRAME, ratioP);
QuantForNewGOP(VC1_B_FRAME, ratioB);
}
if(m_currFrameInGOP == m_frameInGOP)
{
#ifdef VC1_GOP_DEBUG
printf("\nGOP ratio = %f\n\n", ((Ipp32f)m_currGOPSize/(Ipp32f)m_nextGOPSize));
printf("\nIdeal = %f\n", ((Ipp32f)m_currGOPSize/(Ipp32f)m_GOPSize));
printf("\n\n IQuant = %d PQuant = %d BQuant = %d\n\n",
m_AverageIQuant, m_AveragePQuant/(m_PNum*2) + 1, m_AverageBQuant/(m_BNum*2) + 1);
printf("-----------------------------------NEW GOP");
printf("------------------------------------------\n\n\n");
#endif
m_SizeAbberation += m_GOPSize - m_currGOPSize;
//check overflow m_SizeAbberation
if(m_SizeAbberation > 4*m_GOPSize)
m_SizeAbberation = 4*m_GOPSize;
if(m_SizeAbberation < (- 4*m_GOPSize))
m_SizeAbberation = -(4*m_GOPSize);
///---------------------------
m_AveragePQuant /= (m_PNum*2);
m_AveragePQuant++;
m_AverageBQuant /= (m_BNum*2);
m_AverageBQuant++;
///---------------------------
m_INum = 1;
m_PNum = (m_GOPLength - 1)/(m_BFrLength+1);
m_BNum = m_GOPLength - m_INum - m_PNum;
m_frameInGOP = m_INum + m_PNum + m_BNum;
m_GOPSize = m_IdealFrameSize * m_frameInGOP;
m_nextGOPSize = m_GOPSize + m_SizeAbberation;
//check m_needISize
if(m_nextGOPSize > m_GOPSize + (m_GOPSize>>1))
m_nextGOPSize = m_GOPSize + (m_GOPSize>>1);
if(m_nextGOPSize < (m_GOPSize>>1))
m_nextGOPSize = (m_GOPSize>>1);
#ifdef VC1_GOP_DEBUG
printf("nextGOPSize = %d\n", m_nextGOPSize);
printf("m_SizeAbberation = %d\n", m_SizeAbberation);
#endif
///---------------------------
{
Ipp32f P_average_size = (Ipp32f)(m_P_GOPSize/m_PNum);
Ipp32f PRatio = (P_average_size*m_AveragePQuant)/(m_I_GOPSize*m_AverageIQuant);
m_IP_size = (m_IP_size + PRatio)/2;
if(m_IP_size > 1)
m_IP_size = 1;
Ipp32f B_average_size = (Ipp32f)(m_B_GOPSize/m_BNum);
Ipp32f BIRatio = (B_average_size*m_AverageBQuant)/(m_I_GOPSize*m_AverageIQuant);
Ipp32f BPRatio = (B_average_size*m_AverageBQuant)/(m_P_GOPSize*m_AveragePQuant);
m_IB_size = (m_IB_size + BIRatio + BPRatio)/3;
if(m_IB_size > 1)
m_IB_size = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -