Set QP completely at CU level as the name '--set-qp-in-cu' implies

-Move slice delta QP to CU level when using --set-qp-in-cu
-Separate functionality from roi
This commit is contained in:
Ari Lemmetti 2019-05-22 17:26:10 +03:00
parent 87a9208db8
commit 9339845e8b
7 changed files with 15 additions and 31 deletions

View file

@ -138,7 +138,7 @@ Video structure:
QP values in raster order. The map can be of any
size and will be scaled to the video size.
--set-qp-in-cu : Set QP at CU level keeping pic_init_qp_minus26.
in PPS zero.
in PPS and slice_qp_delta in slize header zero.
--(no-)erp-aqp : Use adaptive QP for 360 degree video with
equirectangular projection. [disabled]
--level <number> : Use the given HEVC level in the output and give

View file

@ -1,4 +1,4 @@
.TH KVAZAAR "1" "October 2018" "kvazaar v1.2.0" "User Commands"
.TH KVAZAAR "1" "May 2019" "kvazaar v1.2.0" "User Commands"
.SH NAME
kvazaar \- open source HEVC encoder
.SH SYNOPSIS
@ -157,7 +157,7 @@ size and will be scaled to the video size.
.TP
\fB\-\-set\-qp\-in\-cu
Set QP at CU level keeping pic_init_qp_minus26.
in PPS zero.
in PPS and slice_qp_delta in slize header zero.
.TP
\fB\-\-(no\-)erp\-aqp
Use adaptive QP for 360 degree video with

View file

@ -420,7 +420,7 @@ void print_help(void)
" QP values in raster order. The map can be of any\n"
" size and will be scaled to the video size.\n"
" --set-qp-in-cu : Set QP at CU level keeping pic_init_qp_minus26.\n"
" in PPS zero.\n"
" in PPS and slice_qp_delta in slize header zero.\n"
" --(no-)erp-aqp : Use adaptive QP for 360 degree video with\n"
" equirectangular projection. [disabled]\n"
" --level <number> : Use the given HEVC level in the output and give\n"

View file

@ -352,32 +352,11 @@ encoder_control_t* kvz_encoder_control_init(const kvz_config *const cfg)
}
// If QP will be set at CU level instead of PPS,
// encoder is given qp 26 making pic_init_qp_minus26
// zero. The difference is added to the delta QP map.
if (cfg->set_qp_in_cu) {
encoder->cfg.qp = 26;
// If delta QP map does not already exist, it has to be created.
if (encoder->cfg.roi.dqps == NULL) {
encoder->cfg.roi.width = 1;
encoder->cfg.roi.height = 1;
encoder->cfg.roi.dqps = calloc(1, sizeof(cfg->roi.dqps[0]));
}
const size_t roi_size = encoder->cfg.roi.width * encoder->cfg.roi.height;
for (int i = 0; i < roi_size; ++i) {
encoder->cfg.roi.dqps[i] += cfg->qp - 26;
encoder->cfg.roi.dqps[i] = CLIP(-51, 51, encoder->cfg.roi.dqps[i]);
}
}
// NOTE: When tr_depth_inter is equal to 0, the transform is still split
// for SMP and AMP partition units.
encoder->tr_depth_inter = 0;
if (encoder->cfg.target_bitrate > 0 || encoder->cfg.roi.dqps) {
if (encoder->cfg.target_bitrate > 0 || encoder->cfg.roi.dqps || encoder->cfg.set_qp_in_cu) {
encoder->max_qp_delta_depth = 0;
} else {
encoder->max_qp_delta_depth = -1;

View file

@ -456,8 +456,9 @@ static void encoder_state_write_bitstream_pic_parameter_set(bitstream_t* stream,
WRITE_UE(stream, 0, "num_ref_idx_l1_default_active_minus1");
// If tiles and slices = tiles is enabled, signal QP in the slice header. Keeping the PPS constant for OMAF etc
bool signal_qp_in_slice_header = (encoder->cfg.slices & KVZ_SLICES_TILES) && encoder->tiles_enable;
WRITE_SE(stream, signal_qp_in_slice_header ?0:(((int8_t)encoder->cfg.qp) - 26), "pic_init_qp_minus26");
// Keep QP constant here also if it will be only set at CU level.
bool constant_qp_in_pps = ((encoder->cfg.slices & KVZ_SLICES_TILES) && encoder->tiles_enable) || encoder->cfg.set_qp_in_cu;
WRITE_SE(stream, constant_qp_in_pps ? 0 : (((int8_t)encoder->cfg.qp) - 26), "pic_init_qp_minus26");
WRITE_U(stream, 0, 1, "constrained_intra_pred_flag");
WRITE_U(stream, encoder->cfg.trskip_enable, 1, "transform_skip_enabled_flag");
@ -812,8 +813,10 @@ static void kvz_encoder_state_write_bitstream_slice_header_independent(
{
// If tiles are enabled, signal the full QP here (relative to the base value of 26)
// If QP is to be set only at CU level, force slice_qp_delta zero
bool signal_qp_in_slice_header = (encoder->cfg.slices & KVZ_SLICES_TILES) && encoder->tiles_enable;
int slice_qp_delta = state->frame->QP - (signal_qp_in_slice_header ? 26 : encoder->cfg.qp);
if(encoder->cfg.set_qp_in_cu) slice_qp_delta = 0;
WRITE_SE(stream, slice_qp_delta, "slice_qp_delta");
}
}

View file

@ -726,7 +726,8 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
const encoder_control_t *ctrl = state->encoder_control;
const kvz_config *cfg = &ctrl->cfg;
state->last_qp = state->frame->QP;
// Signaled slice QP may be different to frame QP with set-qp-in-cu enabled.
state->last_qp = ctrl->cfg.set_qp_in_cu ? 26 : state->frame->QP;
if (cfg->crypto_features) {
state->crypto_hdl = kvz_crypto_create(cfg);
@ -1140,7 +1141,7 @@ static void encoder_state_init_children(encoder_state_t * const state) {
if (state->is_leaf) {
//Leaf states have cabac and context
kvz_cabac_start(&state->cabac);
kvz_init_contexts(state, state->frame->QP, state->frame->slicetype);
kvz_init_contexts(state, state->encoder_control->cfg.set_qp_in_cu ? 26 : state->frame->QP, state->frame->slicetype);
}
//Clear the jobs

View file

@ -272,7 +272,8 @@ static int8_t get_qp_y_pred(const encoder_state_t* state, int x, int y, edge_dir
} else if (dir == EDGE_VER && x > 0) {
qp_p = kvz_cu_array_at_const(state->tile->frame->cu_array, x - 1, y)->qp;
} else {
qp_p = state->frame->QP;
// TODO: This seems to be dead code. Investigate.
qp_p = state->encoder_control->cfg.set_qp_in_cu ? 26 : state->frame->QP;
}
const int32_t qp_q =