⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mode.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
	nBitsHead += statSrc.nBitsHead;
	nBitsY += statSrc.nBitsY;
	nBitsCr += statSrc.nBitsCr;
	nBitsCb += statSrc.nBitsCb;
	nBitsA += statSrc.nBitsA;
//	nBits1stShpCode += statSrc.nBits1stShpCode;
	nBitsCOD += statSrc.nBitsCOD;
	nBitsCBPY += statSrc.nBitsCBPY;
	nBitsMCBPC += statSrc.nBitsMCBPC;
	nBitsDQUANT += statSrc.nBitsDQUANT;
	nBitsMODB += statSrc.nBitsMODB;
	nBitsCBPB += statSrc.nBitsCBPB;
	nBitsMBTYPE += statSrc.nBitsMBTYPE;
	nBitsIntraPred += statSrc.nBitsIntraPred;
	nBitsNoDCT += statSrc.nBitsNoDCT;	
	nBitsCODA += statSrc.nBitsCODA;
	nBitsCBPA += statSrc.nBitsCBPA;
	nBitsMODBA += statSrc.nBitsMODBA;
	nBitsCBPBA += statSrc.nBitsCBPBA;
	nBitsStuffing += statSrc.nBitsStuffing;
	nSkipMB += statSrc.nSkipMB;
	nInterMB += statSrc.nInterMB;
	nInter4VMB += statSrc.nInter4VMB;
	nIntraMB += statSrc.nIntraMB;
	nDirectMB += statSrc.nDirectMB;
	nForwardMB += statSrc.nForwardMB;
	nBackwardMB += statSrc.nBackwardMB;
	nInterpolateMB += statSrc.nInterpolateMB;
	nBitsInterlace += statSrc.nBitsInterlace;
	nFieldForwardMB += statSrc.nFieldForwardMB;
	nFieldBackwardMB += statSrc.nFieldBackwardMB;
	nFieldInterpolateMB += statSrc.nFieldInterpolateMB;
	nFieldDirectMB += statSrc.nFieldDirectMB;
	nFieldDCTMB += statSrc.nFieldDCTMB;
	nVOPs += statSrc.nVOPs;
	nBitsMV += statSrc.nBitsMV;
	nBitsTexture += statSrc.nBitsTexture;
	nBitsShape += statSrc.nBitsShape;
	nBitsTotal += statSrc.nBitsTotal;
	dSNRY += statSrc.dSNRY;
	dSNRU += statSrc.dSNRU;
	dSNRV += statSrc.dSNRV;
	dSNRA += statSrc.dSNRA;
	nQMB += statSrc.nQMB;
	nQp += statSrc.nQp;
}

Void CStatistics::reset ()
{
	nBitsHead = 0;
	nBitsY = 0;
	nBitsCr = 0;
	nBitsCb = 0;
	nBitsA = 0;
//	nBits1stShpCode = 0;
	nBitsCOD = 0;
	nBitsCBPY = 0;
	nBitsMCBPC = 0;
	nBitsDQUANT = 0;
	nBitsMODB = 0;
	nBitsCBPB = 0;
	nBitsMBTYPE = 0;
	nBitsIntraPred = 0;
	nBitsNoDCT = 0;
	nBitsCODA = 0;
	nBitsCBPA = 0;
	nBitsMODBA = 0;
	nBitsCBPBA = 0;
	nBitsStuffing = 0;
	nSkipMB = 0;
	nInterMB = 0;
	nInter4VMB = 0;
	nIntraMB = 0;
	nDirectMB = 0;
	nForwardMB = 0;
	nBackwardMB = 0;
	nInterpolateMB = 0;
	nBitsInterlace = 0;
	nFieldForwardMB = 0;
	nFieldBackwardMB = 0;
	nFieldInterpolateMB = 0;
	nFieldDirectMB = 0;
	nFieldDCTMB = 0;
	nVOPs = 0;
	nBitsMV = 0;
	nBitsTexture = 0;
	nBitsShape = 0;
	nBitsTotal = 0;
	dSNRY = 0;
	dSNRU = 0;
	dSNRV = 0;
	dSNRA = 0;
	nQMB = 0;
	nQp = 0;
}

CStatistics& CStatistics::operator = (const CStatistics& statSrc)
{
	nBitsHead = statSrc.nBitsHead;
	nBitsY = statSrc.nBitsY;
	nBitsCr = statSrc.nBitsCr;
	nBitsCb = statSrc.nBitsCb;
	nBitsA = statSrc.nBitsA;
//	nBits1stShpCode = statSrc.nBits1stShpCode;
	nBitsCOD = statSrc.nBitsCOD;
	nBitsCBPY = statSrc.nBitsCBPY;
	nBitsMCBPC = statSrc.nBitsMCBPC;
	nBitsDQUANT = statSrc.nBitsDQUANT;
	nBitsMODB = statSrc.nBitsMODB;
	nBitsCBPB = statSrc.nBitsCBPB;
	nBitsMBTYPE = statSrc.nBitsMBTYPE;
	nBitsIntraPred = statSrc.nBitsIntraPred;
	nBitsNoDCT = statSrc.nBitsNoDCT;	
	nBitsCODA = statSrc.nBitsCODA;
	nBitsCBPA = statSrc.nBitsCBPA;
	nBitsMODBA = statSrc.nBitsMODBA;
	nBitsCBPBA = statSrc.nBitsCBPBA;
	nBitsStuffing = statSrc.nBitsStuffing;
	nSkipMB = statSrc.nSkipMB;
	nInterMB = statSrc.nInterMB;
	nInter4VMB = statSrc.nInter4VMB;
	nIntraMB = statSrc.nIntraMB;
	nDirectMB = statSrc.nDirectMB;
	nForwardMB = statSrc.nForwardMB;
	nBackwardMB = statSrc.nBackwardMB;
	nInterpolateMB = statSrc.nInterpolateMB;
	nBitsInterlace = statSrc.nBitsInterlace;
	nFieldForwardMB = statSrc.nFieldForwardMB;
	nFieldBackwardMB = statSrc.nFieldBackwardMB;
	nFieldInterpolateMB = statSrc.nFieldInterpolateMB;
	nFieldDirectMB = statSrc.nFieldDirectMB;
	nFieldDCTMB = statSrc.nFieldDCTMB;
	nVOPs = statSrc.nVOPs;
	nBitsMV = statSrc.nBitsMV;
	nBitsTexture = statSrc.nBitsTexture;
	nBitsShape = statSrc.nBitsShape;
	nBitsTotal = statSrc.nBitsTotal;
	dSNRY = statSrc.dSNRY;
	dSNRU = statSrc.dSNRU;
	dSNRV = statSrc.dSNRV;
	dSNRA = statSrc.dSNRA;
	nQMB = statSrc.nQMB;
	nQp = statSrc.nQp;
	return *this;
}


UInt CStatistics::total ()
{
	nBitsTexture = nBitsY + nBitsCr + nBitsCb + nBitsA + nBitsCOD
					+ nBitsCBPY + nBitsMCBPC + nBitsDQUANT
					+ nBitsMODB + nBitsCBPB	+ nBitsMBTYPE 
					+ nBitsIntraPred + nBitsNoDCT
					+ nBitsInterlace
					+ nBitsCODA + nBitsCBPA + nBitsMODBA + nBitsCBPBA;
	nBitsTotal = nBitsHead + nBitsTexture + nBitsMV + nBitsShape + nBitsStuffing;
	return nBitsTotal;
}

UInt CStatistics::head ()
{
	/*
	UInt bitsHead = nBitsCr + nBitsCb + nBitsA + nBitsCOD
					+ nBitsCBPY + nBitsMCBPC + nBitsDQUANT
					+ nBitsMODB + nBitsCBPB	+ nBitsMBTYPE 
					+ nBitsIntraPred + nBitsNoDCT
					+ nBitsInterlace
					+ nBitsCODA + nBitsCBPA + nBitsMODBA + nBitsCBPBA;
	bitsHead +=  nBitsHead + nBitsMV + nBitsShape + nBitsStuffing;
	*/
	UInt bitsHead = nBitsTotal - nBitsTexture;
	return bitsHead;
}

Void CRCMode::reset (UInt uiFirstFrame, UInt uiLastFrame, UInt uiTemporalRate, 
					   UInt uiBufferSize, Double mad, UInt uiBitsFirstFrame, Double dFrameHz)
{
	m_Ts = (uiLastFrame - uiFirstFrame + 1) / 30.0;
	m_Rs = (UInt) (uiBufferSize / m_Ts);
	m_Ns = uiTemporalRate;
	m_X1 = m_Rs * m_Ns / 2.0;				// 1st order coefficient transient
	m_X2 = 0.0;								// 2nd order coeeficient transient
	m_Nr = (uiLastFrame - uiFirstFrame + 1) / m_Ns - 1;
	m_Nc = 0;
	m_Rf = uiBitsFirstFrame;
	m_Rc = uiBitsFirstFrame;
	m_S = uiBitsFirstFrame;
	m_Qc = 15;
	m_Qp = 15;							// a simple solution (assumption)
	m_Rr = (UInt) (m_Ts * m_Rs) - m_Rf;	// total number of bits available for this segment
	m_Rp = m_Rr / m_Nr;					// average bits to be removed from the buffer
	m_Bs = m_Rs / 2;					// assumed buffer size
	m_B = m_Rs / 4;						// current buffer level	containing the bits for first frame
	for (UInt i = 0; i < RC_MAX_SLIDING_WINDOW; i++) {// if 0, don't use that frame (rejected outliers)
		m_rgQp[i] = 0;
		m_rgRp[i] = 0.0;
	}
	m_Ec = mad; 
	m_skipNextFrame = FALSE;
}

UInt CRCMode::updateQuanStepsize ()
{
	// Target bit calculation 
	m_T = (UInt) max (m_Rs / 30.0, m_Rr / m_Nr * (1.0 - RC_PAST_PERCENT) + m_S * RC_PAST_PERCENT); // a minimum of Rs/30 is assigned to each frame
	m_T = (UInt) (m_T * (m_B + 2.0 * (m_Bs - m_B)) / (2.0 * m_B + (m_Bs - m_B))); // increase if less than half, decrease if more than half, don't change if half
	if ((m_B + m_T) >	(1.0 - RC_SAFETY_MARGIN) * m_Bs)
		m_T = (UInt) max (m_Rs / 30.0, (1.0 - RC_SAFETY_MARGIN) * m_Bs - m_B); // to avoid buffer overflow
	else if ((m_B - m_Rp + m_T) < RC_SAFETY_MARGIN * m_Bs)
		m_T = m_Rp - m_B + (UInt) (RC_SAFETY_MARGIN * m_Bs);			  // to avoid buffer underflow
	m_T = min (m_T, (UInt)m_Rr);	

	// Quantization level calculation
	m_T = max (m_Rp / 3 + m_Hp, m_T);
	Double dtmp = m_Ec * m_X1 * m_Ec * m_X1 + 4 * m_X2 * m_Ec * (m_T - m_Hp);
	if ((m_X2 == 0.0) || (dtmp < 0) || ((sqrt (dtmp) - m_X1 * m_Ec) <= 0.0))	// fall back 1st order mode
		m_Qc = (UInt) (m_X1 * m_Ec / (Double) (m_T - m_Hp));
	else				// 2nd order mode
		m_Qc = (UInt) ((2 * m_X2 * m_Ec) / (sqrt (dtmp) - m_X1 * m_Ec));
	m_Qc = (UInt) min (ceil(m_Qp * (1.0 + RC_MAX_Q_INCREASE)), (Double) m_Qc);	// control variation
	m_Qc = min (m_Qc, RC_MAX_QUANT);						// clipping
	m_Qc = (UInt) max (ceil(m_Qp * (1.0 - RC_MAX_Q_INCREASE)), (Double) m_Qc);	// control variation
	m_Qc = max (m_Qc, RC_MIN_QUANT);						// clipping	
	return m_Qc;
}

Void CRCMode::updateRCModel (UInt uiBitsTotalCurr, UInt uiBitsHeadCurr)
{
	UInt n_windowSize;

	m_Rc = uiBitsTotalCurr;		// total bits used for the current frame 
	m_B += m_Rc - m_Rp;			// update buffer fillness
	m_Rr -= m_Rc;				// update the remaining bits
	if (m_Nr != 1) 
		assert (m_Rr > 0.0);	// check if there is any bits left, except the last frame
	m_S = m_Rc;					// update the previous bits
	m_Hc = uiBitsHeadCurr;		// update the current header and motion bits
	m_Hp = m_Hc;				// update the previous header and motion bits
	m_Qp = m_Qc;				// update the previous qunatization level
	m_Nr--;						// update the frame counter
	m_Nc++;

	Int i;
	for (i = RC_MAX_SLIDING_WINDOW - 1; i > 0; i--) {// update the history
		m_rgQp[i] = m_rgQp[i - 1];
		m_rgRp[i] = m_rgRp[i - 1];
	}
	m_rgQp[0] = m_Qc;
	m_rgRp[0] = (m_Rc - m_Hc) / m_Ec;

	n_windowSize = (m_Ep > m_Ec) ? (UInt) (m_Ec / m_Ep * 20) : (UInt) (m_Ep / m_Ec * 20);
	n_windowSize = max (n_windowSize, 1);
	n_windowSize = min (n_windowSize, m_Nc);
	for (i = 0; i < RC_MAX_SLIDING_WINDOW; i++) {
		m_rgRejected[i] = FALSE;
	}

	// initial RD model estimator
	RCModelEstimator (n_windowSize);

	// remove outlier	
	Double error[20], std = 0.0, threshold;
	for (i = 0; i < (Int) n_windowSize; i++) {
		error[i] = m_X1 / m_rgQp[i] + m_X2 / (m_rgQp[i] * m_rgQp[i]) - m_rgRp[i];
		std += error[i] * error[i];	
	}
	threshold = (n_windowSize == 2) ? 0 : sqrt (std / n_windowSize);
	for (i = 0; i < (Int) n_windowSize; i++) {
		if (fabs(error[i]) > threshold)
			m_rgRejected[i] = TRUE;
	}
    // always include the last data point
	m_rgRejected[0] = FALSE;

	// second RD model estimator
	RCModelEstimator (n_windowSize);
}

Bool CRCMode::skipThisFrame ()
{
	if (m_B > (Int) ((RC_SKIP_MARGIN / 100.0) * m_Bs)) {	// buffer full!
		m_skipNextFrame = TRUE;						// set the status
		m_Nr--;										// skip one frame
		m_B -= m_Rp;								// decrease current buffer level
	} else
		m_skipNextFrame = FALSE;
	return m_skipNextFrame;
}

Void CRCMode::RCModelEstimator (UInt n_windowSize)
{
	UInt n_realSize = n_windowSize;
	UInt i;
	for (i = 0; i < n_windowSize; i++) {// find the number of samples which are not rejected
		if (m_rgRejected[i])
			n_realSize--;
	}

	// default RD model estimation results
	Bool estimateX2 = FALSE;
	m_X1 = m_X2 = 0.0;
	Double oneSampleQ = 0.0;
	for (i = 0; i < n_windowSize; i++)	{
		if (!m_rgRejected[i])
			oneSampleQ = m_rgQp[i];
	}
	for (i = 0; i < n_windowSize; i++)	{// if all non-rejected Q are the same, take 1st order model
		if ((m_rgQp[i] != oneSampleQ) && !m_rgRejected[i])
			estimateX2 = TRUE;
		if (!m_rgRejected[i])
			m_X1 += (m_rgQp[i] * m_rgRp[i]) / n_realSize;
	}

	// take 2nd order model to estimate X1 and X2
	if ((n_realSize >= RC_START_RATE_CONTROL) && estimateX2) {
		Double a00 = 0.0, a01 = 0.0, a10 = 0.0, a11 = 0.0, b0 = 0.0, b1 = 0.0;
		for (UInt i = 0; i < n_windowSize; i++) {
			if (!m_rgRejected[i]) {
				a00 = a00 + 1.0;
				a01 += 1.0 / m_rgQp[i];
				a10 = a01;
				a11 += 1.0 / (m_rgQp[i] * m_rgQp[i]);
				b0 += m_rgQp[i] * m_rgRp[i];
				b1 += m_rgRp[i];
			}
		}
		// solve the equation of AX = B
		CMatrix2x2D A = CMatrix2x2D (a00, a01, a10, a11);
		CMatrix2x2D AInv = A.inverse ();
		CVector2D B = CVector2D (b0, b1);
		CVector2D solution = AInv.apply (B);
		if (solution.x != 0.0) {
			m_X1 = solution.x;
			m_X2 = solution.y;
		}	
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -