Merge branch 'stats-files'

# Conflicts:
#	src/cfg.c
#	src/cli.c
#	src/kvazaar.h
This commit is contained in:
Joose Sainio 2020-09-16 09:25:00 +03:00
commit 8143ab971c
9 changed files with 92 additions and 9 deletions

View file

@ -107,7 +107,10 @@ Options:
- intra_pred_modes: Intra prediction modes.
--key <string> : Encryption key [16,213,27,56,255,127,242,112,
97,126,197,204,25,59,38,30]
--stats-file-prefix : A prefix used for stats files that include
bits, lambda, distortion, and qp for each ctu.
These are meant for debugging and are not
written unless the prefix is defined.
Video structure:
-q, --qp <integer> : Quantization parameter [22]
-p, --period <integer> : Period of intra pictures [64]

View file

@ -23,7 +23,7 @@ AC_CONFIG_SRCDIR([src/encmain.c])
#
# Here is a somewhat sane guide to lib versioning: http://apr.apache.org/versioning.html
ver_major=6
ver_minor=2
ver_minor=3
ver_release=0
# Prevents configure from adding a lot of defines to the CFLAGS

View file

@ -100,7 +100,12 @@ a list of features separated with a '+'. [off]
\fB\-\-key <string>
Encryption key [16,213,27,56,255,127,242,112,
97,126,197,204,25,59,38,30]
.TP
\fB\-\-stats\-file\-prefix
A prefix used for stats files that include
bits, lambda, distortion, and qp for each ctu.
These are meant for debugging and are not
written unless the prefix is defined.
.SS "Video structure:"
.TP
\fB\-q\fR, \fB\-\-qp <integer>

View file

@ -165,6 +165,7 @@ int kvz_config_init(kvz_config *cfg)
cfg->file_format = KVZ_FORMAT_AUTO;
cfg->stats_file_prefix = NULL;
return 1;
}
@ -1374,6 +1375,9 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value)
}
cfg->file_format = file_format;
}
else if OPT("stats-file-prefix") {
cfg->stats_file_prefix = strdup(value);
}
else {
return 0;
}

View file

@ -150,6 +150,7 @@ static const struct option long_options[] = {
{ "clip-neighbour", no_argument, NULL, 0 },
{ "no-clip-neighbour", no_argument, NULL, 0 },
{ "input-file-format", required_argument, NULL, 0 },
{ "stats-file-prefix", required_argument, NULL, 0 },
{0, 0, 0, 0}
};
@ -433,6 +434,10 @@ void print_help(void)
" - intra_pred_modes: Intra prediction modes.\n"
" --key <string> : Encryption key [16,213,27,56,255,127,242,112,\n"
" 97,126,197,204,25,59,38,30]\n"
" --stats-file-prefix : A prefix used for stats files that include\n"
" bits, lambda, distortion, and qp for each ctu.\n"
" These are meant for debugging and are not\n"
" written unless the prefix is defined.\n"
"\n"
/* Word wrap to this width to stay under 80 characters (including ") *************/
"Video structure:\n"

View file

@ -1064,7 +1064,7 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state)
state->frame->total_bits_coded = state->previous_encoder_state->frame->total_bits_coded;
}
state->frame->total_bits_coded += newpos - curpos;
if(state->encoder_control->cfg.rc_algorithm == KVZ_OBA) {
if(state->encoder_control->cfg.rc_algorithm == KVZ_OBA || state->encoder_control->cfg.stats_file_prefix) {
kvz_update_after_picture(state);
}

View file

@ -64,6 +64,8 @@ typedef struct lcu_stats_t {
//! \brief Lambda value which was used for this LCU
double lambda;
double adjust_lambda;
//! \brief Rate control alpha parameter
double rc_alpha;
@ -73,6 +75,7 @@ typedef struct lcu_stats_t {
int i_cost;
int8_t qp;
int8_t adjust_qp;
uint8_t skipped;
} lcu_stats_t;

View file

@ -448,6 +448,8 @@ typedef struct kvz_config
uint8_t clip_neighbour;
enum kvz_file_format file_format;
char *stats_file_prefix;
} kvz_config;
/**

View file

@ -35,6 +35,11 @@ static const double MAX_LAMBDA = 10000;
static kvz_rc_data *data;
static FILE *dist_file;
static FILE *bits_file;
static FILE *qp_file;
static FILE *lambda_file;
/**
* \brief Clip lambda value to a valid range.
*/
@ -87,6 +92,17 @@ kvz_rc_data * kvz_get_rc_data(const encoder_control_t * const encoder) {
data->intra_alpha = 6.7542000000000000;
data->intra_beta = 1.7860000000000000;
if(encoder->cfg.stats_file_prefix) {
char buff[128];
sprintf(buff, "%sbits.txt", encoder->cfg.stats_file_prefix);
bits_file = fopen(buff, "w");
sprintf(buff, "%sdist.txt", encoder->cfg.stats_file_prefix);
dist_file = fopen(buff, "w");
sprintf(buff, "%sqp.txt", encoder->cfg.stats_file_prefix);
qp_file = fopen(buff, "w");
sprintf(buff, "%slambda.txt", encoder->cfg.stats_file_prefix);
lambda_file = fopen(buff, "w");
}
return data;
}
@ -791,6 +807,8 @@ static double qp_to_lambda(encoder_state_t* const state, int qp)
state->lambda = qp_to_lambda(state, state->qp);
state->lambda_sqrt = sqrt(state->lambda);
ctu->adjust_lambda = state->lambda;
ctu->adjust_qp = state->qp;
//ctu->qp = state->qp;
//ctu->lambda = state->lambda;
}
@ -854,6 +872,22 @@ static void update_ck(encoder_state_t * const state, int ctu_index, int layer)
}
static int calc_poc(encoder_state_t * const state) {
const encoder_control_t * const encoder = state->encoder_control;
if((encoder->cfg.open_gop && !encoder->cfg.gop_lowdelay) || !encoder->cfg.intra_period) {
return state->frame->poc;
}
if(!encoder->cfg.gop_len || encoder->cfg.open_gop || encoder->cfg.intra_period == 1 || encoder->cfg.gop_lowdelay) {
return state->frame->poc + state->frame->num / encoder->cfg.intra_period * encoder->cfg.intra_period;
}
if (!encoder->cfg.gop_lowdelay && !encoder->cfg.open_gop) {
return state->frame->poc + state->frame->num / (encoder->cfg.intra_period + 1) * (encoder->cfg.intra_period + 1);
}
assert(0);
return -1;
}
void kvz_update_after_picture(encoder_state_t * const state) {
double total_distortion = 0;
double lambda = 0;
@ -875,6 +909,14 @@ void kvz_update_after_picture(encoder_state_t * const state) {
pthread_mutex_unlock(&state->frame->new_ratecontrol->intra_lock);
}
if (encoder->cfg.stats_file_prefix) {
int poc = calc_poc(state);
fprintf(dist_file, "%d %d %d\n", poc, encoder->in.width_in_lcu, encoder->in.height_in_lcu);
fprintf(bits_file, "%d %d %d\n", poc, encoder->in.width_in_lcu, encoder->in.height_in_lcu);
fprintf(qp_file, "%d %d %d\n", poc, encoder->in.width_in_lcu, encoder->in.height_in_lcu);
fprintf(lambda_file, "%d %d %d\n", poc, encoder->in.width_in_lcu, encoder->in.height_in_lcu);
}
for(int y_ctu = 0; y_ctu < state->encoder_control->in.height_in_lcu; y_ctu++) {
for (int x_ctu = 0; x_ctu < state->encoder_control->in.width_in_lcu; x_ctu++) {
int ctu_distortion = 0;
@ -889,9 +931,23 @@ void kvz_update_after_picture(encoder_state_t * const state) {
ctu->distortion = (double)ctu_distortion / ctu->pixels;
total_distortion += (double)ctu_distortion / ctu->pixels;
lambda += ctu->lambda / (state->encoder_control->in.width_in_lcu * state->encoder_control->in.height_in_lcu);
}
if(encoder->cfg.stats_file_prefix) {
fprintf(dist_file, "%f ", ctu->distortion);
fprintf(bits_file, "%d ", ctu->bits);
fprintf(qp_file, "%d ", ctu->adjust_qp ? ctu->adjust_qp : ctu->qp);
fprintf(lambda_file, "%f ", ctu->adjust_lambda ? ctu->adjust_lambda : ctu->lambda);
}
}
if (encoder->cfg.stats_file_prefix) {
fprintf(dist_file, "\n");
fprintf(bits_file, "\n");
fprintf(qp_file, "\n");
fprintf(lambda_file, "\n");
}
}
if(encoder->cfg.stats_file_prefix && encoder->cfg.rc_algorithm != KVZ_OBA) return;
total_distortion /= (state->encoder_control->in.height_in_lcu * state->encoder_control->in.width_in_lcu);
if (state->frame->is_irap) {
pthread_mutex_lock(&state->frame->new_ratecontrol->intra_lock);
@ -1014,6 +1070,7 @@ void kvz_set_lcu_lambda_and_qp(encoder_state_t * const state,
vector2d_t pos)
{
const encoder_control_t * const ctrl = state->encoder_control;
lcu_stats_t *lcu = kvz_get_lcu_stats(state, pos.x, pos.y);
if (ctrl->cfg.roi.dqps != NULL) {
vector2d_t lcu = {
@ -1032,7 +1089,6 @@ void kvz_set_lcu_lambda_and_qp(encoder_state_t * const state,
}
else if (ctrl->cfg.target_bitrate > 0) {
lcu_stats_t *lcu = kvz_get_lcu_stats(state, pos.x, pos.y);
const uint32_t pixels = MIN(LCU_WIDTH, state->tile->frame->width - LCU_WIDTH * pos.x) *
MIN(LCU_WIDTH, state->tile->frame->height - LCU_WIDTH * pos.y);
@ -1065,7 +1121,6 @@ void kvz_set_lcu_lambda_and_qp(encoder_state_t * const state,
lambda);
lambda = clip_lambda(lambda);
lcu->lambda = lambda;
state->lambda = lambda;
state->lambda_sqrt = sqrt(lambda);
state->qp = lambda_to_qp(lambda);
@ -1076,13 +1131,16 @@ void kvz_set_lcu_lambda_and_qp(encoder_state_t * const state,
state->lambda_sqrt = sqrt(state->frame->lambda);
}
lcu->lambda = state->lambda;
lcu->qp = state->qp;
// Apply variance adaptive quantization
if (ctrl->cfg.vaq) {
vector2d_t lcu = {
vector2d_t lcu_pos = {
pos.x + state->tile->lcu_offset_x,
pos.y + state->tile->lcu_offset_y
};
int id = lcu.x + lcu.y * state->tile->frame->width_in_lcu;
int id = lcu_pos.x + lcu_pos.y * state->tile->frame->width_in_lcu;
int aq_offset = round(state->frame->aq_offsets[id]);
state->qp += aq_offset;
// Maximum delta QP is clipped between [-26, 25] according to ITU T-REC-H.265 specification chapter 7.4.9.10 Transform unit semantics
@ -1091,5 +1149,8 @@ void kvz_set_lcu_lambda_and_qp(encoder_state_t * const state,
state->qp = CLIP_TO_QP(state->qp);
state->lambda = qp_to_lambda(state, state->qp);
state->lambda_sqrt = sqrt(state->lambda);
lcu->adjust_lambda = state->lambda;
lcu->adjust_qp = state->qp;
}
}