Commit 14066c2a authored by Yaowu Xu's avatar Yaowu Xu

Refactor internal stats code

Ported from libvpx/nextgenv2: 1a69cb28

Change-Id: Icec13798d8cf2f00b78de16c642dd2aa754ba826
parent bb72d637
......@@ -136,9 +136,10 @@ static void fs_downsample_level(fs_ctx *_ctx, int _l) {
}
}
static void fs_downsample_level0(fs_ctx *_ctx, const unsigned char *_src1,
int _s1ystride, const unsigned char *_src2,
int _s2ystride, int _w, int _h) {
static void fs_downsample_level0(fs_ctx *_ctx, const uint8_t *_src1,
int _s1ystride, const uint8_t *_src2,
int _s2ystride, int _w, int _h,
uint32_t bit_depth) {
uint32_t *dst1;
uint32_t *dst2;
int w;
......@@ -159,44 +160,23 @@ static void fs_downsample_level0(fs_ctx *_ctx, const unsigned char *_src1,
int i1;
i0 = 2 * i;
i1 = FS_MINI(i0 + 1, _w);
dst1[j * w + i] =
_src1[j0 * _s1ystride + i0] + _src1[j0 * _s1ystride + i1] +
_src1[j1 * _s1ystride + i0] + _src1[j1 * _s1ystride + i1];
dst2[j * w + i] =
_src2[j0 * _s2ystride + i0] + _src2[j0 * _s2ystride + i1] +
_src2[j1 * _s2ystride + i0] + _src2[j1 * _s2ystride + i1];
}
}
}
static void hbd_fs_downsample_level0(fs_ctx *_ctx, const uint16_t *_src1,
int _s1ystride, const uint16_t *_src2,
int _s2ystride, int _w, int _h) {
uint32_t *dst1;
uint32_t *dst2;
int w;
int h;
int i;
int j;
w = _ctx->level[0].w;
h = _ctx->level[0].h;
dst1 = _ctx->level[0].im1;
dst2 = _ctx->level[0].im2;
for (j = 0; j < h; j++) {
int j0;
int j1;
j0 = 2 * j;
j1 = FS_MINI(j0 + 1, _h);
for (i = 0; i < w; i++) {
int i0;
int i1;
i0 = 2 * i;
i1 = FS_MINI(i0 + 1, _w);
dst1[j * w + i] =
_src1[j0 * _s1ystride + i0] + _src1[j0 * _s1ystride + i1] +
_src1[j1 * _s1ystride + i0] + _src1[j1 * _s1ystride + i1];
dst2[j * w + i] =
_src2[j0 * _s2ystride + i0] + _src2[j0 * _s2ystride + i1] +
_src2[j1 * _s2ystride + i0] + _src2[j1 * _s2ystride + i1];
if (bit_depth == 8) {
dst1[j * w + i] =
_src1[j0 * _s1ystride + i0] + _src1[j0 * _s1ystride + i1] +
_src1[j1 * _s1ystride + i0] + _src1[j1 * _s1ystride + i1];
dst2[j * w + i] =
_src2[j0 * _s2ystride + i0] + _src2[j0 * _s2ystride + i1] +
_src2[j1 * _s2ystride + i0] + _src2[j1 * _s2ystride + i1];
} else {
uint16_t *src1s = CONVERT_TO_SHORTPTR(_src1);
uint16_t *src2s = CONVERT_TO_SHORTPTR(_src2);
dst1[j * w + i] =
src1s[j0 * _s1ystride + i0] + src1s[j0 * _s1ystride + i1] +
src1s[j1 * _s1ystride + i0] + src1s[j1 * _s1ystride + i1];
dst2[j * w + i] =
src2s[j0 * _s2ystride + i0] + src2s[j0 * _s2ystride + i1] +
src2s[j1 * _s2ystride + i0] + src2s[j1 * _s2ystride + i1];
}
}
}
}
......@@ -461,37 +441,15 @@ static double convert_ssim_db(double _ssim, double _weight) {
return 10 * (log10(_weight) - log10(_weight - _ssim));
}
static double calc_ssim(const unsigned char *_src, int _systride,
const unsigned char *_dst, int _dystride, int _w,
int _h) {
fs_ctx ctx;
double ret;
int l;
ret = 1;
fs_ctx_init(&ctx, _w, _h, FS_NLEVELS);
fs_downsample_level0(&ctx, _src, _systride, _dst, _dystride, _w, _h);
for (l = 0; l < FS_NLEVELS - 1; l++) {
fs_calc_structure(&ctx, l, 8);
ret *= fs_average(&ctx, l);
fs_downsample_level(&ctx, l + 1);
}
fs_calc_structure(&ctx, l, 8);
fs_apply_luminance(&ctx, l, 8);
ret *= fs_average(&ctx, l);
fs_ctx_clear(&ctx);
return ret;
}
static double calc_hbd_ssim(const uint8_t *_src, int _systride,
const uint8_t *_dst, int _dystride, int _w, int _h,
uint32_t bit_depth) {
static double calc_ssim(const uint8_t *_src, int _systride, const uint8_t *_dst,
int _dystride, int _w, int _h, uint32_t bit_depth) {
fs_ctx ctx;
double ret;
int l;
ret = 1;
fs_ctx_init(&ctx, _w, _h, FS_NLEVELS);
hbd_fs_downsample_level0(&ctx, CONVERT_TO_SHORTPTR(_src), _systride,
CONVERT_TO_SHORTPTR(_dst), _dystride, _w, _h);
fs_downsample_level0(&ctx, _src, _systride, _dst, _dystride, _w, _h,
bit_depth);
for (l = 0; l < FS_NLEVELS - 1; l++) {
fs_calc_structure(&ctx, l, bit_depth);
ret *= fs_average(&ctx, l);
......@@ -510,31 +468,15 @@ double aom_calc_fastssim(const YV12_BUFFER_CONFIG *source,
double ssimv;
aom_clear_system_state();
if (bit_depth == 8) {
*ssim_y =
calc_ssim(source->y_buffer, source->y_stride, dest->y_buffer,
dest->y_stride, source->y_crop_width, source->y_crop_height);
*ssim_u = calc_ssim(source->u_buffer, source->uv_stride, dest->u_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height);
*ssim_v = calc_ssim(source->v_buffer, source->uv_stride, dest->v_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height);
} else if (bit_depth == 10 || bit_depth == 12) {
*ssim_y = calc_hbd_ssim(source->y_buffer, source->y_stride, dest->y_buffer,
dest->y_stride, source->y_crop_width,
source->y_crop_height, bit_depth);
*ssim_u = calc_hbd_ssim(source->u_buffer, source->uv_stride, dest->u_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height, bit_depth);
*ssim_v = calc_hbd_ssim(source->v_buffer, source->uv_stride, dest->v_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height, bit_depth);
} else {
assert(0);
}
*ssim_y = calc_ssim(source->y_buffer, source->y_stride, dest->y_buffer,
dest->y_stride, source->y_crop_width,
source->y_crop_height, bit_depth);
*ssim_u = calc_ssim(source->u_buffer, source->uv_stride, dest->u_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height, bit_depth);
*ssim_v = calc_ssim(source->v_buffer, source->uv_stride, dest->v_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height, bit_depth);
ssimv = (*ssim_y) * .8 + .1 * ((*ssim_u) + (*ssim_v));
return convert_ssim_db(ssimv, 1.0);
}
......@@ -1518,7 +1518,6 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
#if CONFIG_INTERNAL_STATS
cpi->b_calculate_ssimg = 0;
cpi->b_calculate_blockiness = 1;
cpi->b_calculate_consistency = 1;
cpi->total_inconsistency = 0;
......@@ -1532,21 +1531,12 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
cpi->total_sq_error = 0;
cpi->total_samples = 0;
cpi->totalp_sq_error = 0;
cpi->totalp_samples = 0;
cpi->tot_recode_hits = 0;
cpi->summed_quality = 0;
cpi->summed_weights = 0;
cpi->summedp_quality = 0;
cpi->summedp_weights = 0;
}
if (cpi->b_calculate_ssimg) {
cpi->ssimg.worst = 100.0;
}
cpi->fastssim.worst = 100.0;
cpi->psnrhvs.worst = 100.0;
if (cpi->b_calculate_blockiness) {
......@@ -1559,7 +1549,6 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
cpi->common.mi_rows * cpi->common.mi_cols);
cpi->worst_consistency = 100.0;
}
#endif
cpi->first_time_stamp_ever = INT64_MAX;
......@@ -1750,12 +1739,8 @@ void av1_remove_compressor(AV1_COMP *cpi) {
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 totalp_psnr = aom_sse_to_psnr(
(double)cpi->totalp_samples, peak, (double)cpi->totalp_sq_error);
const double total_ssim =
100 * pow(cpi->summed_quality / cpi->summed_weights, 8.0);
const double totalp_ssim =
100 * pow(cpi->summedp_quality / cpi->summedp_weights, 8.0);
snprintf(headings, sizeof(headings),
"Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\tGLPsnrP\t"
......@@ -1766,8 +1751,8 @@ void av1_remove_compressor(AV1_COMP *cpi) {
"%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[ALL] / cpi->count, total_psnr,
cpi->psnrp.stat[ALL] / cpi->count, totalp_psnr, total_ssim,
totalp_ssim, cpi->fastssim.stat[ALL] / cpi->count,
cpi->psnr.stat[ALL] / cpi->count, total_psnr, total_ssim,
total_ssim, cpi->fastssim.stat[ALL] / cpi->count,
cpi->psnrhvs.stat[ALL] / cpi->count, cpi->psnr.worst,
cpi->worst_ssim, cpi->fastssim.worst, cpi->psnrhvs.worst);
......@@ -1779,7 +1764,7 @@ void av1_remove_compressor(AV1_COMP *cpi) {
if (cpi->b_calculate_consistency) {
double consistency =
aom_sse_to_psnr((double)cpi->totalp_samples, peak,
aom_sse_to_psnr((double)cpi->total_samples, peak,
(double)cpi->total_inconsistency);
SNPRINT(headings, "\tConsist\tWstCons");
......@@ -1787,12 +1772,6 @@ void av1_remove_compressor(AV1_COMP *cpi) {
SNPRINT2(results, "\t%7.3f", cpi->worst_consistency);
}
if (cpi->b_calculate_ssimg) {
SNPRINT(headings, "\t SSIMG\tWtSSIMG");
SNPRINT2(results, "\t%7.3f", cpi->ssimg.stat[ALL] / cpi->count);
SNPRINT2(results, "\t%7.3f", cpi->ssimg.worst);
}
fprintf(f, "%s\t Time\n", headings);
fprintf(f, "%s\t%8.0f\n", results, total_encode_time);
}
......@@ -3777,6 +3756,103 @@ static void adjust_image_stat(double y, double u, double v, double all,
s->stat[ALL] += all;
s->worst = AOMMIN(s->worst, all);
}
static void compute_internal_stats(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
double samples = 0.0;
uint32_t in_bit_depth = 8;
uint32_t bit_depth = 8;
#if CONFIG_AOM_HIGHBITDEPTH
if (cm->use_highbitdepth) {
in_bit_depth = cpi->oxcf.input_bit_depth;
bit_depth = cm->bit_depth;
}
#endif
if (cm->show_frame) {
const YV12_BUFFER_CONFIG *orig = cpi->Source;
const YV12_BUFFER_CONFIG *recon = cpi->common.frame_to_show;
double y, u, v, frame_all;
cpi->count++;
if (cpi->b_calculate_psnr) {
PSNR_STATS psnr;
double frame_ssim2 = 0.0, weight = 0.0;
aom_clear_system_state();
// TODO(yaowu): unify these two versions into one.
#if CONFIG_AOM_HIGHBITDEPTH
calc_highbd_psnr(orig, recon, &psnr, cpi->td.mb.e_mbd.bd, in_bit_depth);
#else
calc_psnr(orig, recon, &psnr);
#endif // CONFIG_AOM_HIGHBITDEPTH
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];
samples = psnr.samples[0];
// TODO(yaowu): unify these two versions into one.
#if CONFIG_AOM_HIGHBITDEPTH
if (cm->use_highbitdepth)
frame_ssim2 = aom_highbd_calc_ssim(orig, recon, &weight, bit_depth);
else
frame_ssim2 = aom_calc_ssim(orig, recon, &weight);
#else
frame_ssim2 = aom_calc_ssim(orig, recon, &weight);
#endif // CONFIG_AOM_HIGHBITDEPTH
cpi->worst_ssim = AOMMIN(cpi->worst_ssim, frame_ssim2);
cpi->summed_quality += frame_ssim2 * weight;
cpi->summed_weights += weight;
#if 0
{
FILE *f = fopen("q_used.stt", "a");
fprintf(f, "%5d : Y%f7.3:U%f7.3:V%f7.3:F%f7.3:S%7.3f\n",
cpi->common.current_video_frame, y2, u2, v2,
frame_psnr2, frame_ssim2);
fclose(f);
}
#endif
}
if (cpi->b_calculate_blockiness) {
#if CONFIG_AOM_HIGHBITDEPTH
if (!cm->use_highbitdepth)
#endif
{
const double frame_blockiness =
av1_get_blockiness(orig->y_buffer, orig->y_stride, recon->y_buffer,
recon->y_stride, orig->y_width, orig->y_height);
cpi->worst_blockiness = AOMMAX(cpi->worst_blockiness, frame_blockiness);
cpi->total_blockiness += frame_blockiness;
}
if (cpi->b_calculate_consistency) {
#if CONFIG_AOM_HIGHBITDEPTH
if (!cm->use_highbitdepth)
#endif
{
const double this_inconsistency = aom_get_ssim_metrics(
orig->y_buffer, orig->y_stride, recon->y_buffer, recon->y_stride,
orig->y_width, orig->y_height, cpi->ssim_vars, &cpi->metrics, 1);
const double peak = (double)((1 << in_bit_depth) - 1);
const double consistency =
aom_sse_to_psnr(samples, peak, cpi->total_inconsistency);
if (consistency > 0.0)
cpi->worst_consistency =
AOMMIN(cpi->worst_consistency, consistency);
cpi->total_inconsistency += this_inconsistency;
}
}
}
frame_all = aom_calc_fastssim(orig, recon, &y, &u, &v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
frame_all = aom_psnrhvs(orig, recon, &y, &u, &v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
#endif // CONFIG_INTERNAL_STATS
int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
......@@ -3965,135 +4041,9 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
generate_psnr_packet(cpi);
#if CONFIG_INTERNAL_STATS
if (oxcf->pass != 1) {
double samples = 0.0;
compute_internal_stats(cpi);
cpi->bytes += (int)(*size);
if (cm->show_frame) {
uint32_t bit_depth = 8;
#if CONFIG_AOM_HIGHBITDEPTH
uint32_t in_bit_depth = 8;
#endif
cpi->count++;
#if CONFIG_AOM_HIGHBITDEPTH
if (cm->use_highbitdepth) {
in_bit_depth = cpi->oxcf.input_bit_depth;
bit_depth = cm->bit_depth;
}
#endif
if (cpi->b_calculate_psnr) {
YV12_BUFFER_CONFIG *orig = cpi->Source;
YV12_BUFFER_CONFIG *recon = cpi->common.frame_to_show;
PSNR_STATS psnr;
#if CONFIG_AOM_HIGHBITDEPTH
calc_highbd_psnr(orig, recon, &psnr, cpi->td.mb.e_mbd.bd, in_bit_depth);
#else
calc_psnr(orig, recon, &psnr);
#endif // CONFIG_AOM_HIGHBITDEPTH
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];
samples = psnr.samples[0];
{
double frame_ssim2 = 0, weight = 0;
aom_clear_system_state();
#if CONFIG_AOM_HIGHBITDEPTH
if (cm->use_highbitdepth) {
frame_ssim2 =
aom_highbd_calc_ssim(orig, recon, &weight, (int)cm->bit_depth);
} else {
frame_ssim2 = aom_calc_ssim(orig, recon, &weight);
}
#else
frame_ssim2 = aom_calc_ssim(orig, recon, &weight);
#endif // CONFIG_AOM_HIGHBITDEPTH
cpi->worst_ssim = AOMMIN(cpi->worst_ssim, frame_ssim2);
cpi->summed_quality += frame_ssim2 * weight;
cpi->summed_weights += weight;
cpi->summedp_quality += frame_ssim2 * weight;
cpi->summedp_weights += weight;
#if 0
{
FILE *f = fopen("q_used.stt", "a");
fprintf(f, "%5d : Y%f7.3:U%f7.3:V%f7.3:F%f7.3:S%7.3f\n",
cpi->common.current_video_frame, y2, u2, v2,
frame_psnr2, frame_ssim2);
fclose(f);
}
#endif
}
}
if (cpi->b_calculate_blockiness) {
#if CONFIG_AOM_HIGHBITDEPTH
if (!cm->use_highbitdepth)
#endif
{
double frame_blockiness = av1_get_blockiness(
cpi->Source->y_buffer, cpi->Source->y_stride,
cm->frame_to_show->y_buffer, cm->frame_to_show->y_stride,
cpi->Source->y_width, cpi->Source->y_height);
cpi->worst_blockiness =
AOMMAX(cpi->worst_blockiness, frame_blockiness);
cpi->total_blockiness += frame_blockiness;
}
}
if (cpi->b_calculate_consistency) {
#if CONFIG_AOM_HIGHBITDEPTH
if (!cm->use_highbitdepth)
#endif
{
double this_inconsistency = aom_get_ssim_metrics(
cpi->Source->y_buffer, cpi->Source->y_stride,
cm->frame_to_show->y_buffer, cm->frame_to_show->y_stride,
cpi->Source->y_width, cpi->Source->y_height, cpi->ssim_vars,
&cpi->metrics, 1);
const double peak = (double)((1 << cpi->oxcf.input_bit_depth) - 1);
double consistency =
aom_sse_to_psnr(samples, peak, (double)cpi->total_inconsistency);
if (consistency > 0.0)
cpi->worst_consistency =
AOMMIN(cpi->worst_consistency, consistency);
cpi->total_inconsistency += this_inconsistency;
}
}
if (cpi->b_calculate_ssimg) {
double y, u, v, frame_all;
#if CONFIG_AOM_HIGHBITDEPTH
if (cm->use_highbitdepth) {
frame_all = aom_highbd_calc_ssimg(cpi->Source, cm->frame_to_show, &y,
&u, &v, (int)cm->bit_depth);
} else {
frame_all =
aom_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
}
#else
frame_all = aom_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
#endif // CONFIG_AOM_HIGHBITDEPTH
adjust_image_stat(y, u, v, frame_all, &cpi->ssimg);
}
{
double y, u, v, frame_all;
frame_all = aom_calc_fastssim(cpi->Source, cm->frame_to_show, &y, &u,
&v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
frame_all =
aom_psnrhvs(cpi->Source, cm->frame_to_show, &y, &u, &v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
}
#endif
......
......@@ -411,28 +411,19 @@ typedef struct AV1_COMP {
uint64_t total_samples;
ImageStat psnr;
uint64_t totalp_sq_error;
uint64_t totalp_samples;
ImageStat psnrp;
double total_blockiness;
double worst_blockiness;
int bytes;
double summed_quality;
double summed_weights;
double summedp_quality;
double summedp_weights;
unsigned int tot_recode_hits;
double worst_ssim;
ImageStat ssimg;
ImageStat fastssim;
ImageStat psnrhvs;
int b_calculate_ssimg;
int b_calculate_blockiness;
int b_calculate_consistency;
double total_inconsistency;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment