Commit c297fd00 authored by Thomas's avatar Thomas Committed by Yaowu Xu

Add quantisation matrix range parameters.

Change-Id: I25911ea7666465ff19821b07e20c26586e88401c
parent 0527894f
......@@ -212,6 +212,8 @@ typedef struct VP10Common {
qm_val_t *uv_qmatrix[MAX_SEGMENTS][2][TX_SIZES];
int using_qmatrix;
int min_qmlevel;
int max_qmlevel;
#endif
/* We allocate a MODE_INFO struct for each macroblock, together with
......
......@@ -212,15 +212,13 @@ int vp10_get_qindex(const struct segmentation *seg, int segment_id,
}
#if CONFIG_AOM_QM
qm_val_t* aom_iqmatrix(VP10_COMMON* cm, int qindex, int is_chroma,
qm_val_t* aom_iqmatrix(VP10_COMMON* cm, int qmlevel, int is_chroma,
int log2sizem2, int is_intra) {
int scaled_q_index = aom_get_qmlevel(qindex);
return &cm->giqmatrix[scaled_q_index][!!is_chroma][!!is_intra][log2sizem2][0];
return &cm->giqmatrix[qmlevel][!!is_chroma][!!is_intra][log2sizem2][0];
}
qm_val_t* aom_qmatrix(VP10_COMMON* cm, int qindex, int is_chroma,
qm_val_t* aom_qmatrix(VP10_COMMON* cm, int qmlevel, int is_chroma,
int log2sizem2, int is_intra) {
int scaled_q_index = aom_get_qmlevel(qindex);
return &cm->gqmatrix[scaled_q_index][!!is_chroma][!!is_intra][log2sizem2][0];
return &cm->gqmatrix[qmlevel][!!is_chroma][!!is_intra][log2sizem2][0];
}
static uint16_t
......
......@@ -25,12 +25,13 @@ extern "C" {
#define QINDEX_BITS 8
#if CONFIG_AOM_QM
// Total number of QM sets stored
#define NUM_QM_LEVELS 16
#define QM_LEVEL_BITS 4
#define NUM_QM_LEVELS (1 << QM_LEVEL_BITS)
/* Offset into the list of QMs. Actual number of levels used is
(NUM_QM_LEVELS-AOM_QM_OFFSET)
Lower value of AOM_QM_OFFSET implies more heavily weighted matrices.*/
#define AOM_QM_FIRST 8
#define AOM_QM_LAST NUM_QM_LEVELS
#define DEFAULT_QM_FIRST (NUM_QM_LEVELS / 2)
#define DEFAULT_QM_LAST (NUM_QM_LEVELS - 1)
#endif
struct VP10Common;
......@@ -43,10 +44,9 @@ int vp10_get_qindex(const struct segmentation *seg, int segment_id,
#if CONFIG_AOM_QM
// Reduce the large number of quantizers to a smaller number of levels for which
// different matrices may be defined
static inline int aom_get_qmlevel(int qindex) {
int qmlevel =
(qindex * (AOM_QM_LAST - AOM_QM_FIRST) + QINDEX_RANGE / 2) / QINDEX_RANGE;
qmlevel = VPXMIN(qmlevel + AOM_QM_FIRST, NUM_QM_LEVELS - 1);
static inline int aom_get_qmlevel(int qindex, int first, int last) {
int qmlevel = (qindex * (last + 1 - first) + QINDEX_RANGE / 2) / QINDEX_RANGE;
qmlevel = VPXMIN(qmlevel + first, NUM_QM_LEVELS - 1);
return qmlevel;
}
void aom_qm_init(struct VP10Common *cm);
......
......@@ -1118,6 +1118,13 @@ static void setup_quantization(VP10_COMMON *const cm,
cm->dequant_bit_depth = cm->bit_depth;
#if CONFIG_AOM_QM
cm->using_qmatrix = vpx_rb_read_bit(rb);
if (cm->using_qmatrix) {
cm->min_qmlevel = vpx_rb_read_literal(rb, QM_LEVEL_BITS);
cm->max_qmlevel = vpx_rb_read_literal(rb, QM_LEVEL_BITS);
} else {
cm->min_qmlevel = 0;
cm->max_qmlevel = 0;
}
#endif
}
......@@ -1127,8 +1134,10 @@ static void setup_segmentation_dequant(VP10_COMMON *const cm) {
#if CONFIG_AOM_QM
int lossless;
int j = 0;
int qmindex;
int qmlevel;
int using_qm = cm->using_qmatrix;
int minqm = cm->min_qmlevel;
int maxqm = cm->max_qmlevel;
#endif
if (cm->seg.enabled) {
for (i = 0; i < MAX_SEGMENTS; ++i) {
......@@ -1145,13 +1154,14 @@ static void setup_segmentation_dequant(VP10_COMMON *const cm) {
cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
// NB: depends on base index so there is only 1 set per frame
// No quant weighting when lossless or signalled not using QM
qmindex = (lossless || using_qm == 0) ?
QINDEX_RANGE - 1 : cm->base_qindex;
qmlevel = (lossless || using_qm == 0)
? NUM_QM_LEVELS - 1
: aom_get_qmlevel(cm->base_qindex, minqm, maxqm);
for (j = 0; j < TX_SIZES; ++j) {
cm->y_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmindex, 0, j, 1);
cm->y_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmindex, 0, j, 0);
cm->uv_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmindex, 1, j, 1);
cm->uv_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmindex, 1, j, 0);
cm->y_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmlevel, 0, j, 1);
cm->y_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmlevel, 0, j, 0);
cm->uv_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmlevel, 1, j, 1);
cm->uv_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmlevel, 1, j, 0);
}
#endif
}
......@@ -1170,13 +1180,14 @@ static void setup_segmentation_dequant(VP10_COMMON *const cm) {
lossless = qindex == 0 && cm->y_dc_delta_q == 0 && cm->uv_dc_delta_q == 0 &&
cm->uv_ac_delta_q == 0;
// No quant weighting when lossless or signalled not using QM
qmindex = (lossless || using_qm == 0) ?
QINDEX_RANGE - 1 : cm->base_qindex;
qmlevel = (lossless || using_qm == 0)
? NUM_QM_LEVELS - 1
: aom_get_qmlevel(cm->base_qindex, minqm, maxqm);
for (j = 0; j < TX_SIZES; ++j) {
cm->y_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmindex, 0, j, 1);
cm->y_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmindex, 0, j, 0);
cm->uv_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmindex, 1, j, 1);
cm->uv_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmindex, 1, j, 0);
cm->y_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmlevel, 0, j, 1);
cm->y_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmlevel, 0, j, 0);
cm->uv_iqmatrix[i][1][j] = aom_iqmatrix(cm, qmlevel, 1, j, 1);
cm->uv_iqmatrix[i][0][j] = aom_iqmatrix(cm, qmlevel, 1, j, 0);
}
#endif
}
......
......@@ -865,6 +865,10 @@ static void encode_quantization(const VP10_COMMON *const cm,
write_delta_q(wb, cm->uv_ac_delta_q);
#if CONFIG_AOM_QM
vpx_wb_write_bit(wb, cm->using_qmatrix);
if (cm->using_qmatrix) {
vpx_wb_write_literal(wb, cm->min_qmlevel, QM_LEVEL_BITS);
vpx_wb_write_literal(wb, cm->max_qmlevel, QM_LEVEL_BITS);
}
#endif
}
......
......@@ -3828,6 +3828,8 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
#if CONFIG_AOM_QM
cm->using_qmatrix = cpi->oxcf.using_qm;
cm->min_qmlevel = cpi->oxcf.qm_minlevel;
cm->max_qmlevel = cpi->oxcf.qm_maxlevel;
#endif
if (oxcf->pass == 1) {
......
......@@ -168,7 +168,11 @@ typedef struct VP10EncoderConfig {
int best_allowed_q;
int cq_level;
AQ_MODE aq_mode; // Adaptive Quantization mode
#if CONFIG_AOM_QM
int using_qm;
int qm_minlevel;
int qm_maxlevel;
#endif
// Internal frame size scaling.
RESIZE_TYPE resize_mode;
......
......@@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "./vpx_dsp_rtcd.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
......@@ -388,12 +389,15 @@ void vp10_init_plane_quantizers(VP10_COMP *cpi, MACROBLOCK *x) {
const int segment_id = xd->mi[0]->mbmi.segment_id;
const int qindex = vp10_get_qindex(&cm->seg, segment_id, cm->base_qindex);
const int rdmult = vp10_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
const int lossless = xd->lossless[segment_id];
int i;
#if CONFIG_AOM_QM
const int lossless = xd->lossless[segment_id];
int minqm = cm->min_qmlevel;
int maxqm = cm->max_qmlevel;
// Quant matrix only depends on the base QP so there is only one set per frame
int qmlevel = (lossless || cm->using_qmatrix == 0) ?
NUM_QM_LEVELS - 1 : aom_get_qmlevel(cm->base_qindex);
int qmlevel = (lossless || cm->using_qmatrix == 0)
? NUM_QM_LEVELS - 1
: aom_get_qmlevel(cm->base_qindex, minqm, maxqm);
#endif
// Y
......
......@@ -41,6 +41,8 @@ struct vp10_extracfg {
unsigned int lossless;
#if CONFIG_AOM_QM
unsigned int enable_qm;
unsigned int qm_min;
unsigned int qm_max;
#endif
unsigned int frame_parallel_decoding_mode;
AQ_MODE aq_mode;
......@@ -54,25 +56,27 @@ struct vp10_extracfg {
};
static struct vp10_extracfg default_extra_cfg = {
0, // cpu_used
1, // enable_auto_alt_ref
0, // noise_sensitivity
0, // sharpness
0, // static_thresh
6, // tile_columns
0, // tile_rows
7, // arnr_max_frames
5, // arnr_strength
0, // min_gf_interval; 0 -> default decision
0, // max_gf_interval; 0 -> default decision
VPX_TUNE_PSNR, // tuning
10, // cq_level
0, // rc_max_intra_bitrate_pct
0, // rc_max_inter_bitrate_pct
0, // gf_cbr_boost_pct
0, // lossless
0, // cpu_used
1, // enable_auto_alt_ref
0, // noise_sensitivity
0, // sharpness
0, // static_thresh
6, // tile_columns
0, // tile_rows
7, // arnr_max_frames
5, // arnr_strength
0, // min_gf_interval; 0 -> default decision
0, // max_gf_interval; 0 -> default decision
VPX_TUNE_PSNR, // tuning
10, // cq_level
0, // rc_max_intra_bitrate_pct
0, // rc_max_inter_bitrate_pct
0, // gf_cbr_boost_pct
0, // lossless
#if CONFIG_AOM_QM
0, // enable_qm
0, // enable_qm
DEFAULT_QM_FIRST, // qm_min
DEFAULT_QM_LAST, // qm_max
#endif
1, // frame_parallel_decoding_mode
NO_AQ, // aq_mode
......@@ -365,6 +369,8 @@ static vpx_codec_err_t set_encoder_config(
#if CONFIG_AOM_QM
oxcf->using_qm = extra_cfg->enable_qm;
oxcf->qm_minlevel = extra_cfg->qm_min;
oxcf->qm_maxlevel = extra_cfg->qm_max;
#endif
oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
......@@ -649,6 +655,20 @@ static vpx_codec_err_t ctrl_set_enable_qm(vpx_codec_alg_priv_t *ctx,
extra_cfg.enable_qm = CAST(VP9E_SET_ENABLE_QM, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static vpx_codec_err_t ctrl_set_qm_min(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp10_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.qm_min = CAST(VP9E_SET_QM_MIN, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static vpx_codec_err_t ctrl_set_qm_max(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp10_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.qm_max = CAST(VP9E_SET_QM_MAX, args);
return update_extra_cfg(ctx, &extra_cfg);
}
#endif
static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
......@@ -1249,6 +1269,8 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ VP9E_SET_LOSSLESS, ctrl_set_lossless },
#if CONFIG_AOM_QM
{ VP9E_SET_ENABLE_QM, ctrl_set_enable_qm },
{ VP9E_SET_QM_MIN, ctrl_set_qm_min },
{ VP9E_SET_QM_MAX, ctrl_set_qm_max },
#endif
{ VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode },
{ VP9E_SET_AQ_MODE, ctrl_set_aq_mode },
......
......@@ -324,6 +324,33 @@ enum vp8e_enc_control_id {
*/
VP9E_SET_ENABLE_QM,
/*!\brief Codec control function to set the min quant matrix flatness.
*
* AOM can operate with different ranges of quantisation matrices.
* As quantisation levels increase, the matrices get flatter. This
* control sets the minimum level of flatness from which the matrices
* are determined.
*
* By default, the encoder sets this minimum at half the available
* range.
*
* Supported in codecs: AOM
*/
VP9E_SET_QM_MIN,
/*!\brief Codec control function to set the max quant matrix flatness.
*
* AOM can operate with different ranges of quantisation matrices.
* As quantisation levels increase, the matrices get flatter. This
* control sets the maximum level of flatness possible.
*
* By default, the encoder sets this maximum at the top of the
* available range.
*
* Supported in codecs: AOM
*/
VP9E_SET_QM_MAX,
#endif
/*!\brief Codec control function to set number of tile columns.
......@@ -763,6 +790,12 @@ VPX_CTRL_USE_TYPE(VP9E_SET_LOSSLESS, unsigned int)
#if CONFIG_AOM_QM
VPX_CTRL_USE_TYPE(VP9E_SET_ENABLE_QM, unsigned int)
#define VPX_CTRL_VP9E_SET_ENABLE_QM
VPX_CTRL_USE_TYPE(VP9E_SET_QM_MIN, unsigned int)
#define VPX_CTRL_VP9E_SET_QM_MIN
VPX_CTRL_USE_TYPE(VP9E_SET_QM_MAX, unsigned int)
#define VPX_CTRL_VP9E_SET_QM_MAX
#endif
VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int)
......
......@@ -369,6 +369,10 @@ static const arg_def_t lossless =
static const arg_def_t enable_qm =
ARG_DEF(NULL, "enable_qm", 1,
"Enable quantisation matrices (0: false (default), 1: true)");
static const arg_def_t qm_min = ARG_DEF(
NULL, "qm_min", 1, "Min quant matrix flatness (0..15), default is 8");
static const arg_def_t qm_max = ARG_DEF(
NULL, "qm_max", 1, "Max quant matrix flatness (0..15), default is 16");
#endif
static const arg_def_t frame_parallel_decoding = ARG_DEF(
NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
......@@ -432,33 +436,35 @@ static const arg_def_t tune_content = ARG_DEF_ENUM(
#if CONFIG_VP10_ENCODER
/* clang-format off */
static const arg_def_t *vp10_args[] = {
&cpu_used_vp9, &auto_altref, &sharpness, &static_thresh,
&tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
&tune_ssim, &cq_level, &max_intra_rate_pct, &max_inter_rate_pct,
&gf_cbr_boost_pct, &lossless,
&cpu_used_vp9, &auto_altref, &sharpness,
&static_thresh, &tile_cols, &tile_rows,
&arnr_maxframes, &arnr_strength, &arnr_type,
&tune_ssim, &cq_level, &max_intra_rate_pct,
&max_inter_rate_pct, &gf_cbr_boost_pct, &lossless,
#if CONFIG_AOM_QM
&enable_qm,
&enable_qm, &qm_min, &qm_max,
#endif
&frame_parallel_decoding, &aq_mode, &frame_periodic_boost,
&noise_sens, &tune_content, &input_color_space,
&min_gf_interval, &max_gf_interval,
NULL
&frame_parallel_decoding, &aq_mode, &frame_periodic_boost,
&noise_sens, &tune_content, &input_color_space,
&min_gf_interval, &max_gf_interval, NULL
};
static const int vp10_arg_ctrl_map[] = {
VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
VP9E_SET_MAX_INTER_BITRATE_PCT, VP9E_SET_GF_CBR_BOOST_PCT,
VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH,
VP8E_SET_ARNR_TYPE, VP8E_SET_TUNING,
VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
VP9E_SET_MAX_INTER_BITRATE_PCT, VP9E_SET_GF_CBR_BOOST_PCT,
VP9E_SET_LOSSLESS,
#if CONFIG_AOM_QM
VP9E_SET_ENABLE_QM,
VP9E_SET_ENABLE_QM, VP9E_SET_QM_MIN,
VP9E_SET_QM_MAX,
#endif
VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_NOISE_SENSITIVITY,
VP9E_SET_TUNE_CONTENT, VP9E_SET_COLOR_SPACE,
VP9E_SET_MIN_GF_INTERVAL, VP9E_SET_MAX_GF_INTERVAL,
VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_NOISE_SENSITIVITY,
VP9E_SET_TUNE_CONTENT, VP9E_SET_COLOR_SPACE,
VP9E_SET_MIN_GF_INTERVAL, VP9E_SET_MAX_GF_INTERVAL,
0
};
/* clang-format on */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment