[x265] [PATCH] rc: implement qp with Aq for each Cu before encoding them
Aarthi Thirumalai
aarthi at multicorewareinc.com
Mon Oct 28 11:06:27 CET 2013
# HG changeset patch
# User Aarthi Thirumalai
# Date 1382954771 -19800
# Mon Oct 28 15:36:11 2013 +0530
# Node ID 3a3745d7052909c7b725cf7c97d91e089df30a33
# Parent ef2428fd32feddd60168f3430c50f4d7e6f02741
rc: implement qp with Aq for each Cu before encoding them.
diff -r ef2428fd32fe -r 3a3745d70529 source/common/lowres.cpp
--- a/source/common/lowres.cpp Mon Oct 28 00:08:06 2013 -0500
+++ b/source/common/lowres.cpp Mon Oct 28 15:36:11 2013 +0530
@@ -48,7 +48,8 @@
if (*aqMode)
{
m_qpAqOffset = (double*)x265_malloc(sizeof(double) * cuCount);
- if (!m_qpAqOffset)
+ m_invQscaleFactor = (int*)x265_malloc(sizeof(int) * cuCount);
+ if (!m_qpAqOffset || !m_invQscaleFactor)
*aqMode = 0;
}
@@ -110,6 +111,7 @@
X265_FREE(lowresMvCosts[1][i]);
}
X265_FREE(m_qpAqOffset);
+ X265_FREE(m_invQscaleFactor);
}
// (re) initialize lowres state
@@ -125,7 +127,7 @@
satdCost = -1;
memset(costEst, -1, sizeof(costEst));
- if (m_qpAqOffset)
+ if (m_qpAqOffset && m_invQscaleFactor)
memset(costEstAq, -1, sizeof(costEstAq));
for (int y = 0; y < bframes + 2; y++)
diff -r ef2428fd32fe -r 3a3745d70529 source/common/lowres.h
--- a/source/common/lowres.h Mon Oct 28 00:08:06 2013 -0500
+++ b/source/common/lowres.h Mon Oct 28 15:36:11 2013 +0530
@@ -36,6 +36,7 @@
/* lowres buffers, sizes and strides */
pixel *buffer[4];
double *m_qpAqOffset; // qp Aq offset values for each Cu
+ int *m_invQscaleFactor; // qScale values for qp Aq Offsets
int width; // width of lowres frame in pixels
int lines; // height of lowres frame in pixel lines
int frameNum; // Presentation frame number
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/frameencoder.cpp Mon Oct 28 15:36:11 2013 +0530
@@ -1007,6 +1007,8 @@
codeRow.m_entropyCoder.resetEntropy();
TEncSbac *bufSbac = (m_cfg->param.bEnableWavefront && col == 0 && row > 0) ? &m_rows[row - 1].m_bufferSbacCoder : NULL;
+ int qp = calcQpForCu(m_pic, cuAddr);
+ cu->setQP(0,(char)qp);
codeRow.processCU(cu, m_pic->getSlice(), bufSbac, m_cfg->param.bEnableWavefront && col == 1);
// TODO: Keep atomic running totals for rate control?
@@ -1058,6 +1060,34 @@
m_totalTime = m_totalTime + (x265_mdate() - startTime);
}
+int FrameEncoder::calcQpForCu(TComPic *pic, UInt cuAddr)
+{
+ x265_emms();
+ double qp = pic->getSlice()->getSliceQp();
+ if (m_cfg->param.rc.aqMode)
+ {
+ /* Derive qpOffet for each CU by averaging offsets for all 16x16 blocks in the cu. */
+ double qp_offset = 0;
+ int blockSize = g_maxCUWidth >> 2;
+ int maxBlockCols = (pic->getPicYuvOrg()->getWidth() + (blockSize - 1)) / blockSize;
+ int maxBlockRows = (pic->getPicYuvOrg()->getHeight() + (blockSize - 1)) / blockSize;
+ int block_y = (cuAddr / pic->getPicSym()->getFrameWidthInCU()) * 4;
+ int block_x = (cuAddr * 4) - block_y * pic->getPicSym()->getFrameWidthInCU();
+ int cnt = 0;
+ for (int h = 0; h < 4 && block_y < maxBlockRows ; h++, block_y++)
+ {
+ for (int w = 0; w < 4 && (block_x + w) < maxBlockCols; w++)
+ {
+ qp_offset += pic->m_lowres.m_qpAqOffset[block_x + w + (block_y * maxBlockCols)];
+ cnt++;
+ }
+ }
+ qp_offset /= cnt;
+ qp += qp_offset;
+ }
+ return Clip3(MIN_QP, MAX_QP, (int)(qp + 0.5));
+}
+
TComPic *FrameEncoder::getEncodedPicture(NALUnitEBSP **nalunits)
{
if (m_pic)
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/frameencoder.h Mon Oct 28 15:36:11 2013 +0530
@@ -165,7 +165,7 @@
protected:
void determineSliceBounds();
-
+ int calcQpForCu(TComPic *pic, UInt cuAddr);
Encoder* m_top;
TEncCfg* m_cfg;
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/ratecontrol.cpp Mon Oct 28 15:36:11 2013 +0530
@@ -74,34 +74,22 @@
return acEnergyVar(primitives.var[LUMA_16x16](src, srcStride), 8);
}
-/* Find the total AC energy of each CU in all planes */
-double RateControl::acEnergyCu(TComPic* pic, uint32_t cuAddr)
+/* Find the total AC energy of each block in all planes */
+double RateControl::acEnergyCu(TComPic* pic, UInt block_x, UInt block_y)
{
uint32_t var = 0;
double avgQp = 0, strength = cfg->param.rc.aqStrength * 1.0397f;
- pixel* srcLuma = pic->getPicYuvOrg()->getLumaAddr(cuAddr);
- pixel* srcCb = pic->getPicYuvOrg()->getCbAddr(cuAddr);
- pixel* srcCr = pic->getPicYuvOrg()->getCrAddr(cuAddr);
- UInt blockWidth = g_maxCUWidth >> 2;
- UInt blockHeight = g_maxCUHeight >> 2;
- UInt frameStride = pic->getPicYuvOrg()->getStride();
- UInt cStride = pic->getPicYuvOrg()->getCStride();
-
- /* Calculate Qp offset for each 16x16 block in the CU and average them over entire CU */
- for (UInt h = 0, cnt = 0; h < g_maxCUHeight; h += blockHeight)
- {
- for (UInt w = 0; w < g_maxCUWidth; w += blockWidth, cnt++)
- {
- UInt blockOffsetLuma = w + (h * frameStride);
- UInt blockOffsetChroma = (w >> 1) + ((h >> 1) * cStride);
- var = acEnergyPlane(srcLuma + blockOffsetLuma, frameStride, 0);
- var += acEnergyPlane(srcCb + blockOffsetChroma, cStride, 1);
- var += acEnergyPlane(srcCr + blockOffsetChroma, cStride, 1);
- avgQp += strength * (X265_LOG2(X265_MAX(var, 1)) - (14.427f));
- }
- }
-
- avgQp /= 16;
+ pixel* srcLuma = pic->getPicYuvOrg()->getLumaAddr() ;
+ pixel* srcCb = pic->getPicYuvOrg()->getCbAddr() ;
+ pixel* srcCr = pic->getPicYuvOrg()->getCrAddr();
+ int frameStride = pic->getPicYuvOrg()->getStride();
+ int cStride = pic->getPicYuvOrg()->getCStride();
+ UInt blockOffsetLuma = block_x + (block_y * frameStride);
+ UInt blockOffsetChroma = (block_x >> 1) + ((block_y >> 1) * cStride);
+ var = acEnergyPlane(srcLuma + blockOffsetLuma, frameStride, 0);
+ var += acEnergyPlane(srcCb + blockOffsetChroma, cStride, 1);
+ var += acEnergyPlane(srcCr + blockOffsetChroma, cStride, 1);
+ avgQp = strength * (X265_LOG2( X265_MAX(var, 1) ) - 14.427f);
x265_emms();
return avgQp;
}
@@ -111,16 +99,21 @@
/* Actual adaptive quantization */
if (cfg->param.rc.aqMode)
{
- int maxRows = pic->getPicSym()->getFrameHeightInCU();
- int maxCols = pic->getPicSym()->getFrameWidthInCU();
- for (int cu_y = 0; cu_y < maxRows; cu_y++)
+ UInt blockWidth = g_maxCUWidth >> 2;
+ UInt blockHeight = g_maxCUHeight >> 2;
+ double qp_adj = 0;
+ int block_xy = 0;
+ int maxCol = pic->getPicYuvOrg()->getWidth();
+ int maxRow = pic->getPicYuvOrg()->getHeight();
+ /* Calculate Qp offset for each 16x16 block in the frame */
+ for (int block_y = 0; block_y < maxRow; block_y += blockHeight)
{
- for (int cu_x = 0; cu_x < maxCols; cu_x++)
+ for (int block_x = 0; block_x < maxCol; block_x += blockWidth)
{
- double qp_adj;
- int cu_xy = maxCols * cu_y + cu_x;
- qp_adj = acEnergyCu(pic, cu_xy);
- pic->m_lowres.m_qpAqOffset[cu_xy] = qp_adj;
+ qp_adj = acEnergyCu(pic, block_x, block_y);
+ pic->m_lowres.m_qpAqOffset[block_xy] = qp_adj;
+ pic->m_lowres.m_invQscaleFactor[block_xy] = x265_exp2fix8(qp_adj);
+ block_xy++;
}
}
}
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/ratecontrol.h Mon Oct 28 15:36:11 2013 +0530
@@ -85,7 +85,7 @@
double getQScale(RateControlEntry *rce, double rateFactor);
double rateEstimateQscale(RateControlEntry *rce); // main logic for calculating QP based on ABR
void accumPQpUpdate();
- double acEnergyCu(TComPic* pic, uint32_t cuAddr);
+ double acEnergyCu(TComPic* pic, UInt block_x, UInt block_y);
};
}
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/slicetype.cpp Mon Oct 28 15:36:11 2013 +0530
@@ -483,8 +483,8 @@
if (bFrameScoreCU)
{
costIntra += icost;
- if (fenc->m_qpAqOffset)
- costIntraAq += (icost * x265_exp2fix8(fenc->m_qpAqOffset[cuXY]) + 128) >> 8;
+ if (fenc->m_invQscaleFactor)
+ costIntraAq += (icost * fenc->m_invQscaleFactor[cuXY] + 128) >> 8;
}
}
if (!bBidir)
@@ -505,7 +505,7 @@
{
costEst += bcost;
if (fenc->m_qpAqOffset)
- costEstAq += (bcost * x265_exp2fix8(fenc->m_qpAqOffset[cuXY]) + 128) >> 8;
+ costEstAq += (bcost * fenc->m_invQscaleFactor[cuXY] + 128) >> 8;
}
}
fenc->lowresCosts[b - p0][p1 - b][cuXY] = (uint16_t)(X265_MIN(bcost, LOWRES_COST_MASK) | (listused << LOWRES_COST_SHIFT));
More information about the x265-devel
mailing list