[x265] [PATCH] aq: Add AQ_AUTO_VARIANCE feature for performing adaptive quantization
Aarthi Thirumalai
aarthi at multicorewareinc.com
Tue Dec 24 13:15:40 CET 2013
# HG changeset patch
# User Aarthi Thirumalai
# Date 1387887324 -19800
# Tue Dec 24 17:45:24 2013 +0530
# Node ID 7a9c4e1a83ab2846c4242e794156f5c2876da405
# Parent d74f2e0856b443d05ccffd87f86fc942b58a2588
aq: Add AQ_AUTO_VARIANCE feature for performing adaptive quantization.
diff -r d74f2e0856b4 -r 7a9c4e1a83ab source/common/common.cpp
--- a/source/common/common.cpp Tue Dec 24 08:29:01 2013 +0530
+++ b/source/common/common.cpp Tue Dec 24 17:45:24 2013 +0530
@@ -494,7 +494,7 @@
"max consecutive bframe count must be 16 or smaller");
CHECK(param->lookaheadDepth > X265_LOOKAHEAD_MAX,
"Lookahead depth must be less than 256");
- CHECK(param->rc.aqMode < X265_AQ_NONE || param->rc.aqMode > X265_AQ_VARIANCE,
+ CHECK(param->rc.aqMode < X265_AQ_NONE || param->rc.aqMode > X265_AQ_AUTO_VARIANCE,
"Aq-Mode is out of range");
CHECK(param->rc.aqStrength < 0 || param->rc.aqStrength > 3,
"Aq-Strength is out of range");
diff -r d74f2e0856b4 -r 7a9c4e1a83ab source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Tue Dec 24 08:29:01 2013 +0530
+++ b/source/encoder/ratecontrol.cpp Tue Dec 24 17:45:24 2013 +0530
@@ -69,7 +69,7 @@
}
/* Find the total AC energy of each block in all planes */
-double RateControl::acEnergyCu(TComPic* pic, uint32_t block_x, uint32_t block_y)
+uint32_t RateControl::acEnergyCu(TComPic* pic, uint32_t block_x, uint32_t block_y)
{
int stride = pic->getPicYuvOrg()->getStride();
int cStride = pic->getPicYuvOrg()->getCStride();
@@ -82,8 +82,7 @@
var += acEnergyPlane(pic, pic->getPicYuvOrg()->getCbAddr() + blockOffsetChroma, cStride, 1);
var += acEnergyPlane(pic, pic->getPicYuvOrg()->getCrAddr() + blockOffsetChroma, cStride, 2);
x265_emms();
- double strength = cfg->param.rc.aqStrength * 1.0397f;
- return strength * (X265_LOG2(X265_MAX(var, 1)) - 14.427f);
+ return var;
}
void RateControl::calcAdaptiveQuantFrame(TComPic *pic)
@@ -101,10 +100,10 @@
/* Calculate Qp offset for each 16x16 block in the frame */
int block_xy = 0;
int block_x = 0, block_y = 0;
-
+ double strength = 0.f;
if (cfg->param.rc.aqMode == X265_AQ_NONE || cfg->param.rc.aqStrength == 0)
{
- /* Need to init it anyways for MB tree */
+ /* Need to init it anyways for CU tree */
int cuWidth = ((maxCol / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
int cuHeight = ((maxRow / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
int cuCount = cuWidth * cuHeight;
@@ -112,7 +111,7 @@
if(cfg->param.rc.aqMode && cfg->param.rc.aqStrength == 0 )
{
memset(pic->m_lowres.qpOffset, 0, cuCount * sizeof(double));
- memset(pic->m_lowres.qpAqOffset, 0, cuCount * sizeof(double) );
+ memset(pic->m_lowres.qpAqOffset, 0, cuCount * sizeof(double));
for (int cuxy = 0; cuxy < cuCount; cuxy++ )
pic->m_lowres.invQscaleFactor[cuxy] = 256;
}
@@ -128,20 +127,51 @@
}
else
{
- for (block_y = 0; block_y < maxRow; block_y += 16)
+ block_xy = 0;
+ double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0;
+ if (cfg->param.rc.aqMode == X265_AQ_AUTO_VARIANCE)
{
- for (block_x = 0; block_x < maxCol; block_x += 16)
+ double bit_depth_correction = pow (1 << (g_bitDepth - 8), 0.5);
+ for (block_y = 0; block_y < maxRow; block_y += 16)
{
- double qp_adj = acEnergyCu(pic, block_x, block_y);
- if (cfg->param.rc.aqMode)
+ for (block_x = 0; block_x < maxCol; block_x += 16)
{
+ uint32_t energy = acEnergyCu(pic, block_x, block_y);
+ qp_adj = pow (energy + 1, 0.125);
+ pic->m_lowres.qpOffset[block_xy] = qp_adj;
+ avg_adj += qp_adj;
+ avg_adj_pow2 += qp_adj * qp_adj;
+ block_xy++;
+ }
+ }
+ avg_adj /= ncu;
+ avg_adj_pow2 /= ncu;
+ strength = cfg->param.rc.aqStrength * avg_adj / bit_depth_correction;
+ avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - (14.f * bit_depth_correction)) / avg_adj;
+ }
+ else
+ strength = cfg->param.rc.aqStrength * 1.0397f;
+ block_xy = 0;
+ for (block_y = 0; block_y < maxRow; block_y += 16)
+ {
+ for (block_x = 0; block_x < maxCol; block_x += 16)
+ {
+ if(cfg->param.rc.aqMode == X265_AQ_AUTO_VARIANCE)
+ {
+ qp_adj =pic->m_lowres.qpOffset[block_xy];
+ qp_adj = strength * (qp_adj - avg_adj);
+ }
+ else
+ {
+ uint32_t energy = acEnergyCu(pic, block_x, block_y);
+ qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (14.427f + 2*(g_bitDepth-8)));
+ }
pic->m_lowres.qpAqOffset[block_xy] = qp_adj;
pic->m_lowres.qpOffset[block_xy] = qp_adj;
pic->m_lowres.invQscaleFactor[block_xy] = x265_exp2fix8(qp_adj);
block_xy++;
}
}
- }
}
if (cfg->param.bEnableWeightedPred)
diff -r d74f2e0856b4 -r 7a9c4e1a83ab source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Tue Dec 24 08:29:01 2013 +0530
+++ b/source/encoder/ratecontrol.h Tue Dec 24 17:45:24 2013 +0530
@@ -128,7 +128,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 block_x, uint32_t block_y);
+ uint32_t acEnergyCu(TComPic* pic, uint32_t block_x, uint32_t block_y);
void updateVbv(int64_t bits, RateControlEntry* rce);
void updatePredictor(Predictor *p, double q, double var, double bits);
diff -r d74f2e0856b4 -r 7a9c4e1a83ab source/x265.h
--- a/source/x265.h Tue Dec 24 08:29:01 2013 +0530
+++ b/source/x265.h Tue Dec 24 17:45:24 2013 +0530
@@ -162,6 +162,7 @@
#define X265_TYPE_KEYFRAME 0x0006 /* IDR or I depending on b_open_gop option */
#define X265_AQ_NONE 0
#define X265_AQ_VARIANCE 1
+#define X265_AQ_AUTO_VARIANCE 2
#define IS_X265_TYPE_I(x) ((x) == X265_TYPE_I || (x) == X265_TYPE_IDR)
#define IS_X265_TYPE_B(x) ((x) == X265_TYPE_B || (x) == X265_TYPE_BREF)
More information about the x265-devel
mailing list