📄 umc_vc1_enc_brc_gop.cpp
字号:
m_currGOPSize = 0;
m_I_GOPSize = m_P_GOPSize = 0;
m_CurrINum = m_CurrPNum = 0;
m_currFrameInGOP = 0;
m_SizeAbberation = 0;
//Frames parameters
m_currSize = 0;
m_needISize = (Ipp32s)(m_GOPSize/(1 + m_IP_size*m_PNum));
m_needPSize = (Ipp32s)(m_IP_size*m_needISize);
m_currISize = m_needISize;
m_currPSize = m_needPSize;
//Flags
m_recoding = 0;
m_poorRefFrame = 0;
m_GOPHalfFlag = 1;
m_failPQuant = 0;
m_failGOP = 0;
//Picture params
m_picType = VC1_I_FRAME;
};
UMC::Status VC1BRC_IP::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 = 1;
else
m_poorRefFrame = 0;
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 = 1;
else
m_poorRefFrame = 0;
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_IP::CompleteFrame(Ipp32u picType)
{
UMC::Status UMCSts = UMC::UMC_OK;
Ipp32f ratioI = 0;
Ipp32f ratioP = 0;
Ipp32s prefINeedSize = m_needISize;
Ipp32s prefPNeedSize = m_needPSize;
#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;
}
if(m_GOPHalfFlag
&& ((m_currGOPSize > m_GOPSize/2) || m_currFrameInGOP == m_GOPLength/2)
|| (m_currFrameInGOP == 1) || m_failPQuant)
{
Ipp32s PBSize = m_nextGOPSize - m_currGOPSize;
if(m_currFrameInGOP != 1)
{
m_GOPHalfFlag = 0;
}
if(((PBSize) > m_IdealFrameSize) && ( m_currFrameInGOP != m_GOPLength))
{
m_needPSize = (Ipp32s)(PBSize/((m_PNum - m_CurrPNum)));
}
else
{
m_failGOP = 1;
if(m_needPSize > m_IdealFrameSize/2)
m_needPSize = (Ipp32s)(m_needPSize*0.75);
}
ratioP = ((Ipp32f)prefPNeedSize/(Ipp32f)m_needPSize);
if(m_needPSize < (m_IdealFrameSize>>2))
ratioP = 1;
QuantForNewGOP(VC1_P_FRAME, ratioP);
}
if(m_currFrameInGOP == m_GOPLength)
{
#ifdef VC1_GOP_DEBUG
printf("\nGOP ratio = %f\n", ((Ipp32f)m_currGOPSize/(Ipp32f)m_nextGOPSize));
printf("\nIdeal = %f\n", ((Ipp32f)m_currGOPSize/(Ipp32f)m_GOPSize));
printf("\n\n IQuant = %d PQuant = %d\n\n", m_AverageIQuant, m_AveragePQuant/(m_PNum*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_INum = 1;
m_PNum = (m_GOPLength - 1)/(m_BFrLength+1);
m_GOPSize = m_IdealFrameSize * m_GOPLength;
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
//---------------------------
{
m_AveragePQuant /= (m_PNum*2);
m_AveragePQuant++;
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;
#ifdef VC1_GOP_DEBUG
printf("\n\n I:P = %f\n\n", m_IP_size);
#endif
}
//---------------------------
m_needISize = (Ipp32s)(m_nextGOPSize/(1 + m_IP_size*m_PNum));
ratioI = ((Ipp32f)prefINeedSize/(Ipp32f)m_needISize);
QuantForNewGOP(VC1_I_FRAME, ratioI);
m_currFrameInGOP = 0;
m_poorRefFrame = 0;
m_currGOPSize = 0;
m_GOPHalfFlag = 1;
m_I_GOPSize = 0;
m_P_GOPSize = 0;
m_CurrINum = 0;
m_CurrPNum = 0;
m_failGOP = 0;
m_AveragePQuant = 0;
m_AverageIQuant = 0;
}
m_recoding = 0;
m_failPQuant = 0;
#ifdef VC1_BRC_DEBUG
printf("\n\n\n");
#endif
};
void VC1BRC_IP::CheckFrame_QualityMode(Ipp32u picType, Ipp32f ratio, UMC::Status UMCSts)
{
Ipp32s curQuant = 0;
Ipp32s Sts = VC1_BRC_OK;
bool HalfQP = 0;
//new quant calculation
curQuant = (Ipp32s)(ratio * m_CurQuant.PQIndex + 0.5);
VC1_QUANT_CLIP(curQuant, 0);
//check compression
if((ratio <= m_buffer_overflow) && (ratio >= VC1_GOOD_COMPRESSION))
Sts = VC1_BRC_OK; //good frame
else if(ratio > m_buffer_overflow)
Sts |= VC1_BRC_NOT_ENOUGH_BUFFER; //could be critical situation, if HRD buffer small
else if(ratio <= m_ratio_min)
{
//very small frame
Sts |= VC1_BRC_ERR_SMALL_FRAME;
if(m_CurQuant.PQIndex > 1)
HalfQP = 1;
}
else if(ratio >= VC1_MIN_RATIO_HALF)
{
if((m_CurQuant.PQIndex > 1) && ((Ipp32u)curQuant > m_CurQuant.PQIndex))
HalfQP = 1;
Sts |= VC1_BRC_SMALL_FRAME;
}
else
Sts |= VC1_BRC_SMALL_FRAME;
//check HRD status
if(UMCSts == UMC::UMC_ERR_NOT_ENOUGH_BUFFER)
{
Sts |= VC1_BRC_NOT_ENOUGH_BUFFER;
HalfQP = 0;
}
if(Sts != VC1_BRC_OK)
switch (picType)
{
case(VC1_I_FRAME):
{
#ifdef VC1_BRC_DEBUG
printf("m_LimIQuant %d\n", m_Quant.LimIQuant);
#endif
m_Quant.IQuant = (m_Quant.IQuant + curQuant)/2;
if(Sts & VC1_BRC_NOT_ENOUGH_BUFFER)
{
if(ratio > VC1_RATIO_ILIM)
{
m_Quant.IQuant++;
m_Quant.LimIQuant = m_CurQuant.PQIndex + 2;
}
else
{
if(m_CurQuant.PQIndex > 9)
m_Quant.LimIQuant = m_CurQuant.PQIndex + 1;
else if(m_Quant.IQuant <= m_CurQuant.PQIndex)
HalfQP = 1;
}
}
else if(Sts & VC1_BRC_ERR_SMALL_FRAME)
{
m_Quant.LimIQuant--;
if(m_Quant.IQuant >= m_CurQuant.PQIndex)
m_Quant.IQuant--;
if((ratio > VC1_MIN_RATIO_HALF) && (m_CurQuant.PQIndex > 1))
HalfQP = 1;
}
else if(Sts & VC1_BRC_SMALL_FRAME)
{
m_Quant.LimIQuant--;
if((m_Quant.IQuant < m_CurQuant.PQIndex) && m_Quant.IQuant && (m_CurQuant.PQIndex > 1))
HalfQP = 1;
}
VC1_QUANT_CLIP(m_Quant.LimIQuant,0);
VC1_QUANT_CLIP(m_Quant.IQuant, m_Quant.LimIQuant);
m_Quant.IHalf = HalfQP;
}
break;
case(VC1_P_FRAME):
{
#ifdef VC1_BRC_DEBUG
printf("m_LimPQuant %d\n", m_Quant.LimPQuant);
#endif
if(Sts & VC1_BRC_NOT_ENOUGH_BUFFER)
{
if(ratio > VC1_RATIO_ILIM)
{
m_failPQuant = (m_Quant.PQuant + curQuant + 1)/2 - m_Quant.PQuant;
m_Quant.PQuant++;
m_Quant.LimPQuant = m_CurQuant.PQIndex + 1;
}
else
{
m_Quant.PQuant = (m_Quant.PQuant + curQuant + 1)/2;
if(m_Quant.PQuant <= m_CurQuant.PQIndex)
if(m_CurQuant.PQIndex > 9)
{
if(m_Quant.PQuant <= m_CurQuant.PQIndex)
m_Quant.PQuant++;
}
else
{
if(!m_CurQuant.HalfPQ)
HalfQP = 1;
else
{
HalfQP = 0;
if(m_Quant.PQuant <= m_CurQuant.PQIndex)
m_Quant.PQuant++;
}
}
}
}
else if(Sts & VC1_BRC_ERR_SMALL_FRAME)
{
m_Quant.PQuant = (m_Quant.PQuant + curQuant + 1)/2;
m_Quant.LimPQuant--;
if(m_CurQuant.PQIndex > 9)
{
if(m_Quant.PQuant >= m_CurQuant.PQIndex)
m_Quant.PQuant--;
}
else
{
if(m_CurQuant.HalfPQ)
HalfQP = 0;
else
{
if(m_Quant.PQuant >= m_CurQuant.PQIndex)
m_Quant.PQuant--;
}
}
}
else if(Sts & VC1_BRC_SMALL_FRAME)
{
m_Quant.PQuant = (m_Quant.PQuant + curQuant + 1)/2;
m_Quant.LimPQuant--;
if(m_CurQuant.HalfPQ)
HalfQP = 0;
else
{
if(m_Quant.PQuant >= m_CurQuant.PQIndex)
{
m_Quant.PQuant--;
if((m_CurQuant.PQIndex != VC1_MIN_QUANT) && (ratio > VC1_MIN_RATIO_HALF))
HalfQP = 1;
}
}
}
VC1_QUANT_CLIP(m_Quant.LimPQuant,0);
VC1_QUANT_CLIP(m_Quant.PQuant, m_Quant.LimPQuant);
m_Quant.PHalf = HalfQP;
}
break;
}
};
void VC1BRC_IP::QuantForNewGOP(Ipp32u picType, Ipp32f ratio)
{
Ipp32s curQuant = 0;
if(ratio == 1)
return;
switch (picType)
{
case(VC1_I_FRAME):
{
//new quant calculation
curQuant = (Ipp32s)(ratio * m_Quant.IQuant + 0.5);
VC1_QUANT_CLIP(curQuant, 0);
if(curQuant != m_Quant.IQuant)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -