Commit 003a9d20 authored by Yaowu Xu's avatar Yaowu Xu

Port metric computation changes from nextgenv2

Change-Id: I4aceffcdf7af59ffeb51984f0345c3a4c7e76a9f
parent 7ed1d54a
......@@ -21,7 +21,7 @@
#include "vp8/common/alloccommon.h"
#include "mcomp.h"
#include "firstpass.h"
#include "vpx/internal/vpx_psnr.h"
#include "vpx_dsp/psnr.h"
#include "vpx_scale/vpx_scale.h"
#include "vp8/common/extend.h"
#include "ratectrl.h"
......@@ -2023,14 +2023,6 @@ struct VP8_COMP* vp8_create_compressor(VP8_CONFIG *oxcf)
cpi->summed_weights = 0;
}
if (cpi->b_calculate_ssimg)
{
cpi->total_ssimg_y = 0;
cpi->total_ssimg_u = 0;
cpi->total_ssimg_v = 0;
cpi->total_ssimg_all = 0;
}
#endif
cpi->first_time_stamp_ever = 0x7FFFFFFF;
......@@ -2313,45 +2305,6 @@ void vp8_remove_compressor(VP8_COMP **ptr)
rate_err, fabs(rate_err));
}
}
if (cpi->b_calculate_ssimg)
{
if (cpi->oxcf.number_of_layers > 1)
{
int i;
fprintf(f, "Layer\tBitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t"
"Time(us)\n");
for (i=0; i<(int)cpi->oxcf.number_of_layers; i++)
{
double dr = (double)cpi->bytes_in_layer[i] *
8.0 / 1000.0 / time_encoded;
fprintf(f, "%5d\t%7.3f\t%6.4f\t"
"%6.4f\t%6.4f\t%6.4f\t%8.0f\n",
i, dr,
cpi->total_ssimg_y_in_layer[i] /
cpi->frames_in_layer[i],
cpi->total_ssimg_u_in_layer[i] /
cpi->frames_in_layer[i],
cpi->total_ssimg_v_in_layer[i] /
cpi->frames_in_layer[i],
cpi->total_ssimg_all_in_layer[i] /
cpi->frames_in_layer[i],
total_encode_time);
}
}
else
{
fprintf(f, "BitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t"
"Time(us)\n");
fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
cpi->total_ssimg_y / cpi->count,
cpi->total_ssimg_u / cpi->count,
cpi->total_ssimg_v / cpi->count,
cpi->total_ssimg_all / cpi->count, total_encode_time);
}
}
fclose(f);
#if 0
f = fopen("qskip.stt", "a");
......@@ -5746,38 +5699,6 @@ int vp8_get_compressed_data(VP8_COMP *cpi, unsigned int *frame_flags, unsigned l
}
#endif
}
if (cpi->b_calculate_ssimg)
{
double y, u, v, frame_all;
frame_all = vpx_calc_ssimg(cpi->Source, cm->frame_to_show,
&y, &u, &v);
if (cpi->oxcf.number_of_layers > 1)
{
unsigned int i;
for (i=cpi->current_layer;
i<cpi->oxcf.number_of_layers; i++)
{
if (!cpi->b_calculate_psnr)
cpi->frames_in_layer[i]++;
cpi->total_ssimg_y_in_layer[i] += y;
cpi->total_ssimg_u_in_layer[i] += u;
cpi->total_ssimg_v_in_layer[i] += v;
cpi->total_ssimg_all_in_layer[i] += frame_all;
}
}
else
{
cpi->total_ssimg_y += y;
cpi->total_ssimg_u += u;
cpi->total_ssimg_v += v;
cpi->total_ssimg_all += frame_all;
}
}
}
}
......
......@@ -636,12 +636,6 @@ typedef struct VP8_COMP
double summed_weights;
unsigned int tot_recode_hits;
double total_ssimg_y;
double total_ssimg_u;
double total_ssimg_v;
double total_ssimg_all;
int b_calculate_ssimg;
#endif
int b_calculate_psnr;
......
This diff is collapsed.
......@@ -12,7 +12,7 @@
#include <limits.h>
#include "./vpx_scale_rtcd.h"
#include "vpx_dsp/psnr.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
......@@ -52,12 +52,12 @@ static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
filt_err = vp9_highbd_get_y_sse(sd, cm->frame_to_show);
filt_err = vpx_highbd_get_y_sse(sd, cm->frame_to_show);
} else {
filt_err = vp9_get_y_sse(sd, cm->frame_to_show);
filt_err = vpx_get_y_sse(sd, cm->frame_to_show);
}
#else
filt_err = vp9_get_y_sse(sd, cm->frame_to_show);
filt_err = vpx_get_y_sse(sd, cm->frame_to_show);
#endif // CONFIG_VP9_HIGHBITDEPTH
// Re-instate the unfiltered frame
......
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_INTERNAL_VPX_PSNR_H_
#define VPX_INTERNAL_VPX_PSNR_H_
#ifdef __cplusplus
extern "C" {
#endif
// TODO(dkovalev) change vpx_sse_to_psnr signature: double -> int64_t
/*!\brief Converts SSE to PSNR
*
* Converts sum of squared errros (SSE) to peak signal-to-noise ratio (PNSR).
*
* \param[in] samples Number of samples
* \param[in] peak Max sample value
* \param[in] sse Sum of squared errors
*/
double vpx_sse_to_psnr(double samples, double peak, double sse);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_INTERNAL_VPX_PSNR_H_
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "vpx/internal/vpx_psnr.h"
#define MAX_PSNR 100.0
double vpx_sse_to_psnr(double samples, double peak, double sse) {
if (sse > 0.0) {
const double psnr = 10.0 * log10(samples * peak * peak / sse);
return psnr > MAX_PSNR ? MAX_PSNR : psnr;
} else {
return MAX_PSNR;
}
}
......@@ -36,10 +36,8 @@ API_SRCS-yes += vpx_decoder.h
API_SRCS-yes += src/vpx_encoder.c
API_SRCS-yes += vpx_encoder.h
API_SRCS-yes += internal/vpx_codec_internal.h
API_SRCS-yes += internal/vpx_psnr.h
API_SRCS-yes += src/vpx_codec.c
API_SRCS-yes += src/vpx_image.c
API_SRCS-yes += src/vpx_psnr.c
API_SRCS-yes += vpx_codec.h
API_SRCS-yes += vpx_codec.mk
API_SRCS-yes += vpx_frame_buffer.h
......
......@@ -10,6 +10,7 @@
* This code was originally written by: Nathan E. Egge, at the Daala
* project.
*/
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
......@@ -17,19 +18,24 @@
#include "./vpx_dsp_rtcd.h"
#include "vpx_dsp/ssim.h"
#include "vpx_ports/system_state.h"
/* TODO(jbb): High bit depth version of this code needed */
typedef struct fs_level fs_level;
typedef struct fs_ctx fs_ctx;
#define SSIM_C1 (255 * 255 * 0.01 * 0.01)
#define SSIM_C2 (255 * 255 * 0.03 * 0.03)
#if CONFIG_VP9_HIGHBITDEPTH
#define SSIM_C1_10 (1023 * 1023 * 0.01 * 0.01)
#define SSIM_C1_12 (4095 * 4095 * 0.01 * 0.01)
#define SSIM_C2_10 (1023 * 1023 * 0.03 * 0.03)
#define SSIM_C2_12 (4095 * 4095 * 0.03 * 0.03)
#endif
#define FS_MINI(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define FS_MAXI(_a, _b) ((_a) > (_b) ? (_a) : (_b))
struct fs_level {
uint16_t *im1;
uint16_t *im2;
uint32_t *im1;
uint32_t *im2;
double *ssim;
int w;
int h;
......@@ -80,7 +86,7 @@ static void fs_ctx_init(fs_ctx *_ctx, int _w, int _h, int _nlevels) {
level_size += sizeof(*_ctx->level[l].ssim) - 1;
level_size /= sizeof(*_ctx->level[l].ssim);
level_size *= sizeof(*_ctx->level[l].ssim);
_ctx->level[l].im1 = (uint16_t *) data;
_ctx->level[l].im1 = (uint32_t *)data;
_ctx->level[l].im2 = _ctx->level[l].im1 + im_size;
data += level_size;
_ctx->level[l].ssim = (double *) data;
......@@ -96,10 +102,10 @@ static void fs_ctx_clear(fs_ctx *_ctx) {
}
static void fs_downsample_level(fs_ctx *_ctx, int _l) {
const uint16_t *src1;
const uint16_t *src2;
uint16_t *dst1;
uint16_t *dst2;
const uint32_t *src1;
const uint32_t *src2;
uint32_t *dst1;
uint32_t *dst2;
int w2;
int h2;
int w;
......@@ -132,11 +138,12 @@ 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) {
uint16_t *dst1;
uint16_t *dst2;
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 bd, uint32_t shift) {
uint32_t *dst1;
uint32_t *dst2;
int w;
int h;
int i;
......@@ -155,21 +162,34 @@ 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];
if (bd == 8 && shift == 0) {
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] >> shift)
+ (src1s[j0 * _s1ystride + i1] >> shift)
+ (src1s[j1 * _s1ystride + i0] >> shift)
+ (src1s[j1 * _s1ystride + i1] >> shift);
dst2[j * w + i] = (src2s[j0 * _s2ystride + i0] >> shift)
+ (src2s[j0 * _s2ystride + i1] >> shift)
+ (src2s[j1 * _s2ystride + i0] >> shift)
+ (src2s[j1 * _s2ystride + i1] >> shift);
}
}
}
}
static void fs_apply_luminance(fs_ctx *_ctx, int _l) {
static void fs_apply_luminance(fs_ctx *_ctx, int _l, int bit_depth) {
unsigned *col_sums_x;
unsigned *col_sums_y;
uint16_t *im1;
uint16_t *im2;
uint32_t *im1;
uint32_t *im2;
double *ssim;
double c1;
int w;
......@@ -178,6 +198,15 @@ static void fs_apply_luminance(fs_ctx *_ctx, int _l) {
int j1offs;
int i;
int j;
double ssim_c1 = SSIM_C1;
#if CONFIG_VP9_HIGHBITDEPTH
if (bit_depth == 10)
ssim_c1 = SSIM_C1_10;
if (bit_depth == 12)
ssim_c1 = SSIM_C1_12;
#else
assert(bit_depth == 8);
#endif
w = _ctx->level[_l].w;
h = _ctx->level[_l].h;
col_sums_x = _ctx->col_buf;
......@@ -196,7 +225,7 @@ static void fs_apply_luminance(fs_ctx *_ctx, int _l) {
col_sums_y[i] += im2[j1offs + i];
}
ssim = _ctx->level[_l].ssim;
c1 = (double) (SSIM_C1 * 4096 * (1 << 4 * _l));
c1 = (double) (ssim_c1 * 4096 * (1 << 4 * _l));
for (j = 0; j < h; j++) {
unsigned mux;
unsigned muy;
......@@ -294,9 +323,9 @@ static void fs_apply_luminance(fs_ctx *_ctx, int _l) {
} \
while (0)
static void fs_calc_structure(fs_ctx *_ctx, int _l) {
uint16_t *im1;
uint16_t *im2;
static void fs_calc_structure(fs_ctx *_ctx, int _l, int bit_depth) {
uint32_t *im1;
uint32_t *im2;
unsigned *gx_buf;
unsigned *gy_buf;
double *ssim;
......@@ -309,6 +338,16 @@ static void fs_calc_structure(fs_ctx *_ctx, int _l) {
int h;
int i;
int j;
double ssim_c2 = SSIM_C2;
#if CONFIG_VP9_HIGHBITDEPTH
if (bit_depth == 10)
ssim_c2 = SSIM_C2_10;
if (bit_depth == 12)
ssim_c2 = SSIM_C2_12;
#else
assert(bit_depth == 8);
#endif
w = _ctx->level[_l].w;
h = _ctx->level[_l].h;
im1 = _ctx->level[_l].im1;
......@@ -318,7 +357,7 @@ static void fs_calc_structure(fs_ctx *_ctx, int _l) {
stride = w + 8;
gy_buf = gx_buf + 8 * stride;
memset(gx_buf, 0, 2 * 8 * stride * sizeof(*gx_buf));
c2 = SSIM_C2 * (1 << 4 * _l) * 16 * 104;
c2 = ssim_c2 * (1 << 4 * _l) * 16 * 104;
for (j = 0; j < h + 4; j++) {
if (j < h - 1) {
for (i = 0; i < w - 1; i++) {
......@@ -326,11 +365,11 @@ static void fs_calc_structure(fs_ctx *_ctx, int _l) {
unsigned g2;
unsigned gx;
unsigned gy;
g1 = abs(im1[(j + 1) * w + i + 1] - im1[j * w + i]);
g2 = abs(im1[(j + 1) * w + i] - im1[j * w + i + 1]);
g1 = abs((int)im1[(j + 1) * w + i + 1] - (int)im1[j * w + i]);
g2 = abs((int)im1[(j + 1) * w + i] - (int)im1[j * w + i + 1]);
gx = 4 * FS_MAXI(g1, g2) + FS_MINI(g1, g2);
g1 = abs(im2[(j + 1) * w + i + 1] - im2[j * w + i]);
g2 = abs(im2[(j + 1) * w + i] - im2[j * w + i + 1]);
g1 = abs((int)im2[(j + 1) * w + i + 1] - (int)im2[j * w + i]);
g2 = abs((int)im2[(j + 1) * w + i] - (int)im2[j * w + i + 1]);
gy = 4 * FS_MAXI(g1, g2) + FS_MINI(g1, g2);
gx_buf[(j & 7) * stride + i + 4] = gx;
gy_buf[(j & 7) * stride + i + 4] = gy;
......@@ -421,48 +460,55 @@ static double fs_average(fs_ctx *_ctx, int _l) {
return pow(ret / (w * h), FS_WEIGHTS[_l]);
}
static double calc_ssim(const unsigned char *_src, int _systride,
const unsigned char *_dst, int _dystride, int _w, int _h) {
static double convert_ssim_db(double _ssim, double _weight) {
assert(_weight >= _ssim);
if ((_weight - _ssim) < 1e-10)
return MAX_SSIM_DB;
return 10 * (log10(_weight) - log10(_weight - _ssim));
}
static double calc_ssim(const uint8_t *_src, int _systride,
const uint8_t *_dst, int _dystride,
int _w, int _h, uint32_t _bd, uint32_t _shift) {
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);
fs_downsample_level0(&ctx, _src, _systride, _dst, _dystride,
_w, _h, _bd, _shift);
for (l = 0; l < FS_NLEVELS - 1; l++) {
fs_calc_structure(&ctx, l);
fs_calc_structure(&ctx, l, _bd);
ret *= fs_average(&ctx, l);
fs_downsample_level(&ctx, l + 1);
}
fs_calc_structure(&ctx, l);
fs_apply_luminance(&ctx, l);
fs_calc_structure(&ctx, l, _bd);
fs_apply_luminance(&ctx, l, _bd);
ret *= fs_average(&ctx, l);
fs_ctx_clear(&ctx);
return ret;
}
static double convert_ssim_db(double _ssim, double _weight) {
return 10 * (log10(_weight) - log10(_weight - _ssim));
}
double vpx_calc_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
double *ssim_y, double *ssim_u, double *ssim_v) {
double *ssim_y, double *ssim_u, double *ssim_v,
uint32_t bd, uint32_t in_bd) {
double ssimv;
uint32_t bd_shift = 0;
vpx_clear_system_state();
assert(bd >= in_bd);
bd_shift = bd - in_bd;
*ssim_y = calc_ssim(source->y_buffer, source->y_stride, dest->y_buffer,
dest->y_stride, source->y_crop_width,
source->y_crop_height);
source->y_crop_height, in_bd, bd_shift);
*ssim_u = calc_ssim(source->u_buffer, source->uv_stride, dest->u_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height);
source->uv_crop_height, in_bd, bd_shift);
*ssim_v = calc_ssim(source->v_buffer, source->uv_stride, dest->v_buffer,
dest->uv_stride, source->uv_crop_width,
source->uv_crop_height);
ssimv = (*ssim_y) * .8 + .1 * ((*ssim_u) + (*ssim_v));
source->uv_crop_height, in_bd, bd_shift);
ssimv = (*ssim_y) * .8 + .1 * ((*ssim_u) + (*ssim_v));
return convert_ssim_db(ssimv, 1.0);
}
/*
* Copyright (c) 2016 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include <assert.h>
#include "./vpx_dsp_rtcd.h"
#include "vpx_dsp/psnr.h"
#include "vpx_scale/yv12config.h"
double vpx_sse_to_psnr(double samples, double peak, double sse) {
if (sse > 0.0) {
const double psnr = 10.0 * log10(samples * peak * peak / sse);
return psnr > MAX_PSNR ? MAX_PSNR : psnr;
} else {
return MAX_PSNR;
}
}
/* TODO(yaowu): The block_variance calls the unoptimized versions of variance()
* and highbd_8_variance(). It should not.
*/
static void encoder_variance(const uint8_t *a, int a_stride,
const uint8_t *b, int b_stride,
int w, int h, unsigned int *sse, int *sum) {
int i, j;
*sum = 0;
*sse = 0;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
const int diff = a[j] - b[j];
*sum += diff;
*sse += diff * diff;
}
a += a_stride;
b += b_stride;
}
}
#if CONFIG_VP9_HIGHBITDEPTH
static void encoder_highbd_variance64(const uint8_t *a8, int a_stride,
const uint8_t *b8, int b_stride,
int w, int h, uint64_t *sse,
uint64_t *sum) {
int i, j;
uint16_t *a = CONVERT_TO_SHORTPTR(a8);
uint16_t *b = CONVERT_TO_SHORTPTR(b8);
*sum = 0;
*sse = 0;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
const int diff = a[j] - b[j];
*sum += diff;
*sse += diff * diff;
}
a += a_stride;
b += b_stride;
}
}
static void encoder_highbd_8_variance(const uint8_t *a8, int a_stride,
const uint8_t *b8, int b_stride,
int w, int h,
unsigned int *sse, int *sum) {
uint64_t sse_long = 0;
uint64_t sum_long = 0;
encoder_highbd_variance64(a8, a_stride, b8, b_stride, w, h,
&sse_long, &sum_long);
*sse = (unsigned int)sse_long;
*sum = (int)sum_long;
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static int64_t get_sse(const uint8_t *a, int a_stride,
const uint8_t *b, int b_stride,
int width, int height) {
const int dw = width % 16;
const int dh = height % 16;
int64_t total_sse = 0;
unsigned int sse = 0;
int sum = 0;
int x, y;
if (dw > 0) {
encoder_variance(&a[width - dw], a_stride, &b[width - dw], b_stride,
dw, height, &sse, &sum);
total_sse += sse;
}
if (dh > 0) {
encoder_variance(&a[(height - dh) * a_stride], a_stride,
&b[(height - dh) * b_stride], b_stride,
width - dw, dh, &sse, &sum);
total_sse += sse;
}
for (y = 0; y < height / 16; ++y) {
const uint8_t *pa = a;
const uint8_t *pb = b;
for (x = 0; x < width / 16; ++x) {
vpx_mse16x16(pa, a_stride, pb, b_stride, &sse);
total_sse += sse;
pa += 16;
pb += 16;
}
a += 16 * a_stride;
b += 16 * b_stride;
}
return total_sse;
}
#if CONFIG_VP9_HIGHBITDEPTH
static int64_t highbd_get_sse_shift(const uint8_t *a8, int a_stride,
const uint8_t *b8, int b_stride,
int width, int height,
unsigned int input_shift) {
const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
int64_t total_sse = 0;
int x, y;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
int64_t diff;
diff = (a[x] >> input_shift) - (b[x] >> input_shift);
total_sse += diff * diff;
}
a += a_stride;
b += b_stride;
}
return total_sse;
}
static int64_t highbd_get_sse(const uint8_t *a, int a_stride,
const uint8_t *b, int b_stride,
int width, int height) {
int64_t total_sse = 0;
int x, y;
const int dw = width % 16;
const int dh = height % 16;
unsigned int sse = 0;
int sum = 0;
if (dw > 0) {
encoder_highbd_8_variance(&a[width - dw], a_stride,
&b[width - dw], b_stride,
dw, height, &sse, &sum);
total_sse += sse;
}
if (dh > 0) {
encoder_highbd_8_variance(&a[(height - dh) * a_stride], a_stride,
&b[(height - dh) * b_stride], b_stride,
width - dw, dh, &sse, &sum);
total_sse += sse;
}
for (y = 0; y < height / 16; ++y) {
const uint8_t *pa = a;
const uint8_t *pb = b;
for (x = 0; x < width / 16; ++x) {
vpx_highbd_8_mse16x16(pa, a_stride, pb, b_stride, &sse);
total_sse += sse;
pa += 16;
pb += 16;
}
a += 16 * a_stride;
b += 16 * b_stride;
}
return total_sse;
}
#endif // CONFIG_VP9_HIGHBITDEPTH
int64_t vpx_get_y_sse(const YV12_BUFFER_CONFIG *a,
const YV12_BUFFER_CONFIG *b) {
assert(a->y_crop_width == b->y_crop_width);
assert(a->y_crop_height == b->y_crop_height);
return get_sse(a->y_buffer, a->y_stride, b->y_buffer, b->y_stride,
a->y_crop_width, a->y_crop_height);
}
#if CONFIG_VP9_HIGHBITDEPTH
int64_t vpx_highbd_get_y_sse(const YV12_BUFFER_CONFIG *a,
const YV12_BUFFER_CONFIG *b) {
assert(a->y_crop_width == b->y_crop_width);
assert(a->y_crop_height == b->y_crop_height);
assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
return highbd_get_sse(a->y_buffer, a->y_stride, b->y_buffer, b->y_stride,
a->y_crop_width, a->y_crop_height);
}
#endif // CONFIG_VP9_HIGHBITDEPTH
#if CONFIG_VP9_HIGHBITDEPTH
void vpx_calc_highbd_psnr(const YV12_BUFFER_CONFIG *a,
const YV12_BUFFER_CONFIG *b,
PSNR_STATS *psnr, uint32_t bit_depth,
uint32_t in_bit_depth) {
const int widths[3] =
{ a->y_crop_width, a->uv_crop_width, a->uv_crop_width };
const int heights[3] =
{ a->y_crop_height, a->uv_crop_height, a->uv_crop_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;
const double peak = (double)((1 << in_bit_depth) - 1);
const unsigned int input_shift = bit_depth - in_bit_depth;
for (i = 0; i < 3; ++i) {