Cleaning up and fixing psnr calculation code.
Introducing calc_psnr() which calculates psnr between two yv12 buffers. Previously we incorrectly used width/height instead of crop_width/crop_height to calculate number of samples -- fixed. Change-Id: Iecda01980555de55ad347e0276e6641c793fa56c
This commit is contained in:
@@ -1734,16 +1734,20 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) {
|
||||
cpi->bytes = 0;
|
||||
|
||||
if (cpi->b_calculate_psnr) {
|
||||
cpi->total_sq_error = 0.0;
|
||||
cpi->total_sq_error2 = 0.0;
|
||||
cpi->total_y = 0.0;
|
||||
cpi->total_u = 0.0;
|
||||
cpi->total_v = 0.0;
|
||||
cpi->total = 0.0;
|
||||
cpi->total_sq_error = 0;
|
||||
cpi->total_samples = 0;
|
||||
|
||||
cpi->totalp_y = 0.0;
|
||||
cpi->totalp_u = 0.0;
|
||||
cpi->totalp_v = 0.0;
|
||||
cpi->totalp = 0.0;
|
||||
cpi->totalp_sq_error = 0;
|
||||
cpi->totalp_samples = 0;
|
||||
|
||||
cpi->tot_recode_hits = 0;
|
||||
cpi->summed_quality = 0;
|
||||
cpi->summed_weights = 0;
|
||||
@@ -1978,21 +1982,20 @@ void vp9_remove_compressor(VP9_PTR *ptr) {
|
||||
/ time_encoded;
|
||||
|
||||
if (cpi->b_calculate_psnr) {
|
||||
YV12_BUFFER_CONFIG *lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
|
||||
double samples = 3.0 / 2 * cpi->count *
|
||||
lst_yv12->y_width * lst_yv12->y_height;
|
||||
double total_psnr = vp9_mse2psnr(samples, 255.0, cpi->total_sq_error);
|
||||
double total_psnr2 = vp9_mse2psnr(samples, 255.0, cpi->total_sq_error2);
|
||||
double total_ssim = 100 * pow(cpi->summed_quality /
|
||||
cpi->summed_weights, 8.0);
|
||||
double total_ssimp = 100 * pow(cpi->summedp_quality /
|
||||
cpi->summedp_weights, 8.0);
|
||||
const double total_psnr = vp9_mse2psnr(cpi->total_samples, 255.0,
|
||||
cpi->total_sq_error);
|
||||
const double totalp_psnr = vp9_mse2psnr(cpi->totalp_samples, 255.0,
|
||||
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);
|
||||
|
||||
fprintf(f, "Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\tGLPsnrP\t"
|
||||
"VPXSSIM\tVPSSIMP\t Time(ms)\n");
|
||||
fprintf(f, "%7.2f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f\n",
|
||||
dr, cpi->total / cpi->count, total_psnr,
|
||||
cpi->totalp / cpi->count, total_psnr2, total_ssim, total_ssimp,
|
||||
cpi->totalp / cpi->count, totalp_psnr, total_ssim, totalp_ssim,
|
||||
total_encode_time);
|
||||
}
|
||||
|
||||
@@ -2136,8 +2139,8 @@ void vp9_remove_compressor(VP9_PTR *ptr) {
|
||||
}
|
||||
|
||||
|
||||
static uint64_t calc_plane_error(uint8_t *orig, int orig_stride,
|
||||
uint8_t *recon, int recon_stride,
|
||||
static uint64_t calc_plane_error(const uint8_t *orig, int orig_stride,
|
||||
const uint8_t *recon, int recon_stride,
|
||||
unsigned int cols, unsigned int rows) {
|
||||
unsigned int row, col;
|
||||
uint64_t total_sse = 0;
|
||||
@@ -2154,8 +2157,8 @@ static uint64_t calc_plane_error(uint8_t *orig, int orig_stride,
|
||||
/* Handle odd-sized width */
|
||||
if (col < cols) {
|
||||
unsigned int border_row, border_col;
|
||||
uint8_t *border_orig = orig;
|
||||
uint8_t *border_recon = recon;
|
||||
const uint8_t *border_orig = orig;
|
||||
const uint8_t *border_recon = recon;
|
||||
|
||||
for (border_row = 0; border_row < 16; border_row++) {
|
||||
for (border_col = col; border_col < cols; border_col++) {
|
||||
@@ -2186,51 +2189,57 @@ static uint64_t calc_plane_error(uint8_t *orig, int orig_stride,
|
||||
return total_sse;
|
||||
}
|
||||
|
||||
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
|
||||
} PSNR_STATS;
|
||||
|
||||
static void generate_psnr_packet(VP9_COMP *cpi) {
|
||||
YV12_BUFFER_CONFIG *orig = cpi->Source;
|
||||
YV12_BUFFER_CONFIG *recon = cpi->common.frame_to_show;
|
||||
struct vpx_codec_cx_pkt pkt;
|
||||
uint64_t sse;
|
||||
int i;
|
||||
unsigned int width = orig->y_crop_width;
|
||||
unsigned int height = orig->y_crop_height;
|
||||
static void calc_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b,
|
||||
PSNR_STATS *psnr) {
|
||||
const int widths[3] = {a->y_width, a->uv_width, a->uv_width };
|
||||
const int heights[3] = {a->y_height, a->uv_height, a->uv_height};
|
||||
const uint8_t *a_planes[3] = {a->y_buffer, a->u_buffer, a->v_buffer };
|
||||
const int a_strides[3] = {a->y_stride, a->uv_stride, a->uv_stride};
|
||||
const uint8_t *b_planes[3] = {b->y_buffer, b->u_buffer, b->v_buffer };
|
||||
const int b_strides[3] = {b->y_stride, b->uv_stride, b->uv_stride};
|
||||
int i;
|
||||
uint64_t total_sse = 0;
|
||||
uint32_t total_samples = 0;
|
||||
|
||||
pkt.kind = VPX_CODEC_PSNR_PKT;
|
||||
sse = calc_plane_error(orig->y_buffer, orig->y_stride,
|
||||
recon->y_buffer, recon->y_stride,
|
||||
width, height);
|
||||
pkt.data.psnr.sse[0] = sse;
|
||||
pkt.data.psnr.sse[1] = sse;
|
||||
pkt.data.psnr.samples[0] = width * height;
|
||||
pkt.data.psnr.samples[1] = width * height;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
const int w = widths[i];
|
||||
const int h = heights[i];
|
||||
const uint32_t samples = w * h;
|
||||
const double sse = calc_plane_error(a_planes[i], a_strides[i],
|
||||
b_planes[i], b_strides[i],
|
||||
w, h);
|
||||
psnr->sse[1 + i] = sse;
|
||||
psnr->samples[1 + i] = samples;
|
||||
psnr->psnr[1 + i] = vp9_mse2psnr(samples, 255.0, sse);
|
||||
|
||||
width = orig->uv_crop_width;
|
||||
height = orig->uv_crop_height;
|
||||
total_sse += sse;
|
||||
total_samples += samples;
|
||||
}
|
||||
|
||||
sse = calc_plane_error(orig->u_buffer, orig->uv_stride,
|
||||
recon->u_buffer, recon->uv_stride,
|
||||
width, height);
|
||||
pkt.data.psnr.sse[0] += sse;
|
||||
pkt.data.psnr.sse[2] = sse;
|
||||
pkt.data.psnr.samples[0] += width * height;
|
||||
pkt.data.psnr.samples[2] = width * height;
|
||||
|
||||
sse = calc_plane_error(orig->v_buffer, orig->uv_stride,
|
||||
recon->v_buffer, recon->uv_stride,
|
||||
width, height);
|
||||
pkt.data.psnr.sse[0] += sse;
|
||||
pkt.data.psnr.sse[3] = sse;
|
||||
pkt.data.psnr.samples[0] += width * height;
|
||||
pkt.data.psnr.samples[3] = width * height;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
pkt.data.psnr.psnr[i] = vp9_mse2psnr(pkt.data.psnr.samples[i], 255.0,
|
||||
(double)pkt.data.psnr.sse[i]);
|
||||
|
||||
vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
|
||||
psnr->sse[0] = total_sse;
|
||||
psnr->samples[0] = total_samples;
|
||||
psnr->psnr[0] = vp9_mse2psnr(total_samples, 255.0, total_sse);
|
||||
}
|
||||
|
||||
static void generate_psnr_packet(VP9_COMP *cpi) {
|
||||
struct vpx_codec_cx_pkt pkt;
|
||||
int i;
|
||||
PSNR_STATS psnr;
|
||||
calc_psnr(cpi->Source, cpi->common.frame_to_show, &psnr);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
pkt.data.psnr.samples[i] = psnr.samples[i];
|
||||
pkt.data.psnr.sse[i] = psnr.sse[i];
|
||||
pkt.data.psnr.psnr[i] = psnr.psnr[i];
|
||||
}
|
||||
pkt.kind = VPX_CODEC_PSNR_PKT;
|
||||
vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
|
||||
}
|
||||
|
||||
int vp9_use_as_reference(VP9_PTR ptr, int ref_frame_flags) {
|
||||
VP9_COMP *cpi = (VP9_COMP *)(ptr);
|
||||
@@ -3686,76 +3695,43 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
|
||||
cpi->count++;
|
||||
|
||||
if (cpi->b_calculate_psnr) {
|
||||
double ye, ue, ve;
|
||||
double frame_psnr;
|
||||
YV12_BUFFER_CONFIG *orig = cpi->Source;
|
||||
YV12_BUFFER_CONFIG *recon = cpi->common.frame_to_show;
|
||||
YV12_BUFFER_CONFIG *pp = &cm->post_proc_buffer;
|
||||
int y_samples = orig->y_height * orig->y_width;
|
||||
int uv_samples = orig->uv_height * orig->uv_width;
|
||||
int t_samples = y_samples + 2 * uv_samples;
|
||||
double sq_error;
|
||||
YV12_BUFFER_CONFIG *orig = cpi->Source;
|
||||
YV12_BUFFER_CONFIG *recon = cpi->common.frame_to_show;
|
||||
YV12_BUFFER_CONFIG *pp = &cm->post_proc_buffer;
|
||||
PSNR_STATS psnr;
|
||||
calc_psnr(orig, recon, &psnr);
|
||||
|
||||
ye = (double)calc_plane_error(orig->y_buffer, orig->y_stride,
|
||||
recon->y_buffer, recon->y_stride,
|
||||
orig->y_crop_width, orig->y_crop_height);
|
||||
cpi->total += psnr.psnr[0];
|
||||
cpi->total_y += psnr.psnr[1];
|
||||
cpi->total_u += psnr.psnr[2];
|
||||
cpi->total_v += psnr.psnr[3];
|
||||
cpi->total_sq_error += psnr.sse[0];
|
||||
cpi->total_samples += psnr.samples[0];
|
||||
|
||||
ue = (double)calc_plane_error(orig->u_buffer, orig->uv_stride,
|
||||
recon->u_buffer, recon->uv_stride,
|
||||
orig->uv_crop_width, orig->uv_crop_height);
|
||||
|
||||
ve = (double)calc_plane_error(orig->v_buffer, orig->uv_stride,
|
||||
recon->v_buffer, recon->uv_stride,
|
||||
orig->uv_crop_width, orig->uv_crop_height);
|
||||
|
||||
sq_error = ye + ue + ve;
|
||||
|
||||
frame_psnr = vp9_mse2psnr(t_samples, 255.0, sq_error);
|
||||
|
||||
cpi->total_y += vp9_mse2psnr(y_samples, 255.0, ye);
|
||||
cpi->total_u += vp9_mse2psnr(uv_samples, 255.0, ue);
|
||||
cpi->total_v += vp9_mse2psnr(uv_samples, 255.0, ve);
|
||||
cpi->total_sq_error += sq_error;
|
||||
cpi->total += frame_psnr;
|
||||
{
|
||||
double frame_psnr2, frame_ssim2 = 0;
|
||||
double weight = 0;
|
||||
PSNR_STATS psnr2;
|
||||
double frame_ssim2 = 0, weight = 0;
|
||||
#if CONFIG_VP9_POSTPROC
|
||||
vp9_deblock(cm->frame_to_show, &cm->post_proc_buffer,
|
||||
cm->lf.filter_level * 10 / 6);
|
||||
#endif
|
||||
vp9_clear_system_state();
|
||||
|
||||
ye = (double)calc_plane_error(orig->y_buffer, orig->y_stride,
|
||||
pp->y_buffer, pp->y_stride,
|
||||
orig->y_crop_width, orig->y_crop_height);
|
||||
calc_psnr(orig, pp, &psnr2);
|
||||
|
||||
ue = (double)calc_plane_error(orig->u_buffer, orig->uv_stride,
|
||||
pp->u_buffer, pp->uv_stride,
|
||||
orig->uv_crop_width, orig->uv_crop_height);
|
||||
cpi->totalp += psnr2.psnr[0];
|
||||
cpi->totalp_y += psnr2.psnr[1];
|
||||
cpi->totalp_u += psnr2.psnr[2];
|
||||
cpi->totalp_v += psnr2.psnr[3];
|
||||
cpi->totalp_sq_error += psnr2.sse[0];
|
||||
cpi->totalp_samples += psnr2.samples[0];
|
||||
|
||||
ve = (double)calc_plane_error(orig->v_buffer, orig->uv_stride,
|
||||
pp->v_buffer, pp->uv_stride,
|
||||
orig->uv_crop_width, orig->uv_crop_height);
|
||||
|
||||
sq_error = ye + ue + ve;
|
||||
|
||||
frame_psnr2 = vp9_mse2psnr(t_samples, 255.0, sq_error);
|
||||
|
||||
cpi->totalp_y += vp9_mse2psnr(y_samples, 255.0, ye);
|
||||
cpi->totalp_u += vp9_mse2psnr(uv_samples, 255.0, ue);
|
||||
cpi->totalp_v += vp9_mse2psnr(uv_samples, 255.0, ve);
|
||||
cpi->total_sq_error2 += sq_error;
|
||||
cpi->totalp += frame_psnr2;
|
||||
|
||||
frame_ssim2 = vp9_calc_ssim(cpi->Source,
|
||||
recon, 1, &weight);
|
||||
frame_ssim2 = vp9_calc_ssim(orig, recon, 1, &weight);
|
||||
|
||||
cpi->summed_quality += frame_ssim2 * weight;
|
||||
cpi->summed_weights += weight;
|
||||
|
||||
frame_ssim2 = vp9_calc_ssim(cpi->Source,
|
||||
&cm->post_proc_buffer, 1, &weight);
|
||||
frame_ssim2 = vp9_calc_ssim(orig, &cm->post_proc_buffer, 1, &weight);
|
||||
|
||||
cpi->summedp_quality += frame_ssim2 * weight;
|
||||
cpi->summedp_weights += weight;
|
||||
@@ -3773,8 +3749,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
|
||||
|
||||
if (cpi->b_calculate_ssimg) {
|
||||
double y, u, v, frame_all;
|
||||
frame_all = vp9_calc_ssimg(cpi->Source, cm->frame_to_show,
|
||||
&y, &u, &v);
|
||||
frame_all = vp9_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
|
||||
cpi->total_ssimg_y += y;
|
||||
cpi->total_ssimg_u += u;
|
||||
cpi->total_ssimg_v += v;
|
||||
|
@@ -563,12 +563,16 @@ typedef struct VP9_COMP {
|
||||
double total_u;
|
||||
double total_v;
|
||||
double total;
|
||||
double total_sq_error;
|
||||
uint64_t total_sq_error;
|
||||
uint64_t total_samples;
|
||||
|
||||
double totalp_y;
|
||||
double totalp_u;
|
||||
double totalp_v;
|
||||
double totalp;
|
||||
double total_sq_error2;
|
||||
uint64_t totalp_sq_error;
|
||||
uint64_t totalp_samples;
|
||||
|
||||
int bytes;
|
||||
double summed_quality;
|
||||
double summed_weights;
|
||||
|
Reference in New Issue
Block a user