Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
VideoLAN
x264
Commits
b59440f0
Commit
b59440f0
authored
Mar 30, 2008
by
Fiona Glaser
Committed by
Loren Merritt
Mar 30, 2008
Browse files
variance-based psy adaptive quantization
new options: --aq-mode --aq-strength AQ is enabled by default
parent
8d8f3ea4
Changes
7
Hide whitespace changes
Inline
Side-by-side
common/common.c
View file @
b59440f0
...
...
@@ -92,6 +92,8 @@ void x264_param_default( x264_param_t *param )
param
->
rc
.
i_qp_step
=
4
;
param
->
rc
.
f_ip_factor
=
1
.
4
;
param
->
rc
.
f_pb_factor
=
1
.
3
;
param
->
rc
.
i_aq_mode
=
X264_AQ_GLOBAL
;
param
->
rc
.
f_aq_strength
=
1
.
0
;
param
->
rc
.
b_stat_write
=
0
;
param
->
rc
.
psz_stat_out
=
"x264_2pass.log"
;
...
...
@@ -494,6 +496,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
p
->
rc
.
f_ip_factor
=
atof
(
value
);
OPT2
(
"pbratio"
,
"pb-factor"
)
p
->
rc
.
f_pb_factor
=
atof
(
value
);
OPT
(
"aq-mode"
)
p
->
rc
.
i_aq_mode
=
atoi
(
value
);
OPT
(
"aq-strength"
)
p
->
rc
.
f_aq_strength
=
atof
(
value
);
OPT
(
"pass"
)
{
int
i
=
x264_clip3
(
atoi
(
value
),
0
,
3
);
...
...
@@ -883,6 +889,9 @@ char *x264_param2string( x264_param_t *p, int b_res )
s
+=
sprintf
(
s
,
" ip_ratio=%.2f"
,
p
->
rc
.
f_ip_factor
);
if
(
p
->
i_bframe
)
s
+=
sprintf
(
s
,
" pb_ratio=%.2f"
,
p
->
rc
.
f_pb_factor
);
s
+=
sprintf
(
s
,
" aq=%d"
,
p
->
rc
.
i_aq_mode
);
if
(
p
->
rc
.
i_aq_mode
)
s
+=
sprintf
(
s
,
":%.2f"
,
p
->
rc
.
f_aq_strength
);
if
(
p
->
rc
.
psz_zones
)
s
+=
sprintf
(
s
,
" zones=%s"
,
p
->
rc
.
psz_zones
);
else
if
(
p
->
rc
.
i_zones
)
...
...
encoder/analyse.c
View file @
b59440f0
...
...
@@ -2061,8 +2061,11 @@ void x264_macroblock_analyse( x264_t *h )
int
i_cost
=
COST_MAX
;
int
i
;
/* init analysis */
x264_mb_analyse_init
(
h
,
&
analysis
,
x264_ratecontrol_qp
(
h
)
);
h
->
mb
.
i_qp
=
x264_ratecontrol_qp
(
h
);
if
(
h
->
param
.
rc
.
i_aq_mode
)
x264_adaptive_quant
(
h
);
x264_mb_analyse_init
(
h
,
&
analysis
,
h
->
mb
.
i_qp
);
/*--------------------------- Do the analysis ---------------------------*/
if
(
h
->
sh
.
i_type
==
SLICE_TYPE_I
)
...
...
encoder/encoder.c
View file @
b59440f0
...
...
@@ -401,6 +401,7 @@ static int x264_validate_parameters( x264_t *h )
h
->
param
.
analyse
.
b_fast_pskip
=
0
;
h
->
param
.
analyse
.
i_noise_reduction
=
0
;
h
->
param
.
analyse
.
i_subpel_refine
=
x264_clip3
(
h
->
param
.
analyse
.
i_subpel_refine
,
1
,
6
);
h
->
param
.
rc
.
i_aq_mode
=
0
;
}
if
(
h
->
param
.
rc
.
i_rc_method
==
X264_RC_CQP
)
{
...
...
@@ -475,6 +476,12 @@ static int x264_validate_parameters( x264_t *h )
if
(
!
h
->
param
.
b_cabac
)
h
->
param
.
analyse
.
i_trellis
=
0
;
h
->
param
.
analyse
.
i_trellis
=
x264_clip3
(
h
->
param
.
analyse
.
i_trellis
,
0
,
2
);
h
->
param
.
rc
.
i_aq_mode
=
x264_clip3
(
h
->
param
.
rc
.
i_aq_mode
,
0
,
2
);
if
(
h
->
param
.
rc
.
f_aq_strength
<=
0
)
h
->
param
.
rc
.
i_aq_mode
=
0
;
/* VAQ effectively replaces qcomp, so qcomp is raised towards 1 to compensate. */
if
(
h
->
param
.
rc
.
i_aq_mode
==
X264_AQ_GLOBAL
)
h
->
param
.
rc
.
f_qcompress
=
x264_clip3f
(
h
->
param
.
rc
.
f_qcompress
+
h
->
param
.
rc
.
f_aq_strength
/
0
.
7
,
0
,
1
);
h
->
param
.
analyse
.
i_noise_reduction
=
x264_clip3
(
h
->
param
.
analyse
.
i_noise_reduction
,
0
,
1
<<
16
);
{
...
...
encoder/ratecontrol.c
View file @
b59440f0
...
...
@@ -128,6 +128,10 @@ struct x264_ratecontrol_t
int
bframes
;
/* # consecutive B-frames before this P-frame */
int
bframe_bits
;
/* total cost of those frames */
/* AQ stuff */
float
aq_threshold
;
int
*
ac_energy
;
int
i_zones
;
x264_zone_t
*
zones
;
x264_zone_t
*
prev_zone
;
...
...
@@ -169,6 +173,93 @@ static inline double qscale2bits(ratecontrol_entry_t *rce, double qscale)
+
rce
->
misc_bits
;
}
// Find the total AC energy of the block in all planes.
static
int
ac_energy_mb
(
x264_t
*
h
,
int
mb_x
,
int
mb_y
,
int
*
satd
)
{
DECLARE_ALIGNED_16
(
static
uint8_t
flat
[
16
]
)
=
{
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
,
128
};
unsigned
int
var
=
0
,
sad
,
ssd
,
i
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
int
w
=
i
?
8
:
16
;
int
stride
=
h
->
fenc
->
i_stride
[
i
];
int
offset
=
h
->
mb
.
b_interlaced
?
w
*
(
mb_x
+
(
mb_y
&~
1
)
*
stride
)
+
(
mb_y
&
1
)
*
stride
:
w
*
(
mb_x
+
mb_y
*
stride
);
int
pix
=
i
?
PIXEL_8x8
:
PIXEL_16x16
;
stride
<<=
h
->
mb
.
b_interlaced
;
sad
=
h
->
pixf
.
sad
[
pix
](
flat
,
0
,
h
->
fenc
->
plane
[
i
]
+
offset
,
stride
);
ssd
=
h
->
pixf
.
ssd
[
pix
](
flat
,
0
,
h
->
fenc
->
plane
[
i
]
+
offset
,
stride
);
var
+=
ssd
-
(
sad
*
sad
>>
(
i
?
6
:
8
));
// SATD to represent the block's overall complexity (bit cost) for intra encoding.
// exclude the DC coef, because nothing short of an actual intra prediction will estimate DC cost.
if
(
var
&&
satd
)
*
satd
+=
h
->
pixf
.
satd
[
pix
](
flat
,
0
,
h
->
fenc
->
plane
[
i
]
+
offset
,
stride
)
-
sad
/
2
;
}
return
var
;
}
void
x264_autosense_aq
(
x264_t
*
h
)
{
double
total
=
0
;
double
n
=
0
;
int
mb_x
,
mb_y
;
// FIXME: Some of the SATDs might be already calculated elsewhere (ratecontrol?). Can we reuse them?
// FIXME: Is chroma SATD necessary?
for
(
mb_y
=
0
;
mb_y
<
h
->
sps
->
i_mb_height
;
mb_y
++
)
for
(
mb_x
=
0
;
mb_x
<
h
->
sps
->
i_mb_width
;
mb_x
++
)
{
int
energy
,
satd
=
0
;
energy
=
ac_energy_mb
(
h
,
mb_x
,
mb_y
,
&
satd
);
h
->
rc
->
ac_energy
[
mb_x
+
mb_y
*
h
->
sps
->
i_mb_width
]
=
energy
;
/* Weight the energy value by the SATD value of the MB.
* This represents the fact that the more complex blocks in a frame should
* be weighted more when calculating the optimal threshold. This also helps
* diminish the negative effect of large numbers of simple blocks in a frame,
* such as in the case of a letterboxed film. */
if
(
energy
)
{
x264_cpu_restore
(
h
->
param
.
cpu
);
total
+=
logf
(
energy
)
*
satd
;
n
+=
satd
;
}
}
x264_cpu_restore
(
h
->
param
.
cpu
);
/* Calculate and store the threshold. */
h
->
rc
->
aq_threshold
=
n
?
total
/
n
:
15
;
}
/*****************************************************************************
* x264_adaptive_quant:
* adjust macroblock QP based on variance (AC energy) of the MB.
* high variance = higher QP
* low variance = lower QP
* This generally increases SSIM and lowers PSNR.
*****************************************************************************/
void
x264_adaptive_quant
(
x264_t
*
h
)
{
int
qp
=
h
->
mb
.
i_qp
;
int
energy
=
h
->
param
.
rc
.
i_aq_mode
==
X264_AQ_GLOBAL
?
ac_energy_mb
(
h
,
h
->
mb
.
i_mb_x
,
h
->
mb
.
i_mb_y
,
NULL
)
:
h
->
rc
->
ac_energy
[
h
->
mb
.
i_mb_xy
];
if
(
energy
==
0
)
h
->
mb
.
i_qp
=
h
->
mb
.
i_last_qp
;
else
{
float
result
,
qp_adj
;
x264_cpu_restore
(
h
->
param
.
cpu
);
result
=
energy
;
/* Adjust the QP based on the AC energy of the macroblock. */
qp_adj
=
1
.
5
*
(
logf
(
result
)
-
h
->
rc
->
aq_threshold
);
if
(
h
->
param
.
rc
.
i_aq_mode
==
X264_AQ_LOCAL
)
qp_adj
=
x264_clip3f
(
qp_adj
,
-
5
,
5
);
h
->
mb
.
i_qp
=
x264_clip3
(
qp
+
qp_adj
*
h
->
param
.
rc
.
f_aq_strength
+
.
5
,
h
->
param
.
rc
.
i_qp_min
,
h
->
param
.
rc
.
i_qp_max
);
/* If the QP of this MB is within 1 of the previous MB, code the same QP as the previous MB,
* to lower the bit cost of the qp_delta. */
if
(
abs
(
h
->
mb
.
i_qp
-
h
->
mb
.
i_last_qp
)
==
1
)
h
->
mb
.
i_qp
=
h
->
mb
.
i_last_qp
;
}
h
->
mb
.
i_chroma_qp
=
i_chroma_qp_table
[
x264_clip3
(
h
->
mb
.
i_qp
+
h
->
pps
->
i_chroma_qp_index_offset
,
0
,
51
)];
}
int
x264_ratecontrol_new
(
x264_t
*
h
)
{
...
...
@@ -244,7 +335,7 @@ int x264_ratecontrol_new( x264_t *h )
rc
->
rate_tolerance
=
0
.
01
;
}
h
->
mb
.
b_variable_qp
=
rc
->
b_vbv
&&
!
rc
->
b_2pass
;
h
->
mb
.
b_variable_qp
=
(
rc
->
b_vbv
&&
!
rc
->
b_2pass
)
||
h
->
param
.
rc
.
i_aq_mode
;
if
(
rc
->
b_abr
)
{
...
...
@@ -458,10 +549,13 @@ int x264_ratecontrol_new( x264_t *h )
x264_free
(
p
);
}
for
(
i
=
1
;
i
<
h
->
param
.
i_threads
;
i
++
)
for
(
i
=
0
;
i
<
h
->
param
.
i_threads
;
i
++
)
{
h
->
thread
[
i
]
->
rc
=
rc
+
i
;
rc
[
i
]
=
rc
[
0
];
if
(
i
)
rc
[
i
]
=
rc
[
0
];
if
(
h
->
param
.
rc
.
i_aq_mode
==
X264_AQ_LOCAL
)
rc
[
i
].
ac_energy
=
x264_malloc
(
h
->
mb
.
i_mb_count
*
sizeof
(
int
)
);
}
return
0
;
...
...
@@ -623,6 +717,8 @@ void x264_ratecontrol_delete( x264_t *h )
x264_free
(
rc
->
zones
[
i
].
param
);
x264_free
(
rc
->
zones
);
}
for
(
i
=
0
;
i
<
h
->
param
.
i_threads
;
i
++
)
x264_free
(
rc
[
i
].
ac_energy
);
x264_free
(
rc
);
}
...
...
@@ -729,6 +825,14 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp )
if
(
h
->
sh
.
i_type
!=
SLICE_TYPE_B
)
rc
->
last_non_b_pict_type
=
h
->
sh
.
i_type
;
/* Adaptive AQ thresholding algorithm. */
if
(
h
->
param
.
rc
.
i_aq_mode
==
X264_AQ_GLOBAL
)
/* Arbitrary value for "center" of the AQ curve.
* Chosen so that any given value of CRF has on average similar bitrate with and without AQ. */
h
->
rc
->
aq_threshold
=
logf
(
5000
);
else
if
(
h
->
param
.
rc
.
i_aq_mode
==
X264_AQ_LOCAL
)
x264_autosense_aq
(
h
);
}
double
predict_row_size
(
x264_t
*
h
,
int
y
,
int
qp
)
...
...
encoder/ratecontrol.h
View file @
b59440f0
...
...
@@ -34,6 +34,7 @@ void x264_ratecontrol_mb( x264_t *, int bits );
int
x264_ratecontrol_qp
(
x264_t
*
);
void
x264_ratecontrol_end
(
x264_t
*
,
int
bits
);
void
x264_ratecontrol_summary
(
x264_t
*
);
void
x264_adaptive_quant
(
x264_t
*
);
#endif
x264.c
View file @
b59440f0
...
...
@@ -187,6 +187,14 @@ static void Help( x264_param_t *defaults, int b_longhelp )
H0
(
" --ipratio <float> QP factor between I and P [%.2f]
\n
"
,
defaults
->
rc
.
f_ip_factor
);
H0
(
" --pbratio <float> QP factor between P and B [%.2f]
\n
"
,
defaults
->
rc
.
f_pb_factor
);
H1
(
" --chroma-qp-offset <integer> QP difference between chroma and luma [%d]
\n
"
,
defaults
->
analyse
.
i_chroma_qp_offset
);
H0
(
" --aq-mode <integer> How AQ distributes bits [%d]
\n
"
" - 0: Disabled
\n
"
" - 1: Avoid moving bits between frames
\n
"
" - 2: Move bits between frames
\n
"
,
defaults
->
rc
.
i_aq_mode
);
H0
(
" --aq-strength <float> Reduces blocking and blurring in flat and
\n
"
" textured areas. [%.1f]
\n
"
" - 0.5: weak AQ
\n
"
" - 1.5: strong AQ
\n
"
,
defaults
->
rc
.
f_aq_strength
);
H0
(
"
\n
"
);
H0
(
" -p, --pass <1|2|3> Enable multipass ratecontrol
\n
"
" - 1: First pass, creates stats file
\n
"
...
...
@@ -407,6 +415,8 @@ static int Parse( int argc, char **argv,
{
"trellis"
,
required_argument
,
NULL
,
't'
},
{
"no-fast-pskip"
,
no_argument
,
NULL
,
0
},
{
"no-dct-decimate"
,
no_argument
,
NULL
,
0
},
{
"aq-strength"
,
required_argument
,
NULL
,
0
},
{
"aq-mode"
,
required_argument
,
NULL
,
0
},
{
"deadzone-inter"
,
required_argument
,
NULL
,
'0'
},
{
"deadzone-intra"
,
required_argument
,
NULL
,
'0'
},
{
"level"
,
required_argument
,
NULL
,
0
},
...
...
x264.h
View file @
b59440f0
...
...
@@ -35,7 +35,7 @@
#include <stdarg.h>
#define X264_BUILD 5
8
#define X264_BUILD 5
9
/* x264_t:
* opaque handler for encoder */
...
...
@@ -82,6 +82,9 @@ typedef struct x264_t x264_t;
#define X264_RC_CQP 0
#define X264_RC_CRF 1
#define X264_RC_ABR 2
#define X264_AQ_NONE 0
#define X264_AQ_LOCAL 1
#define X264_AQ_GLOBAL 2
static
const
char
*
const
x264_direct_pred_names
[]
=
{
"none"
,
"spatial"
,
"temporal"
,
"auto"
,
0
};
static
const
char
*
const
x264_motion_est_names
[]
=
{
"dia"
,
"hex"
,
"umh"
,
"esa"
,
"tesa"
,
0
};
...
...
@@ -260,6 +263,9 @@ typedef struct x264_param_t
float
f_ip_factor
;
float
f_pb_factor
;
int
i_aq_mode
;
/* psy adaptive QP. (X264_AQ_*) */
float
f_aq_strength
;
/* 2pass */
int
b_stat_write
;
/* Enable stat writing in psz_stat_out */
char
*
psz_stat_out
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment