diff --git a/README.md b/README.md index 8f65b64f..4a775a21 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,8 @@ Video structure: the QP delta map followed by width*height delta 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. --(no-)erp-aqp : Use adaptive QP for 360 degree video with equirectangular projection. [disabled] --level : Use the given HEVC level in the output and give diff --git a/doc/kvazaar.1 b/doc/kvazaar.1 index 6e4411b6..ccfd148d 100644 --- a/doc/kvazaar.1 +++ b/doc/kvazaar.1 @@ -1,4 +1,4 @@ -.TH KVAZAAR "1" "July 2018" "kvazaar v1.2.0" "User Commands" +.TH KVAZAAR "1" "August 2018" "kvazaar v1.2.0" "User Commands" .SH NAME kvazaar \- open source HEVC encoder .SH SYNOPSIS @@ -146,6 +146,10 @@ the QP delta map followed by width*height delta QP values in raster order. The map can be of any 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. +.TP \fB\-\-(no\-)erp\-aqp Use adaptive QP for 360 degree video with equirectangular projection. [disabled] diff --git a/src/cfg.c b/src/cfg.c index 2abb296b..a8b3f32e 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -121,6 +121,7 @@ int kvz_config_init(kvz_config *cfg) cfg->roi.width = 0; cfg->roi.height = 0; cfg->roi.dqps = NULL; + cfg->set_qp_in_cu = false; cfg->erp_aqp = false; @@ -1151,6 +1152,9 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value) fclose(f); } + else if OPT("set-qp-in-cu") { + cfg->set_qp_in_cu = (bool)atobool(value); + } else if OPT("erp-aqp") { cfg->erp_aqp = (bool)atobool(value); } diff --git a/src/cli.c b/src/cli.c index 57393ada..07a918ae 100644 --- a/src/cli.c +++ b/src/cli.c @@ -130,6 +130,7 @@ static const struct option long_options[] = { { "high-tier", no_argument, NULL, 0 }, { "me-steps", required_argument, NULL, 0 }, { "fast-residual-cost", required_argument, NULL, 0 }, + { "set-qp-in-cu", no_argument, NULL, 0 }, {0, 0, 0, 0} }; @@ -409,6 +410,8 @@ void print_help(void) " the QP delta map followed by width*height delta\n" " 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" " --(no-)erp-aqp : Use adaptive QP for 360 degree video with\n" " equirectangular projection. [disabled]\n" " --level : Use the given HEVC level in the output and give\n" diff --git a/src/encoder.c b/src/encoder.c index 5830285c..e8ef68e6 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -347,6 +347,27 @@ 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; diff --git a/src/kvazaar.h b/src/kvazaar.h index 6f9e9107..262be213 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -368,6 +368,10 @@ typedef struct kvz_config /** \brief Minimum QP that uses CABAC for residual cost instead of a fast estimate. */ int8_t fast_residual_cost_limit; + + /** \brief Set QP at CU level keeping pic_init_qp_minus26 in PPS zero */ + int8_t set_qp_in_cu; + } kvz_config; /**