summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJingning Han <jingning@google.com>2015-08-11 22:21:38 -0700
committerJingning Han <jingning@google.com>2015-08-11 22:35:46 -0700
commit0a81d36ab4103c4baa37aaae3aa87ad94cc59ab3 (patch)
tree47ec88518027dbba70b094c8ce648c01415d7c5b
parent54d66ef165a86dd23ca4e5e645288f9ef63b7bb0 (diff)
downloadlibvpx-0a81d36ab4103c4baa37aaae3aa87ad94cc59ab3.tar
libvpx-0a81d36ab4103c4baa37aaae3aa87ad94cc59ab3.tar.gz
libvpx-0a81d36ab4103c4baa37aaae3aa87ad94cc59ab3.tar.bz2
libvpx-0a81d36ab4103c4baa37aaae3aa87ad94cc59ab3.zip
Replace vp10_ssim functions with vpx_ssim versions
Remove the ssim files from vp10 folder. Change-Id: Icc1d9d61a0878d53584328b278dfa090aa070035
-rw-r--r--vp10/common/vp10_rtcd_defs.pl19
-rw-r--r--vp10/encoder/blockiness.c8
-rw-r--r--vp10/encoder/encoder.c48
-rw-r--r--vp10/encoder/encoder.h13
-rw-r--r--vp10/encoder/fastssim.c465
-rw-r--r--vp10/encoder/psnrhvs.c224
-rw-r--r--vp10/encoder/ssim.c500
-rw-r--r--vp10/encoder/ssim.h96
-rw-r--r--vp10/vp10cx.mk5
9 files changed, 35 insertions, 1343 deletions
diff --git a/vp10/common/vp10_rtcd_defs.pl b/vp10/common/vp10_rtcd_defs.pl
index 6de3bb06b..37b962236 100644
--- a/vp10/common/vp10_rtcd_defs.pl
+++ b/vp10/common/vp10_rtcd_defs.pl
@@ -261,17 +261,6 @@ if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
specialize qw/vp10_fdct8x8_quant sse2 ssse3 neon/;
}
-#
-# Structured Similarity (SSIM)
-#
-if (vpx_config("CONFIG_INTERNAL_STATS") eq "yes") {
- add_proto qw/void vp10_ssim_parms_8x8/, "uint8_t *s, int sp, uint8_t *r, int rp, unsigned long *sum_s, unsigned long *sum_r, unsigned long *sum_sq_s, unsigned long *sum_sq_r, unsigned long *sum_sxr";
- specialize qw/vp10_ssim_parms_8x8/, "$sse2_x86_64";
-
- add_proto qw/void vp10_ssim_parms_16x16/, "uint8_t *s, int sp, uint8_t *r, int rp, unsigned long *sum_s, unsigned long *sum_r, unsigned long *sum_sq_s, unsigned long *sum_sq_r, unsigned long *sum_sxr";
- specialize qw/vp10_ssim_parms_16x16/, "$sse2_x86_64";
-}
-
# fdct functions
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
@@ -330,14 +319,6 @@ if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
add_proto qw/void vp10_highbd_quantize_fp_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_highbd_quantize_fp_32x32/;
- #
- # Structured Similarity (SSIM)
- #
- if (vpx_config("CONFIG_INTERNAL_STATS") eq "yes") {
- add_proto qw/void vp10_highbd_ssim_parms_8x8/, "uint16_t *s, int sp, uint16_t *r, int rp, uint32_t *sum_s, uint32_t *sum_r, uint32_t *sum_sq_s, uint32_t *sum_sq_r, uint32_t *sum_sxr";
- specialize qw/vp10_highbd_ssim_parms_8x8/;
- }
-
# fdct functions
add_proto qw/void vp10_highbd_fht4x4/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_highbd_fht4x4/;
diff --git a/vp10/encoder/blockiness.c b/vp10/encoder/blockiness.c
index da443486e..5c09b0b0f 100644
--- a/vp10/encoder/blockiness.c
+++ b/vp10/encoder/blockiness.c
@@ -54,8 +54,8 @@ static int variance(int sum, int sum_squared, int size) {
// var_1 = (r0^2+r1^2+r2^2+r3^2) - ((r0 + r1 + r2 + r3) / 4 )^2
// The returned blockiness is the scaled value
// Reconstructed blockiness / ( 1 + var_0 + var_1 ) ;
-int blockiness_vertical(const uint8_t *s, int sp, const uint8_t *r, int rp,
- int size) {
+static int blockiness_vertical(const uint8_t *s, int sp, const uint8_t *r,
+ int rp, int size) {
int s_blockiness = 0;
int r_blockiness = 0;
int sum_0 = 0;
@@ -86,8 +86,8 @@ int blockiness_vertical(const uint8_t *s, int sp, const uint8_t *r, int rp,
// Calculate a blockiness level for a horizontal block edge
// same as above.
-int blockiness_horizontal(const uint8_t *s, int sp, const uint8_t *r, int rp,
- int size) {
+static int blockiness_horizontal(const uint8_t *s, int sp, const uint8_t *r,
+ int rp, int size) {
int s_blockiness = 0;
int r_blockiness = 0;
int sum_0 = 0;
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index 358cd5a9d..46ece39cd 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -12,15 +12,7 @@
#include <stdio.h>
#include <limits.h>
-#include "./vp10_rtcd.h"
#include "./vpx_config.h"
-#include "./vpx_dsp_rtcd.h"
-#include "./vpx_scale_rtcd.h"
-#include "vpx/internal/vpx_psnr.h"
-#include "vpx_dsp/vpx_filter.h"
-#include "vpx_ports/mem.h"
-#include "vpx_ports/vpx_timer.h"
-#include "vpx_scale/vpx_scale.h"
#include "vp10/common/alloccommon.h"
#include "vp10/common/filter.h"
@@ -51,12 +43,21 @@
#include "vp10/encoder/segmentation.h"
#include "vp10/encoder/skin_detection.h"
#include "vp10/encoder/speed_features.h"
-#if CONFIG_INTERNAL_STATS
-#include "vp10/encoder/ssim.h"
-#endif
#include "vp10/encoder/svc_layercontext.h"
#include "vp10/encoder/temporal_filter.h"
+#include "./vp10_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "./vpx_scale_rtcd.h"
+#include "vpx/internal/vpx_psnr.h"
+#if CONFIG_INTERNAL_STATS
+#include "vpx_dsp/ssim.h"
+#endif
+#include "vpx_dsp/vpx_filter.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/vpx_timer.h"
+#include "vpx_scale/vpx_scale.h"
+
#define AM_SEGMENT_ID_INACTIVE 7
#define AM_SEGMENT_ID_ACTIVE 0
@@ -4416,13 +4417,13 @@ int vp10_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- frame_ssim2 = vp10_highbd_calc_ssim(orig, recon, &weight,
+ frame_ssim2 = vpx_highbd_calc_ssim(orig, recon, &weight,
(int)cm->bit_depth);
} else {
- frame_ssim2 = vp10_calc_ssim(orig, recon, &weight);
+ frame_ssim2 = vpx_calc_ssim(orig, recon, &weight);
}
#else
- frame_ssim2 = vp10_calc_ssim(orig, recon, &weight);
+ frame_ssim2 = vpx_calc_ssim(orig, recon, &weight);
#endif // CONFIG_VP9_HIGHBITDEPTH
cpi->worst_ssim= MIN(cpi->worst_ssim, frame_ssim2);
@@ -4431,13 +4432,13 @@ int vp10_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- frame_ssim2 = vp10_highbd_calc_ssim(
+ frame_ssim2 = vpx_highbd_calc_ssim(
orig, &cm->post_proc_buffer, &weight, (int)cm->bit_depth);
} else {
- frame_ssim2 = vp10_calc_ssim(orig, &cm->post_proc_buffer, &weight);
+ frame_ssim2 = vpx_calc_ssim(orig, &cm->post_proc_buffer, &weight);
}
#else
- frame_ssim2 = vp10_calc_ssim(orig, &cm->post_proc_buffer, &weight);
+ frame_ssim2 = vpx_calc_ssim(orig, &cm->post_proc_buffer, &weight);
#endif // CONFIG_VP9_HIGHBITDEPTH
cpi->summedp_quality += frame_ssim2 * weight;
@@ -4472,7 +4473,7 @@ int vp10_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
if (!cm->use_highbitdepth)
#endif
{
- double this_inconsistency = vp10_get_ssim_metrics(
+ double this_inconsistency = vpx_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,
@@ -4492,14 +4493,14 @@ int vp10_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
double y, u, v, frame_all;
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- frame_all = vp10_highbd_calc_ssimg(cpi->Source, cm->frame_to_show, &y,
+ frame_all = vpx_highbd_calc_ssimg(cpi->Source, cm->frame_to_show, &y,
&u, &v, (int)cm->bit_depth);
} else {
- frame_all = vp10_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u,
+ frame_all = vpx_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u,
&v);
}
#else
- frame_all = vp10_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
+ frame_all = vpx_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
#endif // CONFIG_VP9_HIGHBITDEPTH
adjust_image_stat(y, u, v, frame_all, &cpi->ssimg);
}
@@ -4508,7 +4509,7 @@ int vp10_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
#endif
{
double y, u, v, frame_all;
- frame_all = vp10_calc_fastssim(cpi->Source, cm->frame_to_show, &y, &u,
+ frame_all = vpx_calc_fastssim(cpi->Source, cm->frame_to_show, &y, &u,
&v);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
/* TODO(JBB): add 10/12 bit support */
@@ -4518,12 +4519,11 @@ int vp10_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
#endif
{
double y, u, v, frame_all;
- frame_all = vp10_psnrhvs(cpi->Source, cm->frame_to_show, &y, &u, &v);
+ frame_all = vpx_psnrhvs(cpi->Source, cm->frame_to_show, &y, &u, &v);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
}
-
#endif
if (is_two_pass_svc(cpi)) {
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index 53d930303..472ae8814 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -14,9 +14,7 @@
#include <stdio.h>
#include "./vpx_config.h"
-#include "vpx/internal/vpx_codec_internal.h"
#include "vpx/vp8cx.h"
-#include "vpx_util/vpx_thread.h"
#include "vp10/common/alloccommon.h"
#include "vp10/common/ppflags.h"
@@ -34,18 +32,21 @@
#include "vp10/encoder/quantize.h"
#include "vp10/encoder/ratectrl.h"
#include "vp10/encoder/rd.h"
-#if CONFIG_INTERNAL_STATS
-#include "vp10/encoder/ssim.h"
-#endif
#include "vp10/encoder/speed_features.h"
#include "vp10/encoder/svc_layercontext.h"
#include "vp10/encoder/tokenize.h"
-#include "vpx_dsp/variance.h"
#if CONFIG_VP9_TEMPORAL_DENOISING
#include "vp10/encoder/denoiser.h"
#endif
+#if CONFIG_INTERNAL_STATS
+#include "vpx_dsp/ssim.h"
+#endif
+#include "vpx_dsp/variance.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx_util/vpx_thread.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/vp10/encoder/fastssim.c b/vp10/encoder/fastssim.c
deleted file mode 100644
index 126250247..000000000
--- a/vp10/encoder/fastssim.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (c) 2010 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.
- *
- * This code was originally written by: Nathan E. Egge, at the Daala
- * project.
- */
-#include <math.h>
-#include <string.h>
-#include "./vpx_config.h"
-#include "./vp10_rtcd.h"
-#include "vp10/encoder/ssim.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)
-
-#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;
- double *ssim;
- int w;
- int h;
-};
-
-struct fs_ctx {
- fs_level *level;
- int nlevels;
- unsigned *col_buf;
-};
-
-static void fs_ctx_init(fs_ctx *_ctx, int _w, int _h, int _nlevels) {
- unsigned char *data;
- size_t data_size;
- int lw;
- int lh;
- int l;
- lw = (_w + 1) >> 1;
- lh = (_h + 1) >> 1;
- data_size = _nlevels * sizeof(fs_level)
- + 2 * (lw + 8) * 8 * sizeof(*_ctx->col_buf);
- for (l = 0; l < _nlevels; l++) {
- size_t im_size;
- size_t level_size;
- im_size = lw * (size_t) lh;
- level_size = 2 * im_size * sizeof(*_ctx->level[l].im1);
- level_size += sizeof(*_ctx->level[l].ssim) - 1;
- level_size /= sizeof(*_ctx->level[l].ssim);
- level_size += im_size;
- level_size *= sizeof(*_ctx->level[l].ssim);
- data_size += level_size;
- lw = (lw + 1) >> 1;
- lh = (lh + 1) >> 1;
- }
- data = (unsigned char *) malloc(data_size);
- _ctx->level = (fs_level *) data;
- _ctx->nlevels = _nlevels;
- data += _nlevels * sizeof(*_ctx->level);
- lw = (_w + 1) >> 1;
- lh = (_h + 1) >> 1;
- for (l = 0; l < _nlevels; l++) {
- size_t im_size;
- size_t level_size;
- _ctx->level[l].w = lw;
- _ctx->level[l].h = lh;
- im_size = lw * (size_t) lh;
- level_size = 2 * im_size * sizeof(*_ctx->level[l].im1);
- 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].im2 = _ctx->level[l].im1 + im_size;
- data += level_size;
- _ctx->level[l].ssim = (double *) data;
- data += im_size * sizeof(*_ctx->level[l].ssim);
- lw = (lw + 1) >> 1;
- lh = (lh + 1) >> 1;
- }
- _ctx->col_buf = (unsigned *) data;
-}
-
-static void fs_ctx_clear(fs_ctx *_ctx) {
- free(_ctx->level);
-}
-
-static void fs_downsample_level(fs_ctx *_ctx, int _l) {
- const uint16_t *src1;
- const uint16_t *src2;
- uint16_t *dst1;
- uint16_t *dst2;
- int w2;
- int h2;
- int w;
- int h;
- int i;
- int j;
- w = _ctx->level[_l].w;
- h = _ctx->level[_l].h;
- dst1 = _ctx->level[_l].im1;
- dst2 = _ctx->level[_l].im2;
- w2 = _ctx->level[_l - 1].w;
- h2 = _ctx->level[_l - 1].h;
- src1 = _ctx->level[_l - 1].im1;
- src2 = _ctx->level[_l - 1].im2;
- for (j = 0; j < h; j++) {
- int j0offs;
- int j1offs;
- j0offs = 2 * j * w2;
- j1offs = FS_MINI(2 * j + 1, h2) * w2;
- for (i = 0; i < w; i++) {
- int i0;
- int i1;
- i0 = 2 * i;
- i1 = FS_MINI(i0 + 1, w2);
- dst1[j * w + i] = src1[j0offs + i0] + src1[j0offs + i1]
- + src1[j1offs + i0] + src1[j1offs + i1];
- dst2[j * w + i] = src2[j0offs + i0] + src2[j0offs + i1]
- + src2[j1offs + i0] + src2[j1offs + i1];
- }
- }
-}
-
-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;
- 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];
- }
- }
-}
-
-static void fs_apply_luminance(fs_ctx *_ctx, int _l) {
- unsigned *col_sums_x;
- unsigned *col_sums_y;
- uint16_t *im1;
- uint16_t *im2;
- double *ssim;
- double c1;
- int w;
- int h;
- int j0offs;
- int j1offs;
- int i;
- int j;
- w = _ctx->level[_l].w;
- h = _ctx->level[_l].h;
- col_sums_x = _ctx->col_buf;
- col_sums_y = col_sums_x + w;
- im1 = _ctx->level[_l].im1;
- im2 = _ctx->level[_l].im2;
- for (i = 0; i < w; i++)
- col_sums_x[i] = 5 * im1[i];
- for (i = 0; i < w; i++)
- col_sums_y[i] = 5 * im2[i];
- for (j = 1; j < 4; j++) {
- j1offs = FS_MINI(j, h - 1) * w;
- for (i = 0; i < w; i++)
- col_sums_x[i] += im1[j1offs + i];
- for (i = 0; i < w; i++)
- col_sums_y[i] += im2[j1offs + i];
- }
- ssim = _ctx->level[_l].ssim;
- c1 = (double) (SSIM_C1 * 4096 * (1 << 4 * _l));
- for (j = 0; j < h; j++) {
- unsigned mux;
- unsigned muy;
- int i0;
- int i1;
- mux = 5 * col_sums_x[0];
- muy = 5 * col_sums_y[0];
- for (i = 1; i < 4; i++) {
- i1 = FS_MINI(i, w - 1);
- mux += col_sums_x[i1];
- muy += col_sums_y[i1];
- }
- for (i = 0; i < w; i++) {
- ssim[j * w + i] *= (2 * mux * (double) muy + c1)
- / (mux * (double) mux + muy * (double) muy + c1);
- if (i + 1 < w) {
- i0 = FS_MAXI(0, i - 4);
- i1 = FS_MINI(i + 4, w - 1);
- mux += col_sums_x[i1] - col_sums_x[i0];
- muy += col_sums_x[i1] - col_sums_x[i0];
- }
- }
- if (j + 1 < h) {
- j0offs = FS_MAXI(0, j - 4) * w;
- for (i = 0; i < w; i++)
- col_sums_x[i] -= im1[j0offs + i];
- for (i = 0; i < w; i++)
- col_sums_y[i] -= im2[j0offs + i];
- j1offs = FS_MINI(j + 4, h - 1) * w;
- for (i = 0; i < w; i++)
- col_sums_x[i] += im1[j1offs + i];
- for (i = 0; i < w; i++)
- col_sums_y[i] += im2[j1offs + i];
- }
- }
-}
-
-#define FS_COL_SET(_col, _joffs, _ioffs) \
- do { \
- unsigned gx; \
- unsigned gy; \
- gx = gx_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
- gy = gy_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
- col_sums_gx2[(_col)] = gx * (double)gx; \
- col_sums_gy2[(_col)] = gy * (double)gy; \
- col_sums_gxgy[(_col)] = gx * (double)gy; \
- } \
- while (0)
-
-#define FS_COL_ADD(_col, _joffs, _ioffs) \
- do { \
- unsigned gx; \
- unsigned gy; \
- gx = gx_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
- gy = gy_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
- col_sums_gx2[(_col)] += gx * (double)gx; \
- col_sums_gy2[(_col)] += gy * (double)gy; \
- col_sums_gxgy[(_col)] += gx * (double)gy; \
- } \
- while (0)
-
-#define FS_COL_SUB(_col, _joffs, _ioffs) \
- do { \
- unsigned gx; \
- unsigned gy; \
- gx = gx_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
- gy = gy_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
- col_sums_gx2[(_col)] -= gx * (double)gx; \
- col_sums_gy2[(_col)] -= gy * (double)gy; \
- col_sums_gxgy[(_col)] -= gx * (double)gy; \
- } \
- while (0)
-
-#define FS_COL_COPY(_col1, _col2) \
- do { \
- col_sums_gx2[(_col1)] = col_sums_gx2[(_col2)]; \
- col_sums_gy2[(_col1)] = col_sums_gy2[(_col2)]; \
- col_sums_gxgy[(_col1)] = col_sums_gxgy[(_col2)]; \
- } \
- while (0)
-
-#define FS_COL_HALVE(_col1, _col2) \
- do { \
- col_sums_gx2[(_col1)] = col_sums_gx2[(_col2)] * 0.5; \
- col_sums_gy2[(_col1)] = col_sums_gy2[(_col2)] * 0.5; \
- col_sums_gxgy[(_col1)] = col_sums_gxgy[(_col2)] * 0.5; \
- } \
- while (0)
-
-#define FS_COL_DOUBLE(_col1, _col2) \
- do { \
- col_sums_gx2[(_col1)] = col_sums_gx2[(_col2)] * 2; \
- col_sums_gy2[(_col1)] = col_sums_gy2[(_col2)] * 2; \
- col_sums_gxgy[(_col1)] = col_sums_gxgy[(_col2)] * 2; \
- } \
- while (0)
-
-static void fs_calc_structure(fs_ctx *_ctx, int _l) {
- uint16_t *im1;
- uint16_t *im2;
- unsigned *gx_buf;
- unsigned *gy_buf;
- double *ssim;
- double col_sums_gx2[8];
- double col_sums_gy2[8];
- double col_sums_gxgy[8];
- double c2;
- int stride;
- int w;
- int h;
- int i;
- int j;
- w = _ctx->level[_l].w;
- h = _ctx->level[_l].h;
- im1 = _ctx->level[_l].im1;
- im2 = _ctx->level[_l].im2;
- ssim = _ctx->level[_l].ssim;
- gx_buf = _ctx->col_buf;
- 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;
- for (j = 0; j < h + 4; j++) {
- if (j < h - 1) {
- for (i = 0; i < w - 1; i++) {
- unsigned g1;
- 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]);
- 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]);
- 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;
- }
- } else {
- memset(gx_buf + (j & 7) * stride, 0, stride * sizeof(*gx_buf));
- memset(gy_buf + (j & 7) * stride, 0, stride * sizeof(*gy_buf));
- }
- if (j >= 4) {
- int k;
- col_sums_gx2[3] = col_sums_gx2[2] = col_sums_gx2[1] = col_sums_gx2[0] = 0;
- col_sums_gy2[3] = col_sums_gy2[2] = col_sums_gy2[1] = col_sums_gy2[0] = 0;
- col_sums_gxgy[3] = col_sums_gxgy[2] = col_sums_gxgy[1] =
- col_sums_gxgy[0] = 0;
- for (i = 4; i < 8; i++) {
- FS_COL_SET(i, -1, 0);
- FS_COL_ADD(i, 0, 0);
- for (k = 1; k < 8 - i; k++) {
- FS_COL_DOUBLE(i, i);
- FS_COL_ADD(i, -k - 1, 0);
- FS_COL_ADD(i, k, 0);
- }
- }
- for (i = 0; i < w; i++) {
- double mugx2;
- double mugy2;
- double mugxgy;
- mugx2 = col_sums_gx2[0];
- for (k = 1; k < 8; k++)
- mugx2 += col_sums_gx2[k];
- mugy2 = col_sums_gy2[0];
- for (k = 1; k < 8; k++)
- mugy2 += col_sums_gy2[k];
- mugxgy = col_sums_gxgy[0];
- for (k = 1; k < 8; k++)
- mugxgy += col_sums_gxgy[k];
- ssim[(j - 4) * w + i] = (2 * mugxgy + c2) / (mugx2 + mugy2 + c2);
- if (i + 1 < w) {
- FS_COL_SET(0, -1, 1);
- FS_COL_ADD(0, 0, 1);
- FS_COL_SUB(2, -3, 2);
- FS_COL_SUB(2, 2, 2);
- FS_COL_HALVE(1, 2);
- FS_COL_SUB(3, -4, 3);
- FS_COL_SUB(3, 3, 3);
- FS_COL_HALVE(2, 3);
- FS_COL_COPY(3, 4);
- FS_COL_DOUBLE(4, 5);
- FS_COL_ADD(4, -4, 5);
- FS_COL_ADD(4, 3, 5);
- FS_COL_DOUBLE(5, 6);
- FS_COL_ADD(5, -3, 6);
- FS_COL_ADD(5, 2, 6);
- FS_COL_DOUBLE(6, 7);
- FS_COL_ADD(6, -2, 7);
- FS_COL_ADD(6, 1, 7);
- FS_COL_SET(7, -1, 8);
- FS_COL_ADD(7, 0, 8);
- }
- }
- }
- }
-}
-
-#define FS_NLEVELS (4)
-
-/*These weights were derived from the default weights found in Wang's original
- Matlab implementation: {0.0448, 0.2856, 0.2363, 0.1333}.
- We drop the finest scale and renormalize the rest to sum to 1.*/
-
-static const double FS_WEIGHTS[FS_NLEVELS] = {0.2989654541015625,
- 0.3141326904296875, 0.2473602294921875, 0.1395416259765625};
-
-static double fs_average(fs_ctx *_ctx, int _l) {
- double *ssim;
- double ret;
- int w;
- int h;
- int i;
- int j;
- w = _ctx->level[_l].w;
- h = _ctx->level[_l].h;
- ssim = _ctx->level[_l].ssim;
- ret = 0;
- for (j = 0; j < h; j++)
- for (i = 0; i < w; i++)
- ret += ssim[j * w + i];
- 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) {
- 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);
- ret *= fs_average(&ctx, l);
- fs_downsample_level(&ctx, l + 1);
- }
- fs_calc_structure(&ctx, l);
- fs_apply_luminance(&ctx, l);
- 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 vp10_calc_fastssim(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *ssim_y, double *ssim_u, double *ssim_v) {
- double ssimv;
- vpx_clear_system_state();
-
- *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);
- ssimv = (*ssim_y) * .8 + .1 * ((*ssim_u) + (*ssim_v));
-
- return convert_ssim_db(ssimv, 1.0);
-}
diff --git a/vp10/encoder/psnrhvs.c b/vp10/encoder/psnrhvs.c
deleted file mode 100644
index c91cbc19a..000000000
--- a/vp10/encoder/psnrhvs.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2010 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.
- *
- * This code was originally written by: Gregory Maxwell, at the Daala
- * project.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include "./vpx_config.h"
-#include "./vp10_rtcd.h"
-#include "./vpx_dsp_rtcd.h"
-#include "vp10/encoder/ssim.h"
-
-#if !defined(M_PI)
-# define M_PI (3.141592653589793238462643)
-#endif
-#include <string.h>
-
-void od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x, int xstride) {
- (void) xstride;
- vpx_fdct8x8(x, y, ystride);
-}
-
-/* Normalized inverse quantization matrix for 8x8 DCT at the point of
- * transparency. This is not the JPEG based matrix from the paper,
- this one gives a slightly higher MOS agreement.*/
-float csf_y[8][8] = {{1.6193873005, 2.2901594831, 2.08509755623, 1.48366094411,
- 1.00227514334, 0.678296995242, 0.466224900598, 0.3265091542}, {2.2901594831,
- 1.94321815382, 2.04793073064, 1.68731108984, 1.2305666963, 0.868920337363,
- 0.61280991668, 0.436405793551}, {2.08509755623, 2.04793073064,
- 1.34329019223, 1.09205635862, 0.875748795257, 0.670882927016,
- 0.501731932449, 0.372504254596}, {1.48366094411, 1.68731108984,
- 1.09205635862, 0.772819797575, 0.605636379554, 0.48309405692,
- 0.380429446972, 0.295774038565}, {1.00227514334, 1.2305666963,
- 0.875748795257, 0.605636379554, 0.448996256676, 0.352889268808,
- 0.283006984131, 0.226951348204}, {0.678296995242, 0.868920337363,
- 0.670882927016, 0.48309405692, 0.352889268808, 0.27032073436,
- 0.215017739696, 0.17408067321}, {0.466224900598, 0.61280991668,
- 0.501731932449, 0.380429446972, 0.283006984131, 0.215017739696,
- 0.168869545842, 0.136153931001}, {0.3265091542, 0.436405793551,
- 0.372504254596, 0.295774038565, 0.226951348204, 0.17408067321,
- 0.136153931001, 0.109083846276}};
-float csf_cb420[8][8] = {
- {1.91113096927, 2.46074210438, 1.18284184739, 1.14982565193, 1.05017074788,
- 0.898018824055, 0.74725392039, 0.615105596242}, {2.46074210438,
- 1.58529308355, 1.21363250036, 1.38190029285, 1.33100189972,
- 1.17428548929, 0.996404342439, 0.830890433625}, {1.18284184739,
- 1.21363250036, 0.978712413627, 1.02624506078, 1.03145147362,
- 0.960060382087, 0.849823426169, 0.731221236837}, {1.14982565193,
- 1.38190029285, 1.02624506078, 0.861317501629, 0.801821139099,
- 0.751437590932, 0.685398513368, 0.608694761374}, {1.05017074788,
- 1.33100189972, 1.03145147362, 0.801821139099, 0.676555426187,
- 0.605503172737, 0.55002013668, 0.495804539034}, {0.898018824055,
- 1.17428548929, 0.960060382087, 0.751437590932, 0.605503172737,
- 0.514674450957, 0.454353482512, 0.407050308965}, {0.74725392039,
- 0.996404342439, 0.849823426169, 0.685398513368, 0.55002013668,
- 0.454353482512, 0.389234902883, 0.342353999733}, {0.615105596242,
- 0.830890433625, 0.731221236837, 0.608694761374, 0.495804539034,
- 0.407050308965, 0.342353999733, 0.295530605237}};
-float csf_cr420[8][8] = {
- {2.03871978502, 2.62502345193, 1.26180942886, 1.11019789803, 1.01397751469,
- 0.867069376285, 0.721500455585, 0.593906509971}, {2.62502345193,
- 1.69112867013, 1.17180569821, 1.3342742857, 1.28513006198,
- 1.13381474809, 0.962064122248, 0.802254508198}, {1.26180942886,
- 1.17180569821, 0.944981930573, 0.990876405848, 0.995903384143,
- 0.926972725286, 0.820534991409, 0.706020324706}, {1.11019789803,
- 1.3342742857, 0.990876405848, 0.831632933426, 0.77418706195,
- 0.725539939514, 0.661776842059, 0.587716619023}, {1.01397751469,
- 1.28513006198, 0.995903384143, 0.77418706195, 0.653238524286,
- 0.584635025748, 0.531064164893, 0.478717061273}, {0.867069376285,
- 1.13381474809, 0.926972725286, 0.725539939514, 0.584635025748,
- 0.496936637883, 0.438694579826, 0.393021669543}, {0.721500455585,
- 0.962064122248, 0.820534991409, 0.661776842059, 0.531064164893,
- 0.438694579826, 0.375820256136, 0.330555063063}, {0.593906509971,
- 0.802254508198, 0.706020324706, 0.587716619023, 0.478717061273,
- 0.393021669543, 0.330555063063, 0.285345396658}};
-
-static double convert_score_db(double _score, double _weight) {
- return 10 * (log10(255 * 255) - log10(_weight * _score));
-}
-
-static double calc_psnrhvs(const unsigned char *_src, int _systride,
- const unsigned char *_dst, int _dystride,
- double _par, int _w, int _h, int _step,
- float _csf[8][8]) {
- float ret;
- int16_t dct_s[8 * 8], dct_d[8 * 8];
- tran_low_t dct_s_coef[8 * 8], dct_d_coef[8 * 8];
- float mask[8][8];
- int pixels;
- int x;
- int y;
- (void) _par;
- ret = pixels = 0;
- /*In the PSNR-HVS-M paper[1] the authors describe the construction of
- their masking table as "we have used the quantization table for the
- color component Y of JPEG [6] that has been also obtained on the
- basis of CSF. Note that the values in quantization table JPEG have
- been normalized and then squared." Their CSF matrix (from PSNR-HVS)
- was also constructed from the JPEG matrices. I can not find any obvious
- scheme of normalizing to produce their table, but if I multiply their
- CSF by 0.38857 and square the result I get their masking table.
- I have no idea where this constant comes from, but deviating from it
- too greatly hurts MOS agreement.
-
- [1] Nikolay Ponomarenko, Flavia Silvestri, Karen Egiazarian, Marco Carli,
- Jaakko Astola, Vladimir Lukin, "On between-coefficient contrast masking
- of DCT basis functions", CD-ROM Proceedings of the Third
- International Workshop on Video Processing and Quality Metrics for Consumer
- Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.*/
- for (x = 0; x < 8; x++)
- for (y = 0; y < 8; y++)
- mask[x][y] = (_csf[x][y] * 0.3885746225901003)
- * (_csf[x][y] * 0.3885746225901003);
- for (y = 0; y < _h - 7; y += _step) {
- for (x = 0; x < _w - 7; x += _step) {
- int i;
- int j;
- float s_means[4];
- float d_means[4];
- float s_vars[4];
- float d_vars[4];
- float s_gmean = 0;
- float d_gmean = 0;
- float s_gvar = 0;
- float d_gvar = 0;
- float s_mask = 0;
- float d_mask = 0;
- for (i = 0; i < 4; i++)
- s_means[i] = d_means[i] = s_vars[i] = d_vars[i] = 0;
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++) {
- int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
- dct_s[i * 8 + j] = _src[(y + i) * _systride + (j + x)];
- dct_d[i * 8 + j] = _dst[(y + i) * _dystride + (j + x)];
- s_gmean += dct_s[i * 8 + j];
- d_gmean += dct_d[i * 8 + j];
- s_means[sub] += dct_s[i * 8 + j];
- d_means[sub] += dct_d[i * 8 + j];
- }
- }
- s_gmean /= 64.f;
- d_gmean /= 64.f;
- for (i = 0; i < 4; i++)
- s_means[i] /= 16.f;
- for (i = 0; i < 4; i++)
- d_means[i] /= 16.f;
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++) {
- int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
- s_gvar += (dct_s[i * 8 + j] - s_gmean) * (dct_s[i * 8 + j] - s_gmean);
- d_gvar += (dct_d[i * 8 + j] - d_gmean) * (dct_d[i * 8 + j] - d_gmean);
- s_vars[sub] += (dct_s[i * 8 + j] - s_means[sub])
- * (dct_s[i * 8 + j] - s_means[sub]);
- d_vars[sub] += (dct_d[i * 8 + j] - d_means[sub])
- * (dct_d[i * 8 + j] - d_means[sub]);
- }
- }
- s_gvar *= 1 / 63.f * 64;
- d_gvar *= 1 / 63.f * 64;
- for (i = 0; i < 4; i++)
- s_vars[i] *= 1 / 15.f * 16;
- for (i = 0; i < 4; i++)
- d_vars[i] *= 1 / 15.f * 16;
- if (s_gvar > 0)
- s_gvar = (s_vars[0] + s_vars[1] + s_vars[2] + s_vars[3]) / s_gvar;
- if (d_gvar > 0)
- d_gvar = (d_vars[0] + d_vars[1] + d_vars[2] + d_vars[3]) / d_gvar;
- od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
- od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
- for (i = 0; i < 8; i++)
- for (j = (i == 0); j < 8; j++)
- s_mask += dct_s_coef[i * 8 + j] * dct_s_coef[i * 8 + j] * mask[i][j];
- for (i = 0; i < 8; i++)
- for (j = (i == 0); j < 8; j++)
- d_mask += dct_d_coef[i * 8 + j] * dct_d_coef[i * 8 + j] * mask[i][j];
- s_mask = sqrt(s_mask * s_gvar) / 32.f;
- d_mask = sqrt(d_mask * d_gvar) / 32.f;
- if (d_mask > s_mask)
- s_mask = d_mask;
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++) {
- float err;
- err = fabs(dct_s_coef[i * 8 + j] - dct_d_coef[i * 8 + j]);
- if (i != 0 || j != 0)
- err = err < s_mask / mask[i][j] ? 0 : err - s_mask / mask[i][j];
- ret += (err * _csf[i][j]) * (err * _csf[i][j]);
- pixels++;
- }
- }
- }
- }
- ret /= pixels;
- return ret;
-}
-double vp10_psnrhvs(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *y_psnrhvs, double *u_psnrhvs, double *v_psnrhvs) {
- double psnrhvs;
- double par = 1.0;
- int step = 7;
- vpx_clear_system_state();
- *y_psnrhvs = calc_psnrhvs(source->y_buffer, source->y_stride, dest->y_buffer,
- dest->y_stride, par, source->y_crop_width,
- source->y_crop_height, step, csf_y);
-
- *u_psnrhvs = calc_psnrhvs(source->u_buffer, source->uv_stride, dest->u_buffer,
- dest->uv_stride, par, source->uv_crop_width,
- source->uv_crop_height, step, csf_cb420);
-
- *v_psnrhvs = calc_psnrhvs(source->v_buffer, source->uv_stride, dest->v_buffer,
- dest->uv_stride, par, source->uv_crop_width,
- source->uv_crop_height, step, csf_cr420);
- psnrhvs = (*y_psnrhvs) * .8 + .1 * ((*u_psnrhvs) + (*v_psnrhvs));
-
- return convert_score_db(psnrhvs, 1.0);
-}
diff --git a/vp10/encoder/ssim.c b/vp10/encoder/ssim.c
deleted file mode 100644
index 0219621d6..000000000
--- a/vp10/encoder/ssim.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (c) 2010 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 "./vp10_rtcd.h"
-#include "vpx_ports/mem.h"
-#include "vp10/encoder/ssim.h"
-
-void vp10_ssim_parms_16x16_c(uint8_t *s, int sp, uint8_t *r,
- int rp, unsigned long *sum_s, unsigned long *sum_r,
- unsigned long *sum_sq_s, unsigned long *sum_sq_r,
- unsigned long *sum_sxr) {
- int i, j;
- for (i = 0; i < 16; i++, s += sp, r += rp) {
- for (j = 0; j < 16; j++) {
- *sum_s += s[j];
- *sum_r += r[j];
- *sum_sq_s += s[j] * s[j];
- *sum_sq_r += r[j] * r[j];
- *sum_sxr += s[j] * r[j];
- }
- }
-}
-void vp10_ssim_parms_8x8_c(uint8_t *s, int sp, uint8_t *r, int rp,
- unsigned long *sum_s, unsigned long *sum_r,
- unsigned long *sum_sq_s, unsigned long *sum_sq_r,
- unsigned long *sum_sxr) {
- int i, j;
- for (i = 0; i < 8; i++, s += sp, r += rp) {
- for (j = 0; j < 8; j++) {
- *sum_s += s[j];
- *sum_r += r[j];
- *sum_sq_s += s[j] * s[j];
- *sum_sq_r += r[j] * r[j];
- *sum_sxr += s[j] * r[j];
- }
- }
-}
-
-#if CONFIG_VP9_HIGHBITDEPTH
-void vp10_highbd_ssim_parms_8x8_c(uint16_t *s, int sp, uint16_t *r, int rp,
- uint32_t *sum_s, uint32_t *sum_r,
- uint32_t *sum_sq_s, uint32_t *sum_sq_r,
- uint32_t *sum_sxr) {
- int i, j;
- for (i = 0; i < 8; i++, s += sp, r += rp) {
- for (j = 0; j < 8; j++) {
- *sum_s += s[j];
- *sum_r += r[j];
- *sum_sq_s += s[j] * s[j];
- *sum_sq_r += r[j] * r[j];
- *sum_sxr += s[j] * r[j];
- }
- }
-}
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
-static const int64_t cc1 = 26634; // (64^2*(.01*255)^2
-static const int64_t cc2 = 239708; // (64^2*(.03*255)^2
-
-static double similarity(unsigned long sum_s, unsigned long sum_r,
- unsigned long sum_sq_s, unsigned long sum_sq_r,
- unsigned long sum_sxr, int count) {
- int64_t ssim_n, ssim_d;
- int64_t c1, c2;
-
- // scale the constants by number of pixels
- c1 = (cc1 * count * count) >> 12;
- c2 = (cc2 * count * count) >> 12;
-
- ssim_n = (2 * sum_s * sum_r + c1) * ((int64_t) 2 * count * sum_sxr -
- (int64_t) 2 * sum_s * sum_r + c2);
-
- ssim_d = (sum_s * sum_s + sum_r * sum_r + c1) *
- ((int64_t)count * sum_sq_s - (int64_t)sum_s * sum_s +
- (int64_t)count * sum_sq_r - (int64_t) sum_r * sum_r + c2);
-
- return ssim_n * 1.0 / ssim_d;
-}
-
-static double ssim_8x8(uint8_t *s, int sp, uint8_t *r, int rp) {
- unsigned long sum_s = 0, sum_r = 0, sum_sq_s = 0, sum_sq_r = 0, sum_sxr = 0;
- vp10_ssim_parms_8x8(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r,
- &sum_sxr);
- return similarity(sum_s, sum_r, sum_sq_s, sum_sq_r, sum_sxr, 64);
-}
-
-#if CONFIG_VP9_HIGHBITDEPTH
-static double highbd_ssim_8x8(uint16_t *s, int sp, uint16_t *r, int rp,
- unsigned int bd) {
- uint32_t sum_s = 0, sum_r = 0, sum_sq_s = 0, sum_sq_r = 0, sum_sxr = 0;
- const int oshift = bd - 8;
- vp10_highbd_ssim_parms_8x8(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r,
- &sum_sxr);
- return similarity(sum_s >> oshift,
- sum_r >> oshift,
- sum_sq_s >> (2 * oshift),
- sum_sq_r >> (2 * oshift),
- sum_sxr >> (2 * oshift),
- 64);
-}
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
-// We are using a 8x8 moving window with starting location of each 8x8 window
-// on the 4x4 pixel grid. Such arrangement allows the windows to overlap
-// block boundaries to penalize blocking artifacts.
-double vp10_ssim2(uint8_t *img1, uint8_t *img2, int stride_img1,
- int stride_img2, int width, int height) {
- int i, j;
- int samples = 0;
- double ssim_total = 0;
-
- // sample point start with each 4x4 location
- for (i = 0; i <= height - 8;
- i += 4, img1 += stride_img1 * 4, img2 += stride_img2 * 4) {
- for (j = 0; j <= width - 8; j += 4) {
- double v = ssim_8x8(img1 + j, stride_img1, img2 + j, stride_img2);
- ssim_total += v;
- samples++;
- }
- }
- ssim_total /= samples;
- return ssim_total;
-}
-
-#if CONFIG_VP9_HIGHBITDEPTH
-double vp10_highbd_ssim2(uint8_t *img1, uint8_t *img2, int stride_img1,
- int stride_img2, int width, int height,
- unsigned int bd) {
- int i, j;
- int samples = 0;
- double ssim_total = 0;
-
- // sample point start with each 4x4 location
- for (i = 0; i <= height - 8;
- i += 4, img1 += stride_img1 * 4, img2 += stride_img2 * 4) {
- for (j = 0; j <= width - 8; j += 4) {
- double v = highbd_ssim_8x8(CONVERT_TO_SHORTPTR(img1 + j), stride_img1,
- CONVERT_TO_SHORTPTR(img2 + j), stride_img2,
- bd);
- ssim_total += v;
- samples++;
- }
- }
- ssim_total /= samples;
- return ssim_total;
-}
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
-double vp10_calc_ssim(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *weight) {
- double a, b, c;
- double ssimv;
-
- a = vp10_ssim2(source->y_buffer, dest->y_buffer,
- source->y_stride, dest->y_stride,
- source->y_crop_width, source->y_crop_height);
-
- b = vp10_ssim2(source->u_buffer, dest->u_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height);
-
- c = vp10_ssim2(source->v_buffer, dest->v_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height);
-
- ssimv = a * .8 + .1 * (b + c);
-
- *weight = 1;
-
- return ssimv;
-}
-
-double vp10_calc_ssimg(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *ssim_y, double *ssim_u, double *ssim_v) {
- double ssim_all = 0;
- double a, b, c;
-
- a = vp10_ssim2(source->y_buffer, dest->y_buffer,
- source->y_stride, dest->y_stride,
- source->y_crop_width, source->y_crop_height);
-
- b = vp10_ssim2(source->u_buffer, dest->u_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height);
-
- c = vp10_ssim2(source->v_buffer, dest->v_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height);
- *ssim_y = a;
- *ssim_u = b;
- *ssim_v = c;
- ssim_all = (a * 4 + b + c) / 6;
-
- return ssim_all;
-}
-
-// traditional ssim as per: http://en.wikipedia.org/wiki/Structural_similarity
-//
-// Re working out the math ->
-//
-// ssim(x,y) = (2*mean(x)*mean(y) + c1)*(2*cov(x,y)+c2) /
-// ((mean(x)^2+mean(y)^2+c1)*(var(x)+var(y)+c2))
-//
-// mean(x) = sum(x) / n
-//
-// cov(x,y) = (n*sum(xi*yi)-sum(x)*sum(y))/(n*n)
-//
-// var(x) = (n*sum(xi*xi)-sum(xi)*sum(xi))/(n*n)
-//
-// ssim(x,y) =
-// (2*sum(x)*sum(y)/(n*n) + c1)*(2*(n*sum(xi*yi)-sum(x)*sum(y))/(n*n)+c2) /
-// (((sum(x)*sum(x)+sum(y)*sum(y))/(n*n) +c1) *
-// ((n*sum(xi*xi) - sum(xi)*sum(xi))/(n*n)+
-// (n*sum(yi*yi) - sum(yi)*sum(yi))/(n*n)+c2)))
-//
-// factoring out n*n
-//
-// ssim(x,y) =
-// (2*sum(x)*sum(y) + n*n*c1)*(2*(n*sum(xi*yi)-sum(x)*sum(y))+n*n*c2) /
-// (((sum(x)*sum(x)+sum(y)*sum(y)) + n*n*c1) *
-// (n*sum(xi*xi)-sum(xi)*sum(xi)+n*sum(yi*yi)-sum(yi)*sum(yi)+n*n*c2))
-//
-// Replace c1 with n*n * c1 for the final step that leads to this code:
-// The final step scales by 12 bits so we don't lose precision in the constants.
-
-double ssimv_similarity(Ssimv *sv, int64_t n) {
- // Scale the constants by number of pixels.
- const int64_t c1 = (cc1 * n * n) >> 12;
- const int64_t c2 = (cc2 * n * n) >> 12;
-
- const double l = 1.0 * (2 * sv->sum_s * sv->sum_r + c1) /
- (sv->sum_s * sv->sum_s + sv->sum_r * sv->sum_r + c1);
-
- // Since these variables are unsigned sums, convert to double so
- // math is done in double arithmetic.
- const double v = (2.0 * n * sv->sum_sxr - 2 * sv->sum_s * sv->sum_r + c2)
- / (n * sv->sum_sq_s - sv->sum_s * sv->sum_s + n * sv->sum_sq_r
- - sv->sum_r * sv->sum_r + c2);
-
- return l * v;
-}
-
-// The first term of the ssim metric is a luminance factor.
-//
-// (2*mean(x)*mean(y) + c1)/ (mean(x)^2+mean(y)^2+c1)
-//
-// This luminance factor is super sensitive to the dark side of luminance
-// values and completely insensitive on the white side. check out 2 sets
-// (1,3) and (250,252) the term gives ( 2*1*3/(1+9) = .60
-// 2*250*252/ (250^2+252^2) => .99999997
-//
-// As a result in this tweaked version of the calculation in which the
-// luminance is taken as percentage off from peak possible.
-//
-// 255 * 255 - (sum_s - sum_r) / count * (sum_s - sum_r) / count
-//
-double ssimv_similarity2(Ssimv *sv, int64_t n) {
- // Scale the constants by number of pixels.
- const int64_t c1 = (cc1 * n * n) >> 12;
- const int64_t c2 = (cc2 * n * n) >> 12;
-
- const double mean_diff = (1.0 * sv->sum_s - sv->sum_r) / n;
- const double l = (255 * 255 - mean_diff * mean_diff + c1) / (255 * 255 + c1);
-
- // Since these variables are unsigned, sums convert to double so
- // math is done in double arithmetic.
- const double v = (2.0 * n * sv->sum_sxr - 2 * sv->sum_s * sv->sum_r + c2)
- / (n * sv->sum_sq_s - sv->sum_s * sv->sum_s +
- n * sv->sum_sq_r - sv->sum_r * sv->sum_r + c2);
-
- return l * v;
-}
-void ssimv_parms(uint8_t *img1, int img1_pitch, uint8_t *img2, int img2_pitch,
- Ssimv *sv) {
- vp10_ssim_parms_8x8(img1, img1_pitch, img2, img2_pitch,
- &sv->sum_s, &sv->sum_r, &sv->sum_sq_s, &sv->sum_sq_r,
- &sv->sum_sxr);
-}
-
-double vp10_get_ssim_metrics(uint8_t *img1, int img1_pitch,
- uint8_t *img2, int img2_pitch,
- int width, int height,
- Ssimv *sv2, Metrics *m,
- int do_inconsistency) {
- double dssim_total = 0;
- double ssim_total = 0;
- double ssim2_total = 0;
- double inconsistency_total = 0;
- int i, j;
- int c = 0;
- double norm;
- double old_ssim_total = 0;
- vpx_clear_system_state();
- // We can sample points as frequently as we like start with 1 per 4x4.
- for (i = 0; i < height; i += 4,
- img1 += img1_pitch * 4, img2 += img2_pitch * 4) {
- for (j = 0; j < width; j += 4, ++c) {
- Ssimv sv = {0};
- double ssim;
- double ssim2;
- double dssim;
- uint32_t var_new;
- uint32_t var_old;
- uint32_t mean_new;
- uint32_t mean_old;
- double ssim_new;
- double ssim_old;
-
- // Not sure there's a great way to handle the edge pixels
- // in ssim when using a window. Seems biased against edge pixels
- // however you handle this. This uses only samples that are
- // fully in the frame.
- if (j + 8 <= width && i + 8 <= height) {
- ssimv_parms(img1 + j, img1_pitch, img2 + j, img2_pitch, &sv);
- }
-
- ssim = ssimv_similarity(&sv, 64);
- ssim2 = ssimv_similarity2(&sv, 64);
-
- sv.ssim = ssim2;
-
- // dssim is calculated to use as an actual error metric and
- // is scaled up to the same range as sum square error.
- // Since we are subsampling every 16th point maybe this should be
- // *16 ?
- dssim = 255 * 255 * (1 - ssim2) / 2;
-
- // Here I introduce a new error metric: consistency-weighted
- // SSIM-inconsistency. This metric isolates frames where the
- // SSIM 'suddenly' changes, e.g. if one frame in every 8 is much
- // sharper or blurrier than the others. Higher values indicate a
- // temporally inconsistent SSIM. There are two ideas at work:
- //
- // 1) 'SSIM-inconsistency': the total inconsistency value
- // reflects how much SSIM values are changing between this
- // source / reference frame pair and the previous pair.
- //
- // 2) 'consistency-weighted': weights de-emphasize areas in the
- // frame where the scene content has changed. Changes in scene
- // content are detected via changes in local variance and local
- // mean.
- //
- // Thus the overall measure reflects how inconsistent the SSIM
- // values are, over consistent regions of the frame.
- //
- // The metric has three terms:
- //
- // term 1 -> uses change in scene Variance to weight error score
- // 2 * var(Fi)*var(Fi-1) / (var(Fi)^2+var(Fi-1)^2)
- // larger changes from one frame to the next mean we care
- // less about consistency.
- //
- // term 2 -> uses change in local scene luminance to weight error
- // 2 * avg(Fi)*avg(Fi-1) / (avg(Fi)^2+avg(Fi-1)^2)
- // larger changes from one frame to the next mean we care
- // less about consistency.
- //
- // term3 -> measures inconsistency in ssim scores between frames
- // 1 - ( 2 * ssim(Fi)*ssim(Fi-1)/(ssim(Fi)^2+sssim(Fi-1)^2).
- //
- // This term compares the ssim score for the same location in 2
- // subsequent frames.
- var_new = sv.sum_sq_s - sv.sum_s * sv.sum_s / 64;
- var_old = sv2[c].sum_sq_s - sv2[c].sum_s * sv2[c].sum_s / 64;
- mean_new = sv.sum_s;
- mean_old = sv2[c].sum_s;
- ssim_new = sv.ssim;
- ssim_old = sv2[c].ssim;
-
- if (do_inconsistency) {
- // We do the metric once for every 4x4 block in the image. Since
- // we are scaling the error to SSE for use in a psnr calculation
- // 1.0 = 4x4x255x255 the worst error we can possibly have.
- static const double kScaling = 4. * 4 * 255 * 255;
-
- // The constants have to be non 0 to avoid potential divide by 0
- // issues other than that they affect kind of a weighting between
- // the terms. No testing of what the right terms should be has been
- // done.
- static const double c1 = 1, c2 = 1, c3 = 1;
-
- // This measures how much consistent variance is in two consecutive
- // source frames. 1.0 means they have exactly the same variance.
- const double variance_term = (2.0 * var_old * var_new + c1) /
- (1.0 * var_old * var_old + 1.0 * var_new * var_new + c1);
-
- // This measures how consistent the local mean are between two
- // consecutive frames. 1.0 means they have exactly the same mean.
- const double mean_term = (2.0 * mean_old * mean_new + c2) /
- (1.0 * mean_old * mean_old + 1.0 * mean_new * mean_new + c2);
-
- // This measures how consistent the ssims of two
- // consecutive frames is. 1.0 means they are exactly the same.
- double ssim_term = pow((2.0 * ssim_old * ssim_new + c3) /
- (ssim_old * ssim_old + ssim_new * ssim_new + c3),
- 5);
-
- double this_inconsistency;
-
- // Floating point math sometimes makes this > 1 by a tiny bit.
- // We want the metric to scale between 0 and 1.0 so we can convert
- // it to an snr scaled value.
- if (ssim_term > 1)
- ssim_term = 1;
-
- // This converts the consistency metric to an inconsistency metric
- // ( so we can scale it like psnr to something like sum square error.
- // The reason for the variance and mean terms is the assumption that
- // if there are big changes in the source we shouldn't penalize
- // inconsistency in ssim scores a bit less as it will be less visible
- // to the user.
- this_inconsistency = (1 - ssim_term) * variance_term * mean_term;
-
- this_inconsistency *= kScaling;
- inconsistency_total += this_inconsistency;
- }
- sv2[c] = sv;
- ssim_total += ssim;
- ssim2_total += ssim2;
- dssim_total += dssim;
-
- old_ssim_total += ssim_old;
- }
- old_ssim_total += 0;
- }
-
- norm = 1. / (width / 4) / (height / 4);
- ssim_total *= norm;
- ssim2_total *= norm;
- m->ssim2 = ssim2_total;
- m->ssim = ssim_total;
- if (old_ssim_total == 0)
- inconsistency_total = 0;
-
- m->ssimc = inconsistency_total;
-
- m->dssim = dssim_total;
- return inconsistency_total;
-}
-
-
-#if CONFIG_VP9_HIGHBITDEPTH
-double vp10_highbd_calc_ssim(YV12_BUFFER_CONFIG *source,
- YV12_BUFFER_CONFIG *dest,
- double *weight, unsigned int bd) {
- double a, b, c;
- double ssimv;
-
- a = vp10_highbd_ssim2(source->y_buffer, dest->y_buffer,
- source->y_stride, dest->y_stride,
- source->y_crop_width, source->y_crop_height, bd);
-
- b = vp10_highbd_ssim2(source->u_buffer, dest->u_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height, bd);
-
- c = vp10_highbd_ssim2(source->v_buffer, dest->v_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height, bd);
-
- ssimv = a * .8 + .1 * (b + c);
-
- *weight = 1;
-
- return ssimv;
-}
-
-double vp10_highbd_calc_ssimg(YV12_BUFFER_CONFIG *source,
- YV12_BUFFER_CONFIG *dest, double *ssim_y,
- double *ssim_u, double *ssim_v, unsigned int bd) {
- double ssim_all = 0;
- double a, b, c;
-
- a = vp10_highbd_ssim2(source->y_buffer, dest->y_buffer,
- source->y_stride, dest->y_stride,
- source->y_crop_width, source->y_crop_height, bd);
-
- b = vp10_highbd_ssim2(source->u_buffer, dest->u_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height, bd);
-
- c = vp10_highbd_ssim2(source->v_buffer, dest->v_buffer,
- source->uv_stride, dest->uv_stride,
- source->uv_crop_width, source->uv_crop_height, bd);
- *ssim_y = a;
- *ssim_u = b;
- *ssim_v = c;
- ssim_all = (a * 4 + b + c) / 6;
-
- return ssim_all;
-}
-#endif // CONFIG_VP9_HIGHBITDEPTH
diff --git a/vp10/encoder/ssim.h b/vp10/encoder/ssim.h
deleted file mode 100644
index ca0551a94..000000000
--- a/vp10/encoder/ssim.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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 VP9_ENCODER_VP9_SSIM_H_
-#define VP9_ENCODER_VP9_SSIM_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vpx_scale/yv12config.h"
-
-// metrics used for calculating ssim, ssim2, dssim, and ssimc
-typedef struct {
- // source sum ( over 8x8 region )
- uint64_t sum_s;
-
- // reference sum (over 8x8 region )
- uint64_t sum_r;
-
- // source sum squared ( over 8x8 region )
- uint64_t sum_sq_s;
-
- // reference sum squared (over 8x8 region )
- uint64_t sum_sq_r;
-
- // sum of source times reference (over 8x8 region)
- uint64_t sum_sxr;
-
- // calculated ssim score between source and reference
- double ssim;
-} Ssimv;
-
-// metrics collected on a frame basis
-typedef struct {
- // ssim consistency error metric ( see code for explanation )
- double ssimc;
-
- // standard ssim
- double ssim;
-
- // revised ssim ( see code for explanation)
- double ssim2;
-
- // ssim restated as an error metric like sse
- double dssim;
-
- // dssim converted to decibels
- double dssimd;
-
- // ssimc converted to decibels
- double ssimcd;
-} Metrics;
-
-double vp10_get_ssim_metrics(uint8_t *img1, int img1_pitch, uint8_t *img2,
- int img2_pitch, int width, int height, Ssimv *sv2,
- Metrics *m, int do_inconsistency);
-
-double vp10_calc_ssim(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *weight);
-
-double vp10_calc_ssimg(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *ssim_y, double *ssim_u, double *ssim_v);
-
-double vp10_calc_fastssim(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *ssim_y, double *ssim_u, double *ssim_v);
-
-double vp10_psnrhvs(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest,
- double *ssim_y, double *ssim_u, double *ssim_v);
-
-#if CONFIG_VP9_HIGHBITDEPTH
-double vp10_highbd_calc_ssim(YV12_BUFFER_CONFIG *source,
- YV12_BUFFER_CONFIG *dest,
- double *weight,
- unsigned int bd);
-
-double vp10_highbd_calc_ssimg(YV12_BUFFER_CONFIG *source,
- YV12_BUFFER_CONFIG *dest,
- double *ssim_y,
- double *ssim_u,
- double *ssim_v,
- unsigned int bd);
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VP9_ENCODER_VP9_SSIM_H_
diff --git a/vp10/vp10cx.mk b/vp10/vp10cx.mk
index d6846b257..283b7053d 100644
--- a/vp10/vp10cx.mk
+++ b/vp10/vp10cx.mk
@@ -33,7 +33,6 @@ VP10_CX_SRCS-yes += encoder/encodemv.c
VP10_CX_SRCS-yes += encoder/ethread.h
VP10_CX_SRCS-yes += encoder/ethread.c
VP10_CX_SRCS-yes += encoder/extend.c
-VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/fastssim.c
VP10_CX_SRCS-yes += encoder/firstpass.c
VP10_CX_SRCS-yes += encoder/block.h
VP10_CX_SRCS-yes += encoder/bitstream.h
@@ -57,7 +56,6 @@ VP10_CX_SRCS-yes += encoder/mcomp.c
VP10_CX_SRCS-yes += encoder/encoder.c
VP10_CX_SRCS-yes += encoder/picklpf.c
VP10_CX_SRCS-yes += encoder/picklpf.h
-VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/psnrhvs.c
VP10_CX_SRCS-yes += encoder/quantize.c
VP10_CX_SRCS-yes += encoder/ratectrl.c
VP10_CX_SRCS-yes += encoder/rd.c
@@ -72,8 +70,6 @@ VP10_CX_SRCS-yes += encoder/subexp.h
VP10_CX_SRCS-yes += encoder/svc_layercontext.c
VP10_CX_SRCS-yes += encoder/resize.c
VP10_CX_SRCS-yes += encoder/resize.h
-VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/ssim.c
-VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/ssim.h
VP10_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/blockiness.c
VP10_CX_SRCS-yes += encoder/tokenize.c
@@ -113,7 +109,6 @@ VP10_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/quantize_ssse3_x86_64.asm
VP10_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/dct_ssse3_x86_64.asm
endif
endif
-VP10_CX_SRCS-$(ARCH_X86_64) += encoder/x86/ssim_opt_x86_64.asm
VP10_CX_SRCS-$(HAVE_SSE2) += encoder/x86/dct_sse2.c
VP10_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/dct_ssse3.c