Add support for PSNR calculation based on stream bit-depth
This patch adds support to compute PSNR based on stream bit-depth when input bit-depth is lower than stream bit-depth.
Based on a similar change for AV1 (libaom): https://aomedia-review.googlesource.com/c/aom/+/116721
However, unlike AV1, we change the default to use stream bitdepth.
STATS_CHANGED possibly for rare cases.
For issue #344
diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h
index 87e539c..36a1087 100644
--- a/aom/aom_encoder.h
+++ b/aom/aom_encoder.h
@@ -64,6 +64,8 @@
* The available flags are specified by AOM_CODEC_USE_* defines.
*/
#define AOM_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
+/*!\brief Use stream PSNR instead of input PSNR. */
+#define AOM_CODEC_USE_STREAM_PSNR 0x20000
/*!\brief Print per frame stats. */
#define AOM_CODEC_USE_PER_FRAME_STATS 0x80000 /**< Enable printing of stats */
@@ -132,8 +134,17 @@
unsigned int samples[4]; /**< Number of samples, total/y/u/v */
uint64_t sse[4]; /**< sum squared error, total/y/u/v */
double psnr[4]; /**< PSNR, total/y/u/v */
- } psnr; /**< data for PSNR packet */
- aom_fixed_buf_t raw; /**< data for arbitrary packets */
+ /*!\brief Number of samples, total/y/u/v when
+ * input bit-depth < stream bit-depth.*/
+ unsigned int samples_hbd[4];
+ /*!\brief sum squared error, total/y/u/v when
+ * input bit-depth < stream bit-depth.*/
+ uint64_t sse_hbd[4];
+ /*!\brief PSNR, total/y/u/v when
+ * input bit-depth < stream bit-depth.*/
+ double psnr_hbd[4];
+ } psnr; /**< data for PSNR packet */
+ aom_fixed_buf_t raw; /**< data for arbitrary packets */
/* This packet size is fixed to allow codecs to extend this
* interface without having to manage storage for raw packets,
diff --git a/aom_dsp/psnr.c b/aom_dsp/psnr.c
index c2d144d..d651d01 100644
--- a/aom_dsp/psnr.c
+++ b/aom_dsp/psnr.c
@@ -222,9 +222,9 @@
uint64_t total_sse = 0;
uint32_t total_samples = 0;
#if CONFIG_AV2CTC_PSNR_PEAK
- const double peak = (double)(255 << (in_bit_depth - 8));
+ double peak = (double)(255 << (in_bit_depth - 8));
#else
- const double peak = (double)((1 << in_bit_depth) - 1);
+ double peak = (double)((1 << in_bit_depth) - 1);
#endif // CONFIG_AV2CTC_PSNR_PEAK
const unsigned int input_shift = bit_depth - in_bit_depth;
@@ -253,4 +253,33 @@
psnr->samples[0] = total_samples;
psnr->psnr[0] =
aom_sse_to_psnr((double)total_samples, peak, (double)total_sse);
+
+ // Compute PSNR based on stream bit depth
+ if (in_bit_depth < bit_depth) {
+#if CONFIG_AV2CTC_PSNR_PEAK
+ peak = (double)(255 << (bit_depth - 8));
+#else
+ peak = (double)((1 << bit_depth) - 1);
+#endif // CONFIG_AV2CTC_PSNR_PEAK
+ total_sse = 0;
+ total_samples = 0;
+ for (i = 0; i < 3; ++i) {
+ const int w = widths[i];
+ const int h = heights[i];
+ const uint32_t samples = w * h;
+ uint64_t sse;
+ sse = highbd_get_sse(a->buffers[i], a_strides[i], b->buffers[i],
+ b_strides[i], w, h);
+ psnr->sse_hbd[1 + i] = sse;
+ psnr->samples_hbd[1 + i] = samples;
+ psnr->psnr_hbd[1 + i] = aom_sse_to_psnr(samples, peak, (double)sse);
+ total_sse += sse;
+ total_samples += samples;
+ }
+
+ psnr->sse_hbd[0] = total_sse;
+ psnr->samples_hbd[0] = total_samples;
+ psnr->psnr_hbd[0] =
+ aom_sse_to_psnr((double)total_samples, peak, (double)total_sse);
+ }
}
diff --git a/aom_dsp/psnr.h b/aom_dsp/psnr.h
index 67f89ba..0b8d9d8 100644
--- a/aom_dsp/psnr.h
+++ b/aom_dsp/psnr.h
@@ -22,9 +22,12 @@
#endif
typedef struct {
- double psnr[4]; // total/y/u/v
- uint64_t sse[4]; // total/y/u/v
- uint32_t samples[4]; // total/y/u/v
+ double psnr[4]; // total/y/u/v
+ uint64_t sse[4]; // total/y/u/v
+ uint32_t samples[4]; // total/y/u/v
+ double psnr_hbd[4]; // total/y/u/v when input-bit-depth < bit-depth
+ uint64_t sse_hbd[4]; // total/y/u/v when input-bit-depth < bit-depth
+ uint32_t samples_hbd[4]; // total/y/u/v when input-bit-depth < bit-depth
} PSNR_STATS;
/*!\brief Converts SSE to PSNR
diff --git a/apps/aomenc.c b/apps/aomenc.c
index a86f6c8..a9f74b8 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -586,10 +586,10 @@
FILE *file;
struct rate_hist *rate_hist;
struct WebmOutputContext webm_ctx;
- uint64_t psnr_sse_total;
- uint64_t psnr_samples_total;
- double psnr_totals[4];
- int psnr_count;
+ uint64_t psnr_sse_total[2];
+ uint64_t psnr_samples_total[2];
+ double psnr_totals[2][4];
+ int psnr_count[2];
int counts[QINDEX_RANGE];
aom_codec_ctx_t encoder;
unsigned int frames_out;
@@ -751,6 +751,7 @@
global->passes = 1;
global->color_type = I420;
global->csp = AOM_CSP_UNKNOWN;
+ global->show_psnr = 0;
global->step_frames = 1;
int cfg_included = 0;
@@ -810,7 +811,10 @@
die("--step must be positive");
}
} else if (arg_match(&arg, &g_av1_codec_arg_defs.psnrarg, argi)) {
- global->show_psnr = 1;
+ if (arg.val)
+ global->show_psnr = arg_parse_int(&arg);
+ else
+ global->show_psnr = 2;
} else if (arg_match(&arg, &g_av1_codec_arg_defs.recontest, argi)) {
global->test_decode = arg_parse_enum_or_int(&arg);
} else if (arg_match(&arg, &g_av1_codec_arg_defs.framerate, argi)) {
@@ -1738,7 +1742,8 @@
int i;
int flags = 0;
- flags |= global->show_psnr ? AOM_CODEC_USE_PSNR : 0;
+ flags |= (global->show_psnr >= 1) ? AOM_CODEC_USE_PSNR : 0;
+ flags |= (global->show_psnr == 2) ? AOM_CODEC_USE_STREAM_PSNR : 0;
flags |= global->quiet ? 0 : AOM_CODEC_USE_PER_FRAME_STATS;
/* Construct Encoder Context */
@@ -1989,15 +1994,25 @@
break;
case AOM_CODEC_PSNR_PKT:
- if (global->show_psnr) {
+ if (global->show_psnr >= 1) {
int i;
- stream->psnr_sse_total += pkt->data.psnr.sse[0];
- stream->psnr_samples_total += pkt->data.psnr.samples[0];
+ stream->psnr_sse_total[0] += pkt->data.psnr.sse[0];
+ stream->psnr_samples_total[0] += pkt->data.psnr.samples[0];
for (i = 0; i < 4; i++) {
- stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
+ stream->psnr_totals[0][i] += pkt->data.psnr.psnr[i];
}
- stream->psnr_count++;
+ stream->psnr_count[0]++;
+
+ if (stream->config.cfg.g_input_bit_depth <
+ stream->config.cfg.g_bit_depth) {
+ stream->psnr_sse_total[1] += pkt->data.psnr.sse_hbd[0];
+ stream->psnr_samples_total[1] += pkt->data.psnr.samples_hbd[0];
+ for (i = 0; i < 4; i++) {
+ stream->psnr_totals[1][i] += pkt->data.psnr.psnr_hbd[i];
+ }
+ stream->psnr_count[1]++;
+ }
}
break;
@@ -2284,6 +2299,20 @@
"match input format.\n",
stream->config.cfg.g_profile);
}
+ if ((global.show_psnr == 2) && (stream->config.cfg.g_input_bit_depth ==
+ stream->config.cfg.g_bit_depth)) {
+ fprintf(stderr,
+ "Warning: --psnr==2 and --psnr==1 will provide same "
+ "results when input bit-depth == stream bit-depth, "
+ "falling back to default psnr value\n");
+ global.show_psnr = 1;
+ }
+ if (global.show_psnr < 0 || global.show_psnr > 2) {
+ fprintf(stderr,
+ "Warning: --psnr can take only 0,1,2 as values,"
+ "falling back to default psnr value\n");
+ global.show_psnr = 1;
+ }
/* Set limit */
stream->config.cfg.g_limit = global.limit;
}
@@ -2457,17 +2486,23 @@
const double kbps = (bpf * (double)global.framerate.num /
(double)global.framerate.den) /
1000.0;
+ if (global.show_psnr >= 1) {
+ const int psnr_bit_depth = (global.show_psnr == 1)
+ ? stream->config.cfg.g_input_bit_depth
+ : stream->config.cfg.g_bit_depth;
+ const int psnr_idx = (global.show_psnr == 1) ? 0 : 1;
#if CONFIG_AV2CTC_PSNR_PEAK
- const double peak = (255 << (stream->config.cfg.g_input_bit_depth - 8));
+ const double peak = (255 << (psnr_bit_depth - 8));
#else
- const double peak = (1 << stream->config.cfg.g_input_bit_depth) - 1;
+ const double peak = (1 << psnr_bit_depth) - 1;
#endif // CONFIG_AV2CTC_PSNR_PEAK
- const double ovpsnr = sse_to_psnr((double)stream->psnr_samples_total,
- peak, (double)stream->psnr_sse_total);
- double psnr[4] = { 0.0 };
- if (global.show_psnr) {
+ const double ovpsnr =
+ sse_to_psnr((double)stream->psnr_samples_total[psnr_idx], peak,
+ (double)stream->psnr_sse_total[psnr_idx]);
+ double psnr[4] = { 0.0 };
for (int i = 0; i < 4; i++) {
- psnr[i] = stream->psnr_totals[i] / stream->psnr_count;
+ psnr[i] =
+ stream->psnr_totals[psnr_idx][i] / stream->psnr_count[psnr_idx];
}
fprintf(stdout,
"\n Bitrate(kbps) | PSNR(Y) | PSNR(U) "
diff --git a/av1/arg_defs.c b/av1/arg_defs.c
index 11dc2fd..1d69249 100644
--- a/av1/arg_defs.c
+++ b/av1/arg_defs.c
@@ -165,7 +165,12 @@
.good_dl = ARG_DEF(NULL, "good", 0, "Use Good Quality Deadline"),
.quietarg = ARG_DEF("q", "quiet", 0, "Do not print encode progress"),
.verbosearg = ARG_DEF("v", "verbose", 0, "Show encoder parameters"),
- .psnrarg = ARG_DEF(NULL, "psnr", 0, "Show PSNR in status line"),
+ .psnrarg = ARG_DEF(
+ NULL, "psnr", -1,
+ "Show PSNR in status line"
+ "(0: Disable PSNR status line display, 1: PSNR calculated using input "
+ "bit-depth, 2: PSNR calculated using stream bit-depth (default)), "
+ "takes default option when arguments are not specified"),
.use_cfg = ARG_DEF("c", "cfg", 1, "Config file to use"),
.recontest = ARG_DEF_ENUM(NULL, "test-decode", 1,
"Test encode/decode mismatch", test_decode_enum),
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 58f087b..68cf339 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -2868,17 +2868,10 @@
}
static void calculate_psnr(AV1_COMP *cpi, PSNR_STATS *psnr) {
- int i;
- PSNR_STATS stats;
-
const uint32_t in_bit_depth = cpi->oxcf.input_cfg.input_bit_depth;
const uint32_t bit_depth = cpi->td.mb.e_mbd.bd;
aom_calc_highbd_psnr(cpi->unfiltered_source, &cpi->common.cur_frame->buf,
- &stats, bit_depth, in_bit_depth);
-
- for (i = 0; i < 4; ++i) {
- psnr->psnr[i] = stats.psnr[i];
- }
+ psnr, bit_depth, in_bit_depth);
}
static void report_stats(AV1_COMP *cpi, size_t frame_size, uint64_t cx_time) {
@@ -2892,9 +2885,10 @@
for (int i = 0; i < 4; ++i) {
psnr.psnr[i] = 0;
+ psnr.psnr_hbd[i] = 0;
}
- if (cpi->b_calculate_psnr) {
+ if (cpi->b_calculate_psnr >= 1) {
calculate_psnr(cpi, &psnr);
}
@@ -2909,7 +2903,8 @@
? -1
: ref_poc[ref_idx];
}
- if (cpi->b_calculate_psnr) {
+ if (cpi->b_calculate_psnr >= 1) {
+ const bool use_hbd_psnr = (cpi->b_calculate_psnr == 2);
fprintf(stdout,
"POC:%6d [%s][Level:%d][Q:%3d]: %10" PRIu64
" Bytes, "
@@ -2919,8 +2914,10 @@
cm->cur_frame->absolute_poc,
frameType[cm->current_frame.frame_type],
cm->cur_frame->pyramid_level, base_qindex, (uint64_t)frame_size,
- cx_time / 1000.0, psnr.psnr[1], psnr.psnr[2], psnr.psnr[3],
- psnr.psnr[0]);
+ cx_time / 1000.0, use_hbd_psnr ? psnr.psnr_hbd[1] : psnr.psnr[1],
+ use_hbd_psnr ? psnr.psnr_hbd[2] : psnr.psnr[2],
+ use_hbd_psnr ? psnr.psnr_hbd[3] : psnr.psnr[3],
+ use_hbd_psnr ? psnr.psnr_hbd[0] : psnr.psnr[0]);
} else {
fprintf(stdout,
"POC:%6d [%s][Level:%d][Q:%3d]: %10" PRIu64
@@ -3036,6 +3033,9 @@
if (ctx->base.init_flags & AOM_CODEC_USE_PSNR) {
cpi->b_calculate_psnr = 1;
}
+ if (ctx->base.init_flags & AOM_CODEC_USE_STREAM_PSNR) {
+ cpi->b_calculate_psnr = 2;
+ }
if (ctx->base.init_flags & AOM_CODEC_USE_PER_FRAME_STATS) {
cpi->print_per_frame_stats = 1;
}
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 3898040..f98c287 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1102,18 +1102,22 @@
cpi->b_calculate_blockiness = 1;
cpi->b_calculate_consistency = 1;
cpi->total_inconsistency = 0;
- cpi->psnr.worst = 100.0;
+ cpi->psnr[0].worst = 100.0;
+ cpi->psnr[1].worst = 100.0;
cpi->worst_ssim = 100.0;
- cpi->count = 0;
+ cpi->count[0] = 0;
+ cpi->count[1] = 0;
cpi->bytes = 0;
#if CONFIG_SPEED_STATS
cpi->tx_search_count = 0;
#endif // CONFIG_SPEED_STATS
if (cpi->b_calculate_psnr) {
- cpi->total_sq_error = 0;
- cpi->total_samples = 0;
+ cpi->total_sq_error[0] = 0;
+ cpi->total_samples[0] = 0;
+ cpi->total_sq_error[1] = 0;
+ cpi->total_samples[1] = 0;
cpi->tot_recode_hits = 0;
cpi->summed_quality = 0;
cpi->summed_weights = 0;
@@ -1353,8 +1357,9 @@
const double rate_err = ((100.0 * (dr - target_rate)) / target_rate);
if (cpi->b_calculate_psnr) {
- const double total_psnr = aom_sse_to_psnr(
- (double)cpi->total_samples, peak, (double)cpi->total_sq_error);
+ const double total_psnr =
+ aom_sse_to_psnr((double)cpi->total_samples[0], peak,
+ (double)cpi->total_sq_error[0]);
const double total_ssim =
100 * pow(cpi->summed_quality / cpi->summed_weights, 8.0);
snprintf(headings, sizeof(headings),
@@ -1367,24 +1372,25 @@
"%7.3f\t%7.3f\t%7.3f\t%7.3f\t"
"%7.3f\t%7.3f\t%7.3f\t%7.3f\t"
"%7.3f\t%7.3f\t%7.3f",
- dr, cpi->psnr.stat[STAT_ALL] / cpi->count, total_psnr,
- cpi->psnr.stat[STAT_ALL] / cpi->count, total_psnr, total_ssim,
- total_ssim, cpi->fastssim.stat[STAT_ALL] / cpi->count,
- cpi->psnrhvs.stat[STAT_ALL] / cpi->count, cpi->psnr.worst,
- cpi->worst_ssim, cpi->fastssim.worst, cpi->psnrhvs.worst,
- cpi->psnr.stat[STAT_Y] / cpi->count,
- cpi->psnr.stat[STAT_U] / cpi->count,
- cpi->psnr.stat[STAT_V] / cpi->count);
+ dr, cpi->psnr[0].stat[STAT_ALL] / cpi->count[0], total_psnr,
+ cpi->psnr[0].stat[STAT_ALL] / cpi->count[0], total_psnr,
+ total_ssim, total_ssim,
+ cpi->fastssim.stat[STAT_ALL] / cpi->count[0],
+ cpi->psnrhvs.stat[STAT_ALL] / cpi->count[0],
+ cpi->psnr[0].worst, cpi->worst_ssim, cpi->fastssim.worst,
+ cpi->psnrhvs.worst, cpi->psnr[0].stat[STAT_Y] / cpi->count[0],
+ cpi->psnr[0].stat[STAT_U] / cpi->count[0],
+ cpi->psnr[0].stat[STAT_V] / cpi->count[0]);
if (cpi->b_calculate_blockiness) {
SNPRINT(headings, "\t Block\tWstBlck");
- SNPRINT2(results, "\t%7.3f", cpi->total_blockiness / cpi->count);
+ SNPRINT2(results, "\t%7.3f", cpi->total_blockiness / cpi->count[0]);
SNPRINT2(results, "\t%7.3f", cpi->worst_blockiness);
}
if (cpi->b_calculate_consistency) {
double consistency =
- aom_sse_to_psnr((double)cpi->total_samples, peak,
+ aom_sse_to_psnr((double)cpi->total_samples[0], peak,
(double)cpi->total_inconsistency);
SNPRINT(headings, "\tConsist\tWstCons");
@@ -1392,16 +1398,43 @@
SNPRINT2(results, "\t%7.3f", cpi->worst_consistency);
}
- SNPRINT(headings, "\t Time\tRcErr\tAbsErr");
+ SNPRINT(headings, "\t Time\tRcErr\tAbsErr");
SNPRINT2(results, "\t%8.0f", total_encode_time);
- SNPRINT2(results, "\t%7.2f", rate_err);
- SNPRINT2(results, "\t%7.2f", fabs(rate_err));
+ SNPRINT2(results, " %7.2f", rate_err);
+ SNPRINT2(results, " %7.2f", fabs(rate_err));
- fprintf(f, "%s\tAPsnr611\n", headings);
- fprintf(f, "%s\t%7.3f\n", results,
- (6 * cpi->psnr.stat[STAT_Y] + cpi->psnr.stat[STAT_U] +
- cpi->psnr.stat[STAT_V]) /
- (cpi->count * 8));
+ SNPRINT(headings, "\tAPsnr611");
+ SNPRINT2(results, " %7.3f",
+ (6 * cpi->psnr[0].stat[STAT_Y] + cpi->psnr[0].stat[STAT_U] +
+ cpi->psnr[0].stat[STAT_V]) /
+ (cpi->count[0] * 8));
+
+ const uint32_t in_bit_depth = cpi->oxcf.input_cfg.input_bit_depth;
+ const uint32_t bit_depth = cpi->td.mb.e_mbd.bd;
+ if (in_bit_depth < bit_depth) {
+ const double peak_hbd = (double)((1 << bit_depth) - 1);
+ const double total_psnr_hbd =
+ aom_sse_to_psnr((double)cpi->total_samples[1], peak_hbd,
+ (double)cpi->total_sq_error[1]);
+ SNPRINT(headings,
+ "\t AVGPsnrH GLBPsnrH AVPsnrPH GLPsnrPH"
+ " AVPsnrYH APsnrCbH APsnrCrH WstPsnrH");
+ SNPRINT2(results, "\t%7.3f",
+ cpi->psnr[1].stat[STAT_ALL] / cpi->count[1]);
+ SNPRINT2(results, " %7.3f", total_psnr_hbd);
+ SNPRINT2(results, " %7.3f",
+ cpi->psnr[1].stat[STAT_ALL] / cpi->count[1]);
+ SNPRINT2(results, " %7.3f", total_psnr_hbd);
+ SNPRINT2(results, " %7.3f",
+ cpi->psnr[1].stat[STAT_Y] / cpi->count[1]);
+ SNPRINT2(results, " %7.3f",
+ cpi->psnr[1].stat[STAT_U] / cpi->count[1]);
+ SNPRINT2(results, " %7.3f",
+ cpi->psnr[1].stat[STAT_V] / cpi->count[1]);
+ SNPRINT2(results, " %7.3f", cpi->psnr[1].worst);
+ }
+ fprintf(f, "%s\n", headings);
+ fprintf(f, "%s\n", results);
}
fclose(f);
@@ -1502,6 +1535,15 @@
pkt.data.psnr.sse[i] = psnr.sse[i];
pkt.data.psnr.psnr[i] = psnr.psnr[i];
}
+
+ if (in_bit_depth < bit_depth) {
+ for (i = 0; i < 4; ++i) {
+ pkt.data.psnr.samples_hbd[i] = psnr.samples_hbd[i];
+ pkt.data.psnr.sse_hbd[i] = psnr.sse_hbd[i];
+ pkt.data.psnr.psnr_hbd[i] = psnr.psnr_hbd[i];
+ }
+ }
+
pkt.kind = AOM_CODEC_PSNR_PKT;
aom_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
}
@@ -4245,16 +4287,17 @@
const YV12_BUFFER_CONFIG *recon = &cpi->common.cur_frame->buf;
double y, u, v, frame_all;
- cpi->count++;
+ cpi->count[0]++;
+ cpi->count[1]++;
if (cpi->b_calculate_psnr) {
PSNR_STATS psnr;
double frame_ssim2 = 0.0, weight = 0.0;
aom_clear_system_state();
aom_calc_highbd_psnr(orig, recon, &psnr, bit_depth, in_bit_depth);
adjust_image_stat(psnr.psnr[1], psnr.psnr[2], psnr.psnr[3], psnr.psnr[0],
- &cpi->psnr);
- cpi->total_sq_error += psnr.sse[0];
- cpi->total_samples += psnr.samples[0];
+ &(cpi->psnr[0]));
+ cpi->total_sq_error[0] += psnr.sse[0];
+ cpi->total_samples[0] += psnr.samples[0];
frame_ssim2 =
aom_highbd_calc_ssim(orig, recon, &weight, bit_depth, in_bit_depth);
@@ -4262,6 +4305,14 @@
cpi->summed_quality += frame_ssim2 * weight;
cpi->summed_weights += weight;
+ // Compute PSNR based on stream bit depth
+ if (in_bit_depth < bit_depth) {
+ adjust_image_stat(psnr.psnr_hbd[1], psnr.psnr_hbd[2], psnr.psnr_hbd[3],
+ psnr.psnr_hbd[0], &cpi->psnr[1]);
+ cpi->total_sq_error[1] += psnr.sse_hbd[0];
+ cpi->total_samples[1] += psnr.samples_hbd[0];
+ }
+
#if 0
{
FILE *f = fopen("q_used.stt", "a");
@@ -4343,7 +4394,7 @@
(*size > 0 && !is_stat_generation_stage(cpi) && cm->show_frame)) {
#else
// Note *size = 0 indicates a dropeed frame for which psnr is not calculated
- if (cpi->b_calculate_psnr && *size > 0) {
+ if (cpi->b_calculate_psnr >= 1 && *size > 0) {
if (cm->show_existing_frame ||
(!is_stat_generation_stage(cpi) && cm->show_frame)) {
#endif // CONFIG_OUTPUT_FRAME_BASED_ON_ORDER_HINT
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index a195c9d..0a9ac05 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -2779,10 +2779,10 @@
uint64_t time_receive_data;
uint64_t time_compress_data;
- int count;
- uint64_t total_sq_error;
- uint64_t total_samples;
- ImageStat psnr;
+ int count[2];
+ uint64_t total_sq_error[2];
+ uint64_t total_samples[2];
+ ImageStat psnr[2];
double total_blockiness;
double worst_blockiness;
@@ -2807,7 +2807,8 @@
#endif
/*!
- * Calculates PSNR on each frame when set to 1.
+ * Calculates PSNR on each frame when set to 1 or 2.
+ * Uses stream PSNR when set to 2.
*/
int b_calculate_psnr;
@@ -3626,7 +3627,7 @@
static AOM_INLINE int is_psnr_calc_enabled(const AV1_COMP *cpi) {
const AV1_COMMON *const cm = &cpi->common;
- return cpi->b_calculate_psnr && !is_stat_generation_stage(cpi) &&
+ return cpi->b_calculate_psnr >= 1 && !is_stat_generation_stage(cpi) &&
cm->show_frame;
}
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c
index ee501a0..aef304e 100644
--- a/av1/encoder/encoder_utils.c
+++ b/av1/encoder/encoder_utils.c
@@ -897,7 +897,10 @@
if (pass != 1) return;
- const double psnr_diff = psnr[1].psnr[0] - psnr[0].psnr[0];
+ const bool use_hbd_psnr = (cpi->b_calculate_psnr == 2);
+ const double psnr_diff = use_hbd_psnr
+ ? psnr[1].psnr_hbd[0] - psnr[0].psnr_hbd[0]
+ : psnr[1].psnr[0] - psnr[0].psnr[0];
#if CONFIG_SCC_DETERMINATION
// Calculate % of palette mode to be chosen in a frame from mode decision.
const double palette_ratio =