diff --git a/src/cfg.c b/src/cfg.c index 3f9b1fe1..1ca30b60 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -29,6 +29,8 @@ #include +static void parse_qp_map(kvz_config* cfg, int index); + kvz_config *kvz_config_alloc(void) { return calloc(1, sizeof(kvz_config)); @@ -184,15 +186,16 @@ int kvz_config_init(kvz_config *cfg) int8_t in[] = { 17, 27, 32, 44 }; int8_t out[] = { 17, 29, 34, 41 }; - cfg->num_used_table = 1; - cfg->qp_table_length_minus1[0] = 2; - cfg->qp_table_start_minus26[0] = 17 - 26; - cfg->delta_qp_in_val_minus1[0] = malloc(cfg->qp_table_length_minus1[0] + 1); - cfg->delta_qp_out_val[0] = malloc(cfg->qp_table_length_minus1[0] + 1); - for (int i = 0; i < cfg->qp_table_length_minus1[0] + 1; i++) { - cfg->delta_qp_in_val_minus1[0][i] = in[i + 1] - in[i] - (int8_t)1; - cfg->delta_qp_out_val[0][i] = out[i + 1] - out[i]; - } + cfg->chroma_scale_out[0][0] = cfg->chroma_scale_in[0][0] = 17; + cfg->chroma_scale_out[0][1] = cfg->chroma_scale_in[0][1] = 27; + cfg->chroma_scale_out[0][2] = cfg->chroma_scale_in[0][2] = 32; + cfg->chroma_scale_out[0][3] = cfg->chroma_scale_in[0][3] = 44; + cfg->chroma_scale_out[0][4] = cfg->chroma_scale_in[0][4] = -1; + cfg->chroma_scale_out[1][0] = cfg->chroma_scale_in[1][0] = -1; + cfg->chroma_scale_out[2][0] = cfg->chroma_scale_in[2][0] = -1; + + + parse_qp_map(cfg, 0); return 1; } @@ -212,10 +215,6 @@ int kvz_config_destroy(kvz_config *cfg) { FREE_POINTER(cfg->param_set_map); } - for (int i = 0; i < cfg->num_used_table; i++) { - if (cfg->delta_qp_in_val_minus1[i]) FREE_POINTER(cfg->delta_qp_in_val_minus1[i]); - if (cfg->delta_qp_out_val[i]) FREE_POINTER(cfg->delta_qp_out_val[i]); - } } free(cfg); @@ -328,6 +327,22 @@ static int parse_uint8(const char *numstr,uint8_t* number,int min, int max) } } +static int parse_int8(const char *numstr,int8_t* number,int min, int max) +{ + char *tail; + int d = strtol(numstr, &tail, 10); + if (*tail || d < min || d > max){ + fprintf(stderr, "Expected number between %d and %d\n", min, max); + if(number) + *number = 0; + return 0; + } else{ + if (number) + *number = (int8_t) d; + return 1; + } +} + static int parse_array(const char *array, uint8_t *coeff_key, int size, int min, int max) { @@ -360,6 +375,52 @@ static int parse_array(const char *array, uint8_t *coeff_key, int size, return 1; } +static int parse_qp_scale_array(const char *array, int8_t *out) +{ + const int size = 16; + char *key = strdup(array); + const char delim[] = ",;:"; + char *token; + int i = 0; + + token = strtok(key, delim); + while(token!=NULL&&i=size){ + fprintf(stderr, "parsing failed : too many members.\n"); + free(key); + return 0; + } + out[i] = -1; + + free(key); + return 1; +} + +static void parse_qp_map(kvz_config *cfg, int index) { + int i = 0; + for (; cfg->chroma_scale_in[index][i] != -1; i++); + if (cfg->chroma_scale_out[index][i] != -1) return; + assert(i < 17); + + // TODO: Move this to somewhere else when we have more than one table + cfg->num_used_table = 1; + cfg->qp_table_length_minus1[index] = i - 2; + cfg->qp_table_start_minus26[index] = cfg->chroma_scale_in[index][0] - 26; + for (i = 0; i < cfg->qp_table_length_minus1[0] + 1; i++) { + cfg->delta_qp_in_val_minus1[index][i] = cfg->chroma_scale_in[index][i + 1] - cfg->chroma_scale_in[index][i] - (int8_t)1; + cfg->delta_qp_out_val[index][i] = cfg->chroma_scale_out[index][i + 1] - cfg->chroma_scale_out[index][i]; + } +} + static int parse_pu_depth_list( const char *array, int32_t *depths_min, int32_t *depths_max, int size ) { char *list = strdup( array ); @@ -1458,6 +1519,18 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value) else if OPT("stats-file-prefix") { cfg->stats_file_prefix = strdup(value); } + else if OPT("chroma-qp-in") { + memset(cfg->chroma_scale_in[0], 0, 17); + const bool success = parse_qp_scale_array(value, cfg->chroma_scale_in[0]); + parse_qp_map(cfg, 0); + return success; + } + else if OPT("chroma-qp-out") { + memset(cfg->chroma_scale_out[0], 0, 17); + const bool success = parse_qp_scale_array(value, cfg->chroma_scale_out[0]); + parse_qp_map(cfg, 0); + return success; + } else { return 0; } @@ -1801,6 +1874,20 @@ int kvz_config_validate(const kvz_config *const cfg) error = 1; } + for (int index = 0; index < 3; index++) { + int i = 0; + if (cfg->chroma_scale_in[index][i] != cfg->chroma_scale_out[index][i]) { + fprintf(stderr, "The starting points of chroma qp scaling list %d do not match. %d != %d", + index, cfg->chroma_scale_in[index][i], cfg->chroma_scale_out[index][i]); + error = 1; + } + for (; cfg->chroma_scale_in[index][i] != -1; i++); + if (cfg->chroma_scale_out[index][i] != -1) { + fprintf(stderr, "The chroma qp scaling lists of index %d are different lengths.\n", index); + error = 1; + } + } + return !error; } diff --git a/src/cli.c b/src/cli.c index caefbd1c..7203ab74 100644 --- a/src/cli.c +++ b/src/cli.c @@ -159,6 +159,8 @@ static const struct option long_options[] = { { "fastrd-sampling", no_argument, NULL, 0 }, { "fastrd-accuracy-check", no_argument, NULL, 0 }, { "fastrd-outdir", required_argument, NULL, 0 }, + { "chroma-qp-in", required_argument, NULL, 0 }, + { "chroma-qp-out", required_argument, NULL, 0 }, {0, 0, 0, 0} }; @@ -512,6 +514,13 @@ void print_help(void) " --(no-)vaq : Enable variance adaptive quantization with given\n" " strength, in range 1..20. Recommended: 5.\n" " [disabled]\n" + " --chroma-qp-in : List of input values used for mapping the luma\n" + " QP into chroma qp. [17,27,32,44]\n" + " --chroma-qp-out : List of output values used for mapping the luma\n" + " QP into chroma qp. These two lists have to be\n" + " same length, start with same value, and can\n" + " contain maximum 16 or 36 - starting value\n" + " elements. [17,27,32,44]\n" "\n" /* Word wrap to this width to stay under 80 characters (including ") *************/ "Compression tools:\n" diff --git a/src/kvazaar.h b/src/kvazaar.h index 0c8cc966..0b0a10d3 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -494,8 +494,11 @@ typedef struct kvz_config int8_t num_used_table; int8_t qp_table_start_minus26[3]; int8_t qp_table_length_minus1[3]; - int8_t* delta_qp_in_val_minus1[3]; - int8_t* delta_qp_out_val[3]; + int8_t delta_qp_in_val_minus1[3][16]; + int8_t delta_qp_out_val[3][16]; + + int8_t chroma_scale_in[3][17]; + int8_t chroma_scale_out[3][17]; } kvz_config; /**