Merge "Optimizing obmc rd decision by checking the real rd cost" into nextgenv2
diff --git a/test/hbd_metrics_test.cc b/test/hbd_metrics_test.cc
index bf75a29..048c3de 100644
--- a/test/hbd_metrics_test.cc
+++ b/test/hbd_metrics_test.cc
@@ -16,6 +16,7 @@
#include "test/acm_random.h"
#include "test/util.h"
#include "./vpx_config.h"
+#include "vpx_dsp/psnr.h"
#include "vpx_dsp/ssim.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/msvc.h"
@@ -30,44 +31,58 @@
const YV12_BUFFER_CONFIG *dest);
typedef double (*HBDMetricFunc)(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
- uint32_t bd);
+ uint32_t in_bd, uint32_t bd);
+double compute_hbd_psnr(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest,
+ uint32_t in_bd, uint32_t bd) {
+ PSNR_STATS psnr;
+ vpx_calc_highbd_psnr(source, dest, &psnr, bd, in_bd);
+ return psnr.psnr[0];
+}
+
+double compute_psnr(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest) {
+ PSNR_STATS psnr;
+ vpx_calc_psnr(source, dest, &psnr);
+ return psnr.psnr[0];
+}
double compute_hbd_psnrhvs(const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *dest,
- uint32_t bit_depth) {
+ const YV12_BUFFER_CONFIG *dest,
+ uint32_t in_bd, uint32_t bd) {
double tempy, tempu, tempv;
return vpx_psnrhvs(source, dest,
- &tempy, &tempu, &tempv, bit_depth);
+ &tempy, &tempu, &tempv, bd, in_bd);
}
double compute_psnrhvs(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest) {
double tempy, tempu, tempv;
return vpx_psnrhvs(source, dest,
- &tempy, &tempu, &tempv, 8);
+ &tempy, &tempu, &tempv, 8, 8);
}
double compute_hbd_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
- uint32_t bit_depth) {
+ uint32_t in_bd, uint32_t bd) {
double tempy, tempu, tempv;
return vpx_calc_fastssim(source, dest,
- &tempy, &tempu, &tempv, bit_depth);
+ &tempy, &tempu, &tempv, bd, in_bd);
}
double compute_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest) {
double tempy, tempu, tempv;
return vpx_calc_fastssim(source, dest,
- &tempy, &tempu, &tempv, 8);
+ &tempy, &tempu, &tempv, 8, 8);
}
double compute_hbd_vpxssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
- uint32_t bit_depth) {
+ uint32_t in_bd, uint32_t bd) {
double ssim, weight;
- ssim = vpx_highbd_calc_ssim(source, dest, &weight, bit_depth);
+ ssim = vpx_highbd_calc_ssim(source, dest, &weight, bd);
return 100 * pow(ssim / weight, 8.0);
}
@@ -117,7 +132,7 @@
}
lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
- hbd_db = hbd_metric_(&hbd_src, &hbd_dst, bit_depth_);
+ hbd_db = hbd_metric_(&hbd_src, &hbd_dst, input_bit_depth_, bit_depth_);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
i = 0;
@@ -131,7 +146,7 @@
}
lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
- hbd_db = hbd_metric_(&hbd_src, &hbd_dst, bit_depth_);
+ hbd_db = hbd_metric_(&hbd_src, &hbd_dst, input_bit_depth_, bit_depth_);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
i = 0;
@@ -145,7 +160,7 @@
}
lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
- hbd_db = hbd_metric_(&hbd_src, &hbd_dst, bit_depth_);
+ hbd_db = hbd_metric_(&hbd_src, &hbd_dst, input_bit_depth_, bit_depth_);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
vpx_free_frame_buffer(&lbd_src);
@@ -154,6 +169,7 @@
vpx_free_frame_buffer(&hbd_dst);
}
+ int input_bit_depth_;
int bit_depth_;
double threshold_;
LBDMetricFunc lbd_metric_;
@@ -161,7 +177,7 @@
};
typedef std::tr1::tuple<LBDMetricFunc,
- HBDMetricFunc, int, double> MetricTestTParam;
+ HBDMetricFunc, int, int, double> MetricTestTParam;
class HBDMetricsTest
: public HBDMetricsTestBase,
public ::testing::TestWithParam<MetricTestTParam> {
@@ -169,8 +185,9 @@
virtual void SetUp() {
lbd_metric_ = GET_PARAM(0);
hbd_metric_ = GET_PARAM(1);
- bit_depth_ = GET_PARAM(2);
- threshold_ = GET_PARAM(3);
+ input_bit_depth_ = GET_PARAM(2);
+ bit_depth_ = GET_PARAM(3);
+ threshold_ = GET_PARAM(4);
}
virtual void TearDown() {}
};
@@ -189,24 +206,46 @@
INSTANTIATE_TEST_CASE_P(
VPXSSIM, HBDMetricsTest,
::testing::Values(
- MetricTestTParam(&compute_vpxssim, &compute_hbd_vpxssim, 10,
+ MetricTestTParam(&compute_vpxssim, &compute_hbd_vpxssim, 8, 10,
kSsim_thresh),
- MetricTestTParam(&compute_vpxssim, &compute_hbd_vpxssim, 12,
+ MetricTestTParam(&compute_vpxssim, &compute_hbd_vpxssim, 10, 10,
+ kSsim_thresh),
+ MetricTestTParam(&compute_vpxssim, &compute_hbd_vpxssim, 8, 12,
+ kSsim_thresh),
+ MetricTestTParam(&compute_vpxssim, &compute_hbd_vpxssim, 12, 12,
kSsim_thresh)));
INSTANTIATE_TEST_CASE_P(
FASTSSIM, HBDMetricsTest,
::testing::Values(
- MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 10,
+ MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 8, 10,
kFSsim_thresh),
- MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 12,
+ MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 10, 10,
+ kFSsim_thresh),
+ MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 8, 12,
+ kFSsim_thresh),
+ MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 12, 12,
kFSsim_thresh)));
INSTANTIATE_TEST_CASE_P(
PSNRHVS, HBDMetricsTest,
::testing::Values(
- MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 10,
+ MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 8, 10,
kPhvs_thresh),
- MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 12,
+ MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 10, 10,
+ kPhvs_thresh),
+ MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 8, 12,
+ kPhvs_thresh),
+ MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 12, 12,
kPhvs_thresh)));
-
+INSTANTIATE_TEST_CASE_P(
+ PSNR, HBDMetricsTest,
+ ::testing::Values(
+ MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 8, 10,
+ kPhvs_thresh),
+ MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 10, 10,
+ kPhvs_thresh),
+ MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 8, 12,
+ kPhvs_thresh),
+ MetricTestTParam(&compute_psnr, &compute_hbd_psnr, 12, 12,
+ kPhvs_thresh)));
} // namespace
diff --git a/test/vp10_convolve_test.cc b/test/vp10_convolve_test.cc
index eea7068..af34ffc 100644
--- a/test/vp10_convolve_test.cc
+++ b/test/vp10_convolve_test.cc
@@ -60,38 +60,42 @@
int dst_stride = 1;
int x_step_q4 = 16;
int y_step_q4 = 16;
- int subpel_x_q4 = 3;
- int subpel_y_q4 = 2;
int avg = 0;
-
int w = 1;
int h = 1;
+ int subpel_x_q4;
+ int subpel_y_q4;
+
for (int i = 0; i < filter_size * filter_size; i++) {
src[i] = rnd.Rand16() % (1 << 8);
}
- vp10_convolve(src + src_stride * filter_center + filter_center, src_stride,
- dst, dst_stride, w, h, filter_params, subpel_x_q4, x_step_q4,
- subpel_y_q4, y_step_q4, avg);
+ for (subpel_x_q4 = 0; subpel_x_q4 < 16; subpel_x_q4++) {
+ for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) {
+ vp10_convolve(src + src_stride * filter_center + filter_center,
+ src_stride, dst, dst_stride, w, h, filter_params,
+ subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg);
- const int16_t* x_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_x_q4);
- const int16_t* y_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
+ const int16_t* x_filter =
+ vp10_get_interp_filter_kernel(filter_params, subpel_x_q4);
+ const int16_t* y_filter =
+ vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
- int temp[12];
- int dst_ref = 0;
- for (int r = 0; r < filter_size; r++) {
- temp[r] = 0;
- for (int c = 0; c < filter_size; c++) {
- temp[r] += x_filter[c] * src[r * filter_size + c];
+ int temp[12];
+ int dst_ref = 0;
+ for (int r = 0; r < filter_size; r++) {
+ temp[r] = 0;
+ for (int c = 0; c < filter_size; c++) {
+ temp[r] += x_filter[c] * src[r * filter_size + c];
+ }
+ temp[r] = clip_pixel(ROUND_POWER_OF_TWO(temp[r], FILTER_BITS));
+ dst_ref += temp[r] * y_filter[r];
+ }
+ dst_ref = clip_pixel(ROUND_POWER_OF_TWO(dst_ref, FILTER_BITS));
+ EXPECT_EQ(dst[0], dst_ref);
}
- temp[r] = clip_pixel(ROUND_POWER_OF_TWO(temp[r], FILTER_BITS));
- dst_ref += temp[r] * y_filter[r];
}
- dst_ref = clip_pixel(ROUND_POWER_OF_TWO(dst_ref, FILTER_BITS));
- EXPECT_EQ(dst[0], dst_ref);
}
TEST(VP10ConvolveTest, vp10_convolve_avg) {
@@ -110,13 +114,14 @@
int dst_stride = 1;
int x_step_q4 = 16;
int y_step_q4 = 16;
- int subpel_x_q4 = 3;
- int subpel_y_q4 = 2;
int avg = 0;
int w = 1;
int h = 1;
+ int subpel_x_q4;
+ int subpel_y_q4;
+
for (int i = 0; i < filter_size * filter_size; i++) {
src0[i] = rnd.Rand16() % (1 << 8);
src1[i] = rnd.Rand16() % (1 << 8);
@@ -124,23 +129,29 @@
int offset = filter_size * filter_center + filter_center;
- avg = 0;
- vp10_convolve(src0 + offset, src_stride, dst0, dst_stride, w, h,
- filter_params, subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4,
- avg);
- avg = 0;
- vp10_convolve(src1 + offset, src_stride, dst1, dst_stride, w, h,
- filter_params, subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4,
- avg);
+ for (subpel_x_q4 = 0; subpel_x_q4 < 16; subpel_x_q4++) {
+ for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) {
+ avg = 0;
+ vp10_convolve(src0 + offset, src_stride, dst0, dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg);
+ avg = 0;
+ vp10_convolve(src1 + offset, src_stride, dst1, dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg);
- avg = 0;
- vp10_convolve(src0 + offset, src_stride, dst, dst_stride, w, h, filter_params,
- subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg);
- avg = 1;
- vp10_convolve(src1 + offset, src_stride, dst, dst_stride, w, h, filter_params,
- subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg);
+ avg = 0;
+ vp10_convolve(src0 + offset, src_stride, dst, dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg);
+ avg = 1;
+ vp10_convolve(src1 + offset, src_stride, dst, dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg);
- EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));
+ EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));
+ }
+ }
}
#if CONFIG_VP9_HIGHBITDEPTH
@@ -157,40 +168,45 @@
int dst_stride = 1;
int x_step_q4 = 16;
int y_step_q4 = 16;
- int subpel_x_q4 = 8;
- int subpel_y_q4 = 6;
int avg = 0;
int bd = 10;
-
int w = 1;
int h = 1;
+ int subpel_x_q4;
+ int subpel_y_q4;
+
for (int i = 0; i < filter_size * filter_size; i++) {
src[i] = rnd.Rand16() % (1 << bd);
}
- vp10_highbd_convolve(
- CONVERT_TO_BYTEPTR(src + src_stride * filter_center + filter_center),
- src_stride, CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, filter_params,
- subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg, bd);
+ for (subpel_x_q4 = 0; subpel_x_q4 < 16; subpel_x_q4++) {
+ for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) {
+ vp10_highbd_convolve(
+ CONVERT_TO_BYTEPTR(src + src_stride * filter_center + filter_center),
+ src_stride, CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, filter_params,
+ subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg, bd);
- const int16_t* x_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_x_q4);
- const int16_t* y_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
+ const int16_t* x_filter =
+ vp10_get_interp_filter_kernel(filter_params, subpel_x_q4);
+ const int16_t* y_filter =
+ vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
- int temp[12];
- int dst_ref = 0;
- for (int r = 0; r < filter_size; r++) {
- temp[r] = 0;
- for (int c = 0; c < filter_size; c++) {
- temp[r] += x_filter[c] * src[r * filter_size + c];
+ int temp[12];
+ int dst_ref = 0;
+ for (int r = 0; r < filter_size; r++) {
+ temp[r] = 0;
+ for (int c = 0; c < filter_size; c++) {
+ temp[r] += x_filter[c] * src[r * filter_size + c];
+ }
+ temp[r] =
+ clip_pixel_highbd(ROUND_POWER_OF_TWO(temp[r], FILTER_BITS), bd);
+ dst_ref += temp[r] * y_filter[r];
+ }
+ dst_ref = clip_pixel_highbd(ROUND_POWER_OF_TWO(dst_ref, FILTER_BITS), bd);
+ EXPECT_EQ(dst[0], dst_ref);
}
- temp[r] = clip_pixel_highbd(ROUND_POWER_OF_TWO(temp[r], FILTER_BITS), bd);
- dst_ref += temp[r] * y_filter[r];
}
- dst_ref = clip_pixel_highbd(ROUND_POWER_OF_TWO(dst_ref, FILTER_BITS), bd);
- EXPECT_EQ(dst[0], dst_ref);
}
TEST(VP10ConvolveTest, vp10_highbd_convolve_avg) {
@@ -209,42 +225,49 @@
int dst_stride = 1;
int x_step_q4 = 16;
int y_step_q4 = 16;
- int subpel_x_q4 = 3;
- int subpel_y_q4 = 2;
int avg = 0;
int bd = 10;
int w = 1;
int h = 1;
+ int subpel_x_q4;
+ int subpel_y_q4;
+
for (int i = 0; i < filter_size * filter_size; i++) {
src0[i] = rnd.Rand16() % (1 << bd);
src1[i] = rnd.Rand16() % (1 << bd);
}
- int offset = filter_size * filter_center + filter_center;
+ for (subpel_x_q4 = 0; subpel_x_q4 < 16; subpel_x_q4++) {
+ for (subpel_y_q4 = 0; subpel_y_q4 < 16; subpel_y_q4++) {
+ int offset = filter_size * filter_center + filter_center;
- avg = 0;
- vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
- CONVERT_TO_BYTEPTR(dst0), dst_stride, w, h,
- filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
- y_step_q4, avg, bd);
- avg = 0;
- vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
- CONVERT_TO_BYTEPTR(dst1), dst_stride, w, h,
- filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
- y_step_q4, avg, bd);
+ avg = 0;
+ vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
+ CONVERT_TO_BYTEPTR(dst0), dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg, bd);
+ avg = 0;
+ vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
+ CONVERT_TO_BYTEPTR(dst1), dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg, bd);
- avg = 0;
- vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
- CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, filter_params,
- subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg, bd);
- avg = 1;
- vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
- CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, filter_params,
- subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg, bd);
+ avg = 0;
+ vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
+ CONVERT_TO_BYTEPTR(dst), dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg, bd);
+ avg = 1;
+ vp10_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
+ CONVERT_TO_BYTEPTR(dst), dst_stride, w, h,
+ filter_params, subpel_x_q4, x_step_q4, subpel_y_q4,
+ y_step_q4, avg, bd);
- EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));
+ EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));
+ }
+ }
}
#endif // CONFIG_VP9_HIGHBITDEPTH
} // namespace
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index cf78cbb..4d7f921 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -79,6 +79,9 @@
typedef struct {
PREDICTION_MODE as_mode;
int_mv as_mv[2]; // first, second inter predictor motion vectors
+#if CONFIG_REF_MV
+ int_mv pred_mv[2];
+#endif
#if CONFIG_EXT_INTER
int_mv ref_mv[2];
#endif // CONFIG_EXT_INTER
diff --git a/vp10/common/entropy.c b/vp10/common/entropy.c
index f60bcf5..8c7e27a 100644
--- a/vp10/common/entropy.c
+++ b/vp10/common/entropy.c
@@ -1023,10 +1023,8 @@
};
static void extend_to_full_distribution(vpx_prob *probs, vpx_prob p) {
- // TODO(aconverse): model[PIVOT_NODE] should never be zero.
- // https://code.google.com/p/webm/issues/detail?id=1089
- memcpy(probs, vp10_pareto8_full[p == 0 ? 254 : p - 1],
- MODEL_NODES * sizeof(vpx_prob));
+ assert(p != 0);
+ memcpy(probs, vp10_pareto8_full[p - 1], MODEL_NODES * sizeof(vpx_prob));
}
void vp10_model_to_full_probs(const vpx_prob *model, vpx_prob *full) {
diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c
index 735e10e..abdb7db 100644
--- a/vp10/common/entropymode.c
+++ b/vp10/common/entropymode.c
@@ -809,7 +809,17 @@
{ 36, 243, 48},
{ 149, 160, 128},
};
-#else
+#elif CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 5
+static const vpx_prob default_switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS]
+ [SWITCHABLE_FILTERS - 1] = {
+ { 235, 192, 128, 128},
+ { 36, 243, 208, 128},
+ { 34, 16, 128, 128},
+ { 36, 243, 48, 128},
+ { 34, 16, 128, 128},
+ { 149, 160, 128, 128},
+};
+#else // CONFIG_EXT_INTERP
static const vpx_prob default_switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS]
[SWITCHABLE_FILTERS - 1] = {
{ 235, 162, },
@@ -817,7 +827,7 @@
{ 34, 3, },
{ 149, 144, },
};
-#endif
+#endif // CONFIG_EXT_INTERP
#if CONFIG_EXT_TX
const vpx_tree_index vp10_ext_tx_inter_tree[EXT_TX_SETS_INTER]
@@ -1335,6 +1345,14 @@
4, -EIGHTTAP_SHARP,
-EIGHTTAP_SMOOTH, -EIGHTTAP_SMOOTH2,
};
+#elif CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 5
+const vpx_tree_index vp10_switchable_interp_tree
+[TREE_SIZE(SWITCHABLE_FILTERS)] = {
+ -EIGHTTAP, 2,
+ 4, 6,
+ -EIGHTTAP_SMOOTH, -EIGHTTAP_SMOOTH2,
+ -EIGHTTAP_SHARP, -EIGHTTAP_SHARP2,
+};
#else
const vpx_tree_index vp10_switchable_interp_tree
[TREE_SIZE(SWITCHABLE_FILTERS)] = {
diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h
index d581a08..05918ee 100644
--- a/vp10/common/entropymode.h
+++ b/vp10/common/entropymode.h
@@ -93,7 +93,11 @@
vpx_prob txfm_partition_prob[TXFM_PARTITION_CONTEXTS];
#endif
vpx_prob skip_probs[SKIP_CONTEXTS];
+#if CONFIG_REF_MV
+ nmv_context nmvc[NMV_CONTEXTS];
+#else
nmv_context nmvc;
+#endif
int initialized;
#if CONFIG_EXT_TX
vpx_prob inter_ext_tx_prob[EXT_TX_SETS_INTER][EXT_TX_SIZES][TX_TYPES - 1];
@@ -150,7 +154,11 @@
unsigned int txfm_partition[TXFM_PARTITION_CONTEXTS][2];
#endif
unsigned int skip[SKIP_CONTEXTS][2];
+#if CONFIG_REF_MV
+ nmv_context_counts mv[NMV_CONTEXTS];
+#else
nmv_context_counts mv;
+#endif
#if CONFIG_EXT_TX
unsigned int inter_ext_tx[EXT_TX_SETS_INTER][EXT_TX_SIZES][TX_TYPES];
unsigned int intra_ext_tx[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
diff --git a/vp10/common/entropymv.c b/vp10/common/entropymv.c
index a9946ee..5be9797 100644
--- a/vp10/common/entropymv.c
+++ b/vp10/common/entropymv.c
@@ -185,7 +185,45 @@
void vp10_adapt_mv_probs(VP10_COMMON *cm, int allow_hp) {
int i, j;
+#if CONFIG_REF_MV
+ int idx;
+ for (idx = 0; idx < NMV_CONTEXTS; ++idx) {
+ nmv_context *fc = &cm->fc->nmvc[idx];
+ const nmv_context *pre_fc =
+ &cm->frame_contexts[cm->frame_context_idx].nmvc[idx];
+ const nmv_context_counts *counts = &cm->counts.mv[idx];
+ vpx_tree_merge_probs(vp10_mv_joint_tree, pre_fc->joints, counts->joints,
+ fc->joints);
+
+ for (i = 0; i < 2; ++i) {
+ nmv_component *comp = &fc->comps[i];
+ const nmv_component *pre_comp = &pre_fc->comps[i];
+ const nmv_component_counts *c = &counts->comps[i];
+
+ comp->sign = mode_mv_merge_probs(pre_comp->sign, c->sign);
+ vpx_tree_merge_probs(vp10_mv_class_tree, pre_comp->classes, c->classes,
+ comp->classes);
+ vpx_tree_merge_probs(vp10_mv_class0_tree, pre_comp->class0, c->class0,
+ comp->class0);
+
+ for (j = 0; j < MV_OFFSET_BITS; ++j)
+ comp->bits[j] = mode_mv_merge_probs(pre_comp->bits[j], c->bits[j]);
+
+ for (j = 0; j < CLASS0_SIZE; ++j)
+ vpx_tree_merge_probs(vp10_mv_fp_tree, pre_comp->class0_fp[j],
+ c->class0_fp[j], comp->class0_fp[j]);
+
+ vpx_tree_merge_probs(vp10_mv_fp_tree, pre_comp->fp, c->fp, comp->fp);
+
+ if (allow_hp) {
+ comp->class0_hp = mode_mv_merge_probs(pre_comp->class0_hp,
+ c->class0_hp);
+ comp->hp = mode_mv_merge_probs(pre_comp->hp, c->hp);
+ }
+ }
+ }
+#else
nmv_context *fc = &cm->fc->nmvc;
const nmv_context *pre_fc = &cm->frame_contexts[cm->frame_context_idx].nmvc;
const nmv_context_counts *counts = &cm->counts.mv;
@@ -218,8 +256,15 @@
comp->hp = mode_mv_merge_probs(pre_comp->hp, c->hp);
}
}
+#endif
}
void vp10_init_mv_probs(VP10_COMMON *cm) {
+#if CONFIG_REF_MV
+ int i;
+ for (i = 0; i < NMV_CONTEXTS; ++i)
+ cm->fc->nmvc[i] = default_nmv_context;
+#else
cm->fc->nmvc = default_nmv_context;
+#endif
}
diff --git a/vp10/common/enums.h b/vp10/common/enums.h
index af6ef36..e1f3168 100644
--- a/vp10/common/enums.h
+++ b/vp10/common/enums.h
@@ -227,6 +227,8 @@
#define SKIP_CONTEXTS 3
#if CONFIG_REF_MV
+#define NMV_CONTEXTS 2
+
#define NEWMV_MODE_CONTEXTS 7
#define ZEROMV_MODE_CONTEXTS 2
#define REFMV_MODE_CONTEXTS 9
diff --git a/vp10/common/filter.c b/vp10/common/filter.c
index a3aa3cf..c001f7f 100644
--- a/vp10/common/filter.c
+++ b/vp10/common/filter.c
@@ -12,8 +12,6 @@
#include "vp10/common/filter.h"
-#define USE_12_SHARP_FILTER 0
-
DECLARE_ALIGNED(256, static const InterpKernel,
bilinear_filters[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0 },
@@ -75,29 +73,6 @@
#endif // CONFIG_EXT_INTERP
};
-#if USE_12_SHARP_FILTER
-DECLARE_ALIGNED(16, static const int16_t,
- sub_pel_filters_12sharp[16][12]) = {
- // intfilt 0.8
- {0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0},
- {0, 1, -1, 3, -7, 127, 8, -4, 2, -1, 0, 0},
- {0, 1, -3, 5, -12, 124, 18, -8, 4, -2, 1, 0},
- {-1, 2, -4, 8, -17, 120, 28, -11, 6, -3, 1, -1},
- {-1, 2, -4, 10, -21, 114, 38, -15, 8, -4, 2, -1},
- {-1, 3, -5, 11, -23, 107, 49, -18, 9, -5, 2, -1},
- {-1, 3, -6, 12, -25, 99, 60, -21, 11, -6, 3, -1},
- {-1, 3, -6, 12, -25, 90, 70, -23, 12, -6, 3, -1},
- {-1, 3, -6, 12, -24, 80, 80, -24, 12, -6, 3, -1},
- {-1, 3, -6, 12, -23, 70, 90, -25, 12, -6, 3, -1},
- {-1, 3, -6, 11, -21, 60, 99, -25, 12, -6, 3, -1},
- {-1, 2, -5, 9, -18, 49, 107, -23, 11, -5, 3, -1},
- {-1, 2, -4, 8, -15, 38, 114, -21, 10, -4, 2, -1},
- {-1, 1, -3, 6, -11, 28, 120, -17, 8, -4, 2, -1},
- {0, 1, -2, 4, -8, 18, 124, -12, 5, -3, 1, 0},
- {0, 0, -1, 2, -4, 8, 127, -7, 3, -1, 1, 0},
-};
-#endif // USE_12_SHARP_FILTER
-
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8sharp[SUBPEL_SHIFTS]) = {
#if CONFIG_EXT_INTERP
@@ -139,7 +114,7 @@
#endif // CONFIG_EXT_INTERP
};
-#if CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 4
+#if CONFIG_EXT_INTERP && (SWITCHABLE_FILTERS == 4 || SWITCHABLE_FILTERS == 5)
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8smooth2[SUBPEL_SHIFTS]) = {
@@ -183,6 +158,27 @@
{0, 2, -11, 31, 95, 19, -10, 2},
};
+DECLARE_ALIGNED(16, static const int16_t,
+ sub_pel_filters_12sharp[16][12]) = {
+ // intfilt 0.8
+ {0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0},
+ {0, 1, -1, 3, -7, 127, 8, -4, 2, -1, 0, 0},
+ {0, 1, -3, 5, -12, 124, 18, -8, 4, -2, 1, 0},
+ {-1, 2, -4, 8, -17, 120, 28, -11, 6, -3, 1, -1},
+ {-1, 2, -4, 10, -21, 114, 38, -15, 8, -4, 2, -1},
+ {-1, 3, -5, 11, -23, 107, 49, -18, 9, -5, 2, -1},
+ {-1, 3, -6, 12, -25, 99, 60, -21, 11, -6, 3, -1},
+ {-1, 3, -6, 12, -25, 90, 70, -23, 12, -6, 3, -1},
+ {-1, 3, -6, 12, -24, 80, 80, -24, 12, -6, 3, -1},
+ {-1, 3, -6, 12, -23, 70, 90, -25, 12, -6, 3, -1},
+ {-1, 3, -6, 11, -21, 60, 99, -25, 12, -6, 3, -1},
+ {-1, 2, -5, 9, -18, 49, 107, -23, 11, -5, 3, -1},
+ {-1, 2, -4, 8, -15, 38, 114, -21, 10, -4, 2, -1},
+ {-1, 1, -3, 6, -11, 28, 120, -17, 8, -4, 2, -1},
+ {0, 1, -2, 4, -8, 18, 124, -12, 5, -3, 1, 0},
+ {0, 0, -1, 2, -4, 8, 127, -7, 3, -1, 1, 0},
+};
+
#else
DECLARE_ALIGNED(256, static const InterpKernel,
@@ -214,13 +210,16 @@
sub_pel_filters_8sharp,
#if CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 4
sub_pel_filters_8smooth2,
+#elif CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 5
+ sub_pel_filters_8smooth2,
+ (const InterpKernel*)sub_pel_filters_12sharp,
#endif
bilinear_filters
};
#if CONFIG_EXT_INTRA
const InterpKernel *vp10_intra_filter_kernels[INTRA_FILTERS] = {
- NULL, // INTRA_FILTER_LINEAR
+ bilinear_filters, // INTRA_FILTER_LINEAR
sub_pel_filters_8, // INTRA_FILTER_8TAP
sub_pel_filters_8sharp, // INTRA_FILTER_8TAP_SHARP
sub_pel_filters_8smooth, // INTRA_FILTER_8TAP_SMOOTH
@@ -231,13 +230,12 @@
vp10_interp_filter_params_list[SWITCHABLE_FILTERS + 1] = {
{(const int16_t*)sub_pel_filters_8, SUBPEL_TAPS, SUBPEL_SHIFTS},
{(const int16_t*)sub_pel_filters_8smooth, SUBPEL_TAPS, SUBPEL_SHIFTS},
-#if USE_12_SHARP_FILTER
- {(const int16_t*)sub_pel_filters_12sharp, 12, SUBPEL_SHIFTS},
-#else // USE_12_SHARP_FILTER
{(const int16_t*)sub_pel_filters_8sharp, SUBPEL_TAPS, SUBPEL_SHIFTS},
-#endif // USE_12_SHARP_FILTER
#if CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 4
{(const int16_t*)sub_pel_filters_8smooth2, SUBPEL_TAPS, SUBPEL_SHIFTS},
+#elif CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 5
+ {(const int16_t*)sub_pel_filters_8smooth2, SUBPEL_TAPS, SUBPEL_SHIFTS},
+ {(const int16_t*)sub_pel_filters_12sharp, 12, SUBPEL_SHIFTS},
#endif
{(const int16_t*)bilinear_filters, SUBPEL_TAPS, SUBPEL_SHIFTS}
};
diff --git a/vp10/common/filter.h b/vp10/common/filter.h
index afebee0..fea8330 100644
--- a/vp10/common/filter.h
+++ b/vp10/common/filter.h
@@ -27,8 +27,19 @@
#if CONFIG_EXT_INTERP
#define SUPPORT_NONINTERPOLATING_FILTERS 0 /* turn it on for experimentation */
+#define SWITCHABLE_FILTERS 5 /* Number of switchable filters */
+
+#if SWITCHABLE_FILTERS == 4
+
#define EIGHTTAP_SMOOTH2 3
-#define SWITCHABLE_FILTERS 4 /* Number of switchable filters */
+
+#elif SWITCHABLE_FILTERS == 5
+
+#define EIGHTTAP_SMOOTH2 3
+#define EIGHTTAP_SHARP2 4
+
+#endif // SWITCHABLE_FILTERS
+
#else
#define SWITCHABLE_FILTERS 3 /* Number of switchable filters */
#endif // CONFIG_EXT_INTERP
diff --git a/vp10/common/mv.h b/vp10/common/mv.h
index 904d372..4523705 100644
--- a/vp10/common/mv.h
+++ b/vp10/common/mv.h
@@ -38,6 +38,7 @@
typedef struct candidate_mv {
int_mv this_mv;
int_mv comp_mv;
+ int_mv pred_mv;
int weight;
} CANDIDATE_MV;
#endif
diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c
index 1b7fb7d..5a2def0 100644
--- a/vp10/common/mvref_common.c
+++ b/vp10/common/mvref_common.c
@@ -38,6 +38,8 @@
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
+ ref_mv_stack[index].pred_mv =
+ get_sub_block_pred_mv(candidate_mi, ref, col, block);
ref_mv_stack[index].weight = 2 * weight;
++(*refmv_count);
@@ -63,6 +65,8 @@
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
+ ref_mv_stack[index].pred_mv =
+ get_sub_block_pred_mv(candidate_mi, ref, col, alt_block);
ref_mv_stack[index].weight = weight;
++(*refmv_count);
diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h
index b02c0dd..b3a8beb 100644
--- a/vp10/common/mvref_common.h
+++ b/vp10/common/mvref_common.h
@@ -150,6 +150,16 @@
: candidate->mbmi.mv[which_mv];
}
+#if CONFIG_REF_MV
+static INLINE int_mv get_sub_block_pred_mv(const MODE_INFO *candidate,
+ int which_mv,
+ int search_col, int block_idx) {
+ return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8
+ ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]]
+ .pred_mv[which_mv]
+ : candidate->mbmi.pred_mv[which_mv];
+}
+#endif
// Performs mv sign inversion if indicated by the reference frame combination.
static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
@@ -218,6 +228,22 @@
}
#if CONFIG_REF_MV
+static INLINE int vp10_nmv_ctx(const uint8_t ref_mv_count,
+ const CANDIDATE_MV *ref_mv_stack) {
+#if CONFIG_EXT_INTER
+ return 0;
+#endif
+ if (ref_mv_stack[0].weight > REF_CAT_LEVEL &&
+ ref_mv_count > 0) {
+ if (abs(ref_mv_stack[0].this_mv.as_mv.row -
+ ref_mv_stack[0].pred_mv.as_mv.row) < 8 &&
+ abs(ref_mv_stack[0].this_mv.as_mv.col -
+ ref_mv_stack[0].pred_mv.as_mv.col) < 8)
+ return 1;
+ }
+ return 0;
+}
+
static INLINE int8_t vp10_ref_frame_type(const MV_REFERENCE_FRAME *const rf) {
if (rf[1] > INTRA_FRAME)
return rf[0] + ALTREF_FRAME;
diff --git a/vp10/common/reconintra.c b/vp10/common/reconintra.c
index f257200..99c3340 100644
--- a/vp10/common/reconintra.c
+++ b/vp10/common/reconintra.c
@@ -276,28 +276,95 @@
static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bs,
const uint8_t *above, const uint8_t *left,
int dx, int dy, INTRA_FILTER filter_type) {
- int r, c, x, y, base, shift, val;
+ int r, c, x, base, shift, val;
(void)left;
(void)dy;
assert(dy == 1);
assert(dx < 0);
- for (r = 0; r < bs; ++r) {
- y = r + 1;
- for (c = 0; c < bs; ++c) {
- x = (c << 8) - y * dx;
+ if (filter_type != INTRA_FILTER_LINEAR) {
+ const int pad_size = SUBPEL_TAPS >> 1;
+ int len;
+ DECLARE_ALIGNED(16, uint8_t, buf[SUBPEL_SHIFTS][64]);
+ DECLARE_ALIGNED(16, uint8_t, src[64 + SUBPEL_TAPS]);
+ uint8_t flags[SUBPEL_SHIFTS];
+
+ memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
+ memset(src, above[0], pad_size * sizeof(above[0]));
+ memcpy(src + pad_size, above, 2 * bs * sizeof(above[0]));
+ memset(src + pad_size + 2 * bs, above[2 * bs - 1],
+ pad_size * sizeof(above[0]));
+ flags[0] = 1;
+ x = -dx;
+ for (r = 0; r < bs; ++r, dst += stride, x -= dx) {
base = x >> 8;
- shift = x - (base << 8);
+ shift = x & 0xFF;
+ shift = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
+ if (shift == SUBPEL_SHIFTS) {
+ base += 1;
+ shift = 0;
+ }
+ len = VPXMIN(bs, 2 * bs - 1 - base);
+ if (len <= 0) {
+ int i;
+ for (i = r; i < bs; ++i) {
+ memset(dst, above[2 * bs - 1], bs * sizeof(dst[0]));
+ dst += stride;
+ }
+ return;
+ }
+
+ if (len <= (bs >> 1) && !flags[shift]) {
+ base = x >> 8;
+ shift = x & 0xFF;
+ for (c = 0; c < len; ++c) {
+ val = intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
+ filter_type);
+ dst[c] = clip_pixel(val);
+ ++base;
+ }
+ } else {
+ if (!flags[shift]) {
+ vpx_convolve8_horiz(src + pad_size, 2 * bs, buf[shift], 2 * bs,
+ vp10_intra_filter_kernels[filter_type][shift], 16,
+ NULL, 16, 2 * bs, 2 * bs < 16 ? 2 : 1);
+ flags[shift] = 1;
+ }
+ memcpy(dst, shift == 0 ? src + pad_size + base : &buf[shift][base],
+ len * sizeof(dst[0]));
+ }
+
+ if (len < bs)
+ memset(dst + len, above[2 * bs - 1], (bs - len) * sizeof(dst[0]));
+ }
+ return;
+ }
+
+ // For linear filter, C code is faster.
+ x = -dx;
+ for (r = 0; r < bs; ++r, dst += stride, x -= dx) {
+ base = x >> 8;
+ shift = x & 0xFF;
+
+ if (base >= 2 * bs - 1) {
+ int i;
+ for (i = r; i < bs; ++i) {
+ memset(dst, above[2 * bs - 1], bs * sizeof(dst[0]));
+ dst += stride;
+ }
+ return;
+ }
+
+ for (c = 0; c < bs; ++c, ++base) {
if (base < 2 * bs - 1) {
- val = intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
- filter_type);
+ val = above[base] * (256 - shift) + above[base + 1] * shift;
+ val = ROUND_POWER_OF_TWO(val, 8);
dst[c] = clip_pixel(val);
} else {
dst[c] = above[2 * bs - 1];
}
}
- dst += stride;
}
}
@@ -305,33 +372,33 @@
static void dr_prediction_z2(uint8_t *dst, ptrdiff_t stride, int bs,
const uint8_t *above, const uint8_t *left,
int dx, int dy, INTRA_FILTER filter_type) {
- int r, c, x, y, shift, val, base;
+ int r, c, x, y, shift1, shift2, val, base1, base2, use_above;
assert(dx > 0);
assert(dy > 0);
- for (r = 0; r < bs; ++r) {
- for (c = 0; c < bs; ++c) {
- y = r + 1;
- x = (c << 8) - y * dx;
- base = x >> 8;
- if (base >= -1) {
- shift = x - (base << 8);
- val = intra_subpel_interp(base, shift, above, -1, bs - 1, filter_type);
+ x = -dx;
+ for (r = 0; r < bs; ++r, x -= dx, dst += stride) {
+ use_above = 0;
+ base1 = x >> 8;
+ y = (r << 8) - dy;
+ for (c = 0; c < bs; ++c, ++base1, y -= dy) {
+ if (base1 >= -1) {
+ shift1 = x & 0xFF;
+ val = intra_subpel_interp(base1, shift1, above, -1, bs - 1,
+ filter_type);
} else {
- x = c + 1;
- y = (r << 8) - x * dy;
- base = y >> 8;
- if (base >= 0) {
- shift = y - (base << 8);
- val = intra_subpel_interp(base, shift, left, 0, bs - 1, filter_type);
+ base2 = y >> 8;
+ if (base2 >= 0) {
+ shift2 = y & 0xFF;
+ val = intra_subpel_interp(base2, shift2, left, 0, bs - 1,
+ filter_type);
} else {
val = left[0];
}
}
dst[c] = clip_pixel(val);
}
- dst += stride;
}
}
@@ -339,7 +406,7 @@
static void dr_prediction_z3(uint8_t *dst, ptrdiff_t stride, int bs,
const uint8_t *above, const uint8_t *left,
int dx, int dy, INTRA_FILTER filter_type) {
- int r, c, x, y, base, shift, val;
+ int r, c, y, base, shift, val;
(void)above;
(void)dx;
@@ -347,21 +414,94 @@
assert(dx == 1);
assert(dy < 0);
- for (r = 0; r < bs; ++r) {
- for (c = 0; c < bs; ++c) {
- x = c + 1;
- y = (r << 8) - x * dy;
+ if (filter_type != INTRA_FILTER_LINEAR) {
+ const int pad_size = SUBPEL_TAPS >> 1;
+ int len, i;
+ DECLARE_ALIGNED(16, uint8_t, buf[64][4 * SUBPEL_SHIFTS]);
+ DECLARE_ALIGNED(16, uint8_t, src[(64 + SUBPEL_TAPS) * 4]);
+ uint8_t flags[SUBPEL_SHIFTS];
+
+ memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
+ for (i = 0; i < pad_size; ++i)
+ src[4 * i] = left[0];
+ for (i = 0; i < 2 * bs; ++i)
+ src[4 * (i + pad_size)] = left[i];
+ for (i = 0; i < pad_size; ++i)
+ src[4 * (i + 2 * bs + pad_size)] = left[2 * bs - 1];
+ flags[0] = 1;
+ y = -dy;
+ for (c = 0; c < bs; ++c, y -= dy) {
base = y >> 8;
- shift = y - (base << 8);
- if (base < 2 * bs - 1) {
- val = intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
- filter_type);
- dst[c] = clip_pixel(val);
+ shift = y & 0xFF;
+ shift = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
+ if (shift == SUBPEL_SHIFTS) {
+ base += 1;
+ shift = 0;
+ }
+ len = VPXMIN(bs, 2 * bs - 1 - base);
+
+ if (len <= 0) {
+ for (i = r; r < bs; ++r) {
+ dst[i * stride + c] = left[ 2 * bs - 1];
+ }
+ continue;
+ }
+
+ if (len <= (bs >> 1) && !flags[shift]) {
+ base = y >> 8;
+ shift = y & 0xFF;
+ for (r = 0; r < len; ++r) {
+ val = intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
+ filter_type);
+ dst[r * stride + c] = clip_pixel(val);
+ ++base;
+ }
} else {
- dst[c] = left[ 2 * bs - 1];
+ if (!flags[shift]) {
+ vpx_convolve8_vert(src + 4 * pad_size, 4,
+ buf[0] + 4 * shift, 4 * SUBPEL_SHIFTS, NULL, 16,
+ vp10_intra_filter_kernels[filter_type][shift], 16,
+ 2 * bs < 16 ? 4 : 4, 2 * bs);
+ flags[shift] = 1;
+ }
+
+ if (shift == 0) {
+ for (r = 0; r < len; ++r) {
+ dst[r * stride + c] = left[r + base];
+ }
+ } else {
+ for (r = 0; r < len; ++r) {
+ dst[r * stride + c] = buf[r + base][4 * shift];
+ }
+ }
+ }
+
+ if (len < bs) {
+ for (r = len; r < bs; ++r) {
+ dst[r * stride + c] = left[ 2 * bs - 1];
+ }
}
}
- dst += stride;
+ return;
+ }
+
+ // For linear filter, C code is faster.
+ y = -dy;
+ for (c = 0; c < bs; ++c, y -= dy) {
+ base = y >> 8;
+ shift = y & 0xFF;
+
+ for (r = 0; r < bs; ++r, ++base) {
+ if (base < 2 * bs - 1) {
+ val = left[base] * (256 - shift) + left[base + 1] * shift;
+ val = ROUND_POWER_OF_TWO(val, 8);
+ dst[r * stride + c] = clip_pixel(val);
+ } else {
+ for (; r < bs; ++r)
+ dst[r * stride + c] = left[2 * bs - 1];
+ break;
+ }
+ }
}
}
diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c
index 6e959ed..7f04a09 100644
--- a/vp10/common/thread_common.c
+++ b/vp10/common/thread_common.c
@@ -447,6 +447,39 @@
for (j = 0; j < 2; j++)
cm->counts.skip[i][j] += counts->skip[i][j];
+#if CONFIG_REF_MV
+ for (m = 0; m < NMV_CONTEXTS; ++m) {
+ for (i = 0; i < MV_JOINTS; i++)
+ cm->counts.mv[m].joints[i] += counts->mv[m].joints[i];
+
+ for (k = 0; k < 2; k++) {
+ nmv_component_counts *comps = &cm->counts.mv[m].comps[k];
+ nmv_component_counts *comps_t = &counts->mv[m].comps[k];
+
+ for (i = 0; i < 2; i++) {
+ comps->sign[i] += comps_t->sign[i];
+ comps->class0_hp[i] += comps_t->class0_hp[i];
+ comps->hp[i] += comps_t->hp[i];
+ }
+
+ for (i = 0; i < MV_CLASSES; i++)
+ comps->classes[i] += comps_t->classes[i];
+
+ for (i = 0; i < CLASS0_SIZE; i++) {
+ comps->class0[i] += comps_t->class0[i];
+ for (j = 0; j < MV_FP_SIZE; j++)
+ comps->class0_fp[i][j] += comps_t->class0_fp[i][j];
+ }
+
+ for (i = 0; i < MV_OFFSET_BITS; i++)
+ for (j = 0; j < 2; j++)
+ comps->bits[i][j] += comps_t->bits[i][j];
+
+ for (i = 0; i < MV_FP_SIZE; i++)
+ comps->fp[i] += comps_t->fp[i];
+ }
+ }
+#else
for (i = 0; i < MV_JOINTS; i++)
cm->counts.mv.joints[i] += counts->mv.joints[i];
@@ -476,6 +509,7 @@
for (i = 0; i < MV_FP_SIZE; i++)
comps->fp[i] += comps_t->fp[i];
}
+#endif
#if CONFIG_EXT_TX
for (i = 0; i < EXT_TX_SIZES; i++) {
diff --git a/vp10/common/vp10_convolve.c b/vp10/common/vp10_convolve.c
index e8c0c92..33a8542 100644
--- a/vp10/common/vp10_convolve.c
+++ b/vp10/common/vp10_convolve.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <string.h>
#include "vp10/common/filter.h"
#include "vpx_dsp/vpx_dsp_common.h"
@@ -69,22 +70,35 @@
}
}
+static void convolve_copy(const uint8_t *src, int src_stride, uint8_t *dst,
+ int dst_stride, int w, int h, int avg) {
+ if (avg == 0) {
+ int r;
+ for (r = 0; r < h; ++r) {
+ memcpy(dst, src, w);
+ src += src_stride;
+ dst += dst_stride;
+ }
+ } else {
+ int r, c;
+ for (r = 0; r < h; ++r) {
+ for (c = 0; c < w; ++c) {
+ dst[c] = clip_pixel(ROUND_POWER_OF_TWO(dst[c] + src[c], 1));
+ }
+ src += src_stride;
+ dst += dst_stride;
+ }
+ }
+}
+
void vp10_convolve(const uint8_t *src, int src_stride, uint8_t *dst,
int dst_stride, int w, int h,
const InterpFilterParams filter_params,
const int subpel_x_q4, int x_step_q4, const int subpel_y_q4,
int y_step_q4, int avg) {
int filter_size = filter_params.tap;
-
- // temp's size is set to (maximum possible intermediate_height) *
- // MAX_BLOCK_WIDTH
- uint8_t temp[((((MAX_BLOCK_HEIGHT - 1) * MAX_STEP + 15) >> SUBPEL_BITS) +
- MAX_FILTER_TAP) *
- MAX_BLOCK_WIDTH];
- int temp_stride = MAX_BLOCK_WIDTH;
-
- int intermediate_height =
- (((h - 1) * y_step_q4 + subpel_y_q4) >> SUBPEL_BITS) + filter_size;
+ int ignore_horiz = x_step_q4 == 16 && subpel_x_q4 == 0;
+ int ignore_vert = y_step_q4 == 16 && subpel_y_q4 == 0;
assert(w <= MAX_BLOCK_WIDTH);
assert(h <= MAX_BLOCK_HEIGHT);
@@ -92,11 +106,31 @@
assert(x_step_q4 <= MAX_STEP);
assert(filter_params.tap <= MAX_FILTER_TAP);
- convolve_horiz(src - src_stride * (filter_size / 2 - 1), src_stride, temp,
- temp_stride, w, intermediate_height, filter_params,
- subpel_x_q4, x_step_q4, 0);
- convolve_vert(temp + temp_stride * (filter_size / 2 - 1), temp_stride, dst,
- dst_stride, w, h, filter_params, subpel_y_q4, y_step_q4, avg);
+ if (ignore_horiz && ignore_vert) {
+ convolve_copy(src, src_stride, dst, dst_stride, w, h, avg);
+ } else if (ignore_vert) {
+ convolve_horiz(src, src_stride, dst, dst_stride, w, h, filter_params,
+ subpel_x_q4, x_step_q4, avg);
+ } else if (ignore_horiz) {
+ convolve_vert(src, src_stride, dst, dst_stride, w, h, filter_params,
+ subpel_y_q4, y_step_q4, avg);
+ } else {
+ // temp's size is set to (maximum possible intermediate_height) *
+ // MAX_BLOCK_WIDTH
+ uint8_t temp[((((MAX_BLOCK_HEIGHT - 1) * MAX_STEP + 15) >> SUBPEL_BITS) +
+ MAX_FILTER_TAP) *
+ MAX_BLOCK_WIDTH];
+ int temp_stride = MAX_BLOCK_WIDTH;
+
+ int intermediate_height =
+ (((h - 1) * y_step_q4 + subpel_y_q4) >> SUBPEL_BITS) + filter_size;
+
+ convolve_horiz(src - src_stride * (filter_size / 2 - 1), src_stride, temp,
+ temp_stride, w, intermediate_height, filter_params,
+ subpel_x_q4, x_step_q4, 0);
+ convolve_vert(temp + temp_stride * (filter_size / 2 - 1), temp_stride, dst,
+ dst_stride, w, h, filter_params, subpel_y_q4, y_step_q4, avg);
+ }
}
#if CONFIG_VP9_HIGHBITDEPTH
@@ -164,23 +198,39 @@
}
}
+static void highbd_convolve_copy(const uint16_t *src, int src_stride,
+ uint16_t *dst, int dst_stride, int w, int h,
+ int avg, int bd) {
+ if (avg == 0) {
+ int r;
+ for (r = 0; r < h; ++r) {
+ memcpy(dst, src, w * sizeof(*src));
+ src += src_stride;
+ dst += dst_stride;
+ }
+ } else {
+ int r, c;
+ for (r = 0; r < h; ++r) {
+ for (c = 0; c < w; ++c) {
+ dst[c] = clip_pixel_highbd(ROUND_POWER_OF_TWO(dst[c] + src[c], 1), bd);
+ }
+ src += src_stride;
+ dst += dst_stride;
+ }
+ }
+}
+
void vp10_highbd_convolve(const uint8_t *src8, int src_stride, uint8_t *dst8,
int dst_stride, int w, int h,
const InterpFilterParams filter_params,
const int subpel_x_q4, int x_step_q4,
const int subpel_y_q4, int y_step_q4, int avg,
int bd) {
+ uint16_t *src = CONVERT_TO_SHORTPTR(src8);
+ uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
int filter_size = filter_params.tap;
-
- // temp's size is set to (maximum possible intermediate_height) *
- // MAX_BLOCK_WIDTH
- uint16_t temp[((((MAX_BLOCK_HEIGHT - 1) * MAX_STEP + 15) >> SUBPEL_BITS) +
- MAX_FILTER_TAP) *
- MAX_BLOCK_WIDTH];
- int temp_stride = MAX_BLOCK_WIDTH;
-
- int intermediate_height =
- (((h - 1) * y_step_q4 + subpel_y_q4) >> SUBPEL_BITS) + filter_size;
+ int ignore_horiz = x_step_q4 == 16 && subpel_x_q4 == 0;
+ int ignore_vert = y_step_q4 == 16 && subpel_y_q4 == 0;
assert(w <= MAX_BLOCK_WIDTH);
assert(h <= MAX_BLOCK_HEIGHT);
@@ -188,12 +238,31 @@
assert(x_step_q4 <= MAX_STEP);
assert(filter_params.tap <= MAX_FILTER_TAP);
- highbd_convolve_horiz(
- CONVERT_TO_SHORTPTR(src8 - src_stride * (filter_size / 2 - 1)),
- src_stride, temp, temp_stride, w, intermediate_height, filter_params,
- subpel_x_q4, x_step_q4, 0, bd);
- highbd_convolve_vert(temp + temp_stride * (filter_size / 2 - 1), temp_stride,
- CONVERT_TO_SHORTPTR(dst8), dst_stride, w, h,
- filter_params, subpel_y_q4, y_step_q4, avg, bd);
+ if (ignore_horiz && ignore_vert) {
+ highbd_convolve_copy(src, src_stride, dst, dst_stride, w, h, avg, bd);
+ } else if (ignore_vert) {
+ highbd_convolve_horiz(src, src_stride, dst, dst_stride, w, h, filter_params,
+ subpel_x_q4, x_step_q4, avg, bd);
+ } else if (ignore_horiz) {
+ highbd_convolve_vert(src, src_stride, dst, dst_stride, w, h, filter_params,
+ subpel_y_q4, y_step_q4, avg, bd);
+ } else {
+ // temp's size is set to (maximum possible intermediate_height) *
+ // MAX_BLOCK_WIDTH
+ uint16_t temp[((((MAX_BLOCK_HEIGHT - 1) * MAX_STEP + 15) >> SUBPEL_BITS) +
+ MAX_FILTER_TAP) *
+ MAX_BLOCK_WIDTH];
+ int temp_stride = MAX_BLOCK_WIDTH;
+
+ int intermediate_height =
+ (((h - 1) * y_step_q4 + subpel_y_q4) >> SUBPEL_BITS) + filter_size;
+
+ highbd_convolve_horiz(src - src_stride * (filter_size / 2 - 1), src_stride,
+ temp, temp_stride, w, intermediate_height,
+ filter_params, subpel_x_q4, x_step_q4, 0, bd);
+ highbd_convolve_vert(temp + temp_stride * (filter_size / 2 - 1),
+ temp_stride, dst, dst_stride, w, h, filter_params,
+ subpel_y_q4, y_step_q4, avg, bd);
+ }
}
#endif // CONFIG_VP9_HIGHBITDEPTH
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index a003d7a..509e1b8 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -653,6 +653,7 @@
struct macroblockd_plane *const pd = &xd->plane[plane];
uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
MV32 scaled_mv;
+ MV mv_q4;
int xs, ys, x0, y0, x0_16, y0_16, frame_width, frame_height,
buf_stride, subpel_x, subpel_y;
uint8_t *ref_frame, *buf_ptr;
@@ -672,10 +673,10 @@
: ref_frame_buf->buf.v_buffer;
}
+ mv_q4 = clamp_mv_to_umv_border_sb(xd, mv, bw, bh,
+ pd->subsampling_x,
+ pd->subsampling_y);
if (is_scaled) {
- const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, mv, bw, bh,
- pd->subsampling_x,
- pd->subsampling_y);
// Co-ordinate of containing block to pixel precision.
int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x));
int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y));
@@ -699,11 +700,6 @@
xs = sf->x_step_q4;
ys = sf->y_step_q4;
} else {
-#if CONFIG_OBMC
- const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, mv, bw, bh,
- pd->subsampling_x,
- pd->subsampling_y);
-#endif // CONFIG_OBMC
// Co-ordinate of containing block to pixel precision.
x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
@@ -712,13 +708,8 @@
x0_16 = x0 << SUBPEL_BITS;
y0_16 = y0 << SUBPEL_BITS;
-#if CONFIG_OBMC
scaled_mv.row = mv_q4.row;
scaled_mv.col = mv_q4.col;
-#else
- scaled_mv.row = mv->row * (1 << (1 - pd->subsampling_y));
- scaled_mv.col = mv->col * (1 << (1 - pd->subsampling_x));
-#endif // CONFIG_OBMC
xs = ys = 16;
}
subpel_x = scaled_mv.col & SUBPEL_MASK;
@@ -1839,6 +1830,9 @@
(xd->mb_to_bottom_edge >= 0 ?
0 : xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
+ if (plane <= 1 && mbmi->palette_mode_info.palette_size[plane])
+ vp10_decode_palette_tokens(xd, plane, r);
+
for (row = 0; row < max_blocks_high; row += step)
for (col = 0; col < max_blocks_wide; col += step)
predict_and_reconstruct_intra_block(xd,
@@ -3566,7 +3560,9 @@
for (i = 0; i < INTRA_MODES - 1; ++i)
vp10_diff_update_prob(&r, &cm->kf_y_prob[k][j][i]);
} else {
+#if !CONFIG_REF_MV
nmv_context *const nmvc = &fc->nmvc;
+#endif
read_inter_mode_probs(fc, &r);
@@ -3593,7 +3589,12 @@
for (i = 0; i < INTRA_MODES - 1; ++i)
vp10_diff_update_prob(&r, &fc->y_mode_prob[j][i]);
+#if CONFIG_REF_MV
+ for (i = 0; i < NMV_CONTEXTS; ++i)
+ read_mv_probs(&fc->nmvc[i], cm->allow_high_precision_mv, &r);
+#else
read_mv_probs(nmvc, cm->allow_high_precision_mv, &r);
+#endif
read_ext_tx_probs(fc, &r);
#if CONFIG_SUPERTX
if (!xd->lossless[0])
@@ -3647,7 +3648,14 @@
sizeof(cm->counts.comp_ref)));
assert(!memcmp(&cm->counts.tx, &zero_counts.tx, sizeof(cm->counts.tx)));
assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
+#if CONFIG_REF_MV
+ assert(!memcmp(&cm->counts.mv[0], &zero_counts.mv[0],
+ sizeof(cm->counts.mv[0])));
+ assert(!memcmp(&cm->counts.mv[1], &zero_counts.mv[1],
+ sizeof(cm->counts.mv[0])));
+#else
assert(!memcmp(&cm->counts.mv, &zero_counts.mv, sizeof(cm->counts.mv)));
+#endif
assert(!memcmp(cm->counts.inter_ext_tx, zero_counts.inter_ext_tx,
sizeof(cm->counts.inter_ext_tx)));
assert(!memcmp(cm->counts.intra_ext_tx, zero_counts.intra_ext_tx,
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index 401298f..7a8b47f 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -891,11 +891,20 @@
static INLINE int assign_mv(VP10_COMMON *cm, MACROBLOCKD *xd,
PREDICTION_MODE mode,
+#if CONFIG_REF_MV
+ int block,
+#endif
int_mv mv[2], int_mv ref_mv[2],
int_mv nearest_mv[2], int_mv near_mv[2],
int is_compound, int allow_hp, vpx_reader *r) {
int i;
int ret = 1;
+#if CONFIG_REF_MV
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+ BLOCK_SIZE bsize = mbmi->sb_type;
+ int_mv *pred_mv = (bsize >= BLOCK_8X8) ?
+ mbmi->pred_mv : xd->mi[0]->bmi[block].pred_mv;
+#endif
switch (mode) {
#if CONFIG_EXT_INTER
@@ -903,11 +912,26 @@
#endif // CONFIG_EXT_INTER
case NEWMV: {
FRAME_COUNTS *counts = xd->counts;
+#if !CONFIG_REF_MV
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
+#endif
for (i = 0; i < 1 + is_compound; ++i) {
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(xd->ref_mv_count[mbmi->ref_frame[i]],
+ xd->ref_mv_stack[mbmi->ref_frame[i]]);
+ nmv_context_counts *const mv_counts =
+ counts ? &counts->mv[nmv_ctx] : NULL;
+ read_mv(r, &mv[i].as_mv, &ref_mv[i].as_mv, &cm->fc->nmvc[nmv_ctx],
+ mv_counts, allow_hp);
+#else
read_mv(r, &mv[i].as_mv, &ref_mv[i].as_mv, &cm->fc->nmvc, mv_counts,
allow_hp);
+#endif
ret = ret && is_mv_valid(&mv[i].as_mv);
+
+#if CONFIG_REF_MV
+ pred_mv[i].as_int = ref_mv[i].as_int;
+#endif
}
break;
}
@@ -915,28 +939,58 @@
mv[0].as_int = nearest_mv[0].as_int;
if (is_compound)
mv[1].as_int = nearest_mv[1].as_int;
+
+#if CONFIG_REF_MV
+ pred_mv[0].as_int = nearest_mv[0].as_int;
+ if (is_compound)
+ pred_mv[1].as_int = nearest_mv[1].as_int;
+#endif
break;
}
case NEARMV: {
mv[0].as_int = near_mv[0].as_int;
if (is_compound)
mv[1].as_int = near_mv[1].as_int;
+
+#if CONFIG_REF_MV
+ pred_mv[0].as_int = near_mv[0].as_int;
+ if (is_compound)
+ pred_mv[1].as_int = near_mv[1].as_int;
+#endif
break;
}
case ZEROMV: {
mv[0].as_int = 0;
if (is_compound)
mv[1].as_int = 0;
+
+#if CONFIG_REF_MV
+ pred_mv[0].as_int = 0;
+ if (is_compound)
+ pred_mv[1].as_int = 0;
+#endif
break;
}
#if CONFIG_EXT_INTER
case NEW_NEWMV: {
FRAME_COUNTS *counts = xd->counts;
+#if !CONFIG_REF_MV
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
+#endif
assert(is_compound);
for (i = 0; i < 2; ++i) {
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(xd->ref_mv_count[mbmi->ref_frame[i]],
+ xd->ref_mv_stack[mbmi->ref_frame[i]]);
+ nmv_context_counts *const mv_counts =
+ counts ? &counts->mv[nmv_ctx] : NULL;
+ read_mv(r, &mv[i].as_mv, &ref_mv[i].as_mv,
+ &cm->fc->nmvc[nmv_ctx], mv_counts,
+ allow_hp);
+#else
read_mv(r, &mv[i].as_mv, &ref_mv[i].as_mv, &cm->fc->nmvc, mv_counts,
allow_hp);
+#endif
ret = ret && is_mv_valid(&mv[i].as_mv);
}
break;
@@ -961,40 +1015,83 @@
}
case NEW_NEARESTMV: {
FRAME_COUNTS *counts = xd->counts;
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(xd->ref_mv_count[mbmi->ref_frame[0]],
+ xd->ref_mv_stack[mbmi->ref_frame[0]]);
+ nmv_context_counts *const mv_counts =
+ counts ? &counts->mv[nmv_ctx] : NULL;
+ read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv,
+ &cm->fc->nmvc[nmv_ctx], mv_counts,
+ allow_hp);
+#else
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
- assert(is_compound);
read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv, &cm->fc->nmvc, mv_counts,
allow_hp);
+#endif
+ assert(is_compound);
ret = ret && is_mv_valid(&mv[0].as_mv);
mv[1].as_int = nearest_mv[1].as_int;
break;
}
case NEAREST_NEWMV: {
FRAME_COUNTS *counts = xd->counts;
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(xd->ref_mv_count[mbmi->ref_frame[1]],
+ xd->ref_mv_stack[mbmi->ref_frame[1]]);
+ nmv_context_counts *const mv_counts =
+ counts ? &counts->mv[nmv_ctx] : NULL;
+ mv[0].as_int = nearest_mv[0].as_int;
+ read_mv(r, &mv[1].as_mv, &ref_mv[1].as_mv,
+ &cm->fc->nmvc[nmv_ctx], mv_counts,
+ allow_hp);
+#else
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
- assert(is_compound);
mv[0].as_int = nearest_mv[0].as_int;
read_mv(r, &mv[1].as_mv, &ref_mv[1].as_mv, &cm->fc->nmvc, mv_counts,
allow_hp);
+#endif
+ assert(is_compound);
ret = ret && is_mv_valid(&mv[1].as_mv);
break;
}
case NEAR_NEWMV: {
FRAME_COUNTS *counts = xd->counts;
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(xd->ref_mv_count[mbmi->ref_frame[1]],
+ xd->ref_mv_stack[mbmi->ref_frame[1]]);
+ nmv_context_counts *const mv_counts =
+ counts ? &counts->mv[nmv_ctx] : NULL;
+ mv[0].as_int = near_mv[0].as_int;
+ read_mv(r, &mv[1].as_mv, &ref_mv[1].as_mv,
+ &cm->fc->nmvc[nmv_ctx], mv_counts,
+ allow_hp);
+#else
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
- assert(is_compound);
mv[0].as_int = near_mv[0].as_int;
read_mv(r, &mv[1].as_mv, &ref_mv[1].as_mv, &cm->fc->nmvc, mv_counts,
allow_hp);
+#endif
+ assert(is_compound);
+
ret = ret && is_mv_valid(&mv[1].as_mv);
break;
}
case NEW_NEARMV: {
FRAME_COUNTS *counts = xd->counts;
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(xd->ref_mv_count[mbmi->ref_frame[0]],
+ xd->ref_mv_stack[mbmi->ref_frame[0]]);
+ nmv_context_counts *const mv_counts =
+ counts ? &counts->mv[nmv_ctx] : NULL;
+ read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv,
+ &cm->fc->nmvc[nmv_ctx], mv_counts,
+ allow_hp);
+#else
nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
- assert(is_compound);
read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv, &cm->fc->nmvc, mv_counts,
allow_hp);
+#endif
+ assert(is_compound);
ret = ret && is_mv_valid(&mv[0].as_mv);
mv[1].as_int = near_mv[1].as_int;
break;
@@ -1284,7 +1381,11 @@
#endif // CONFIG_EXT_INTER
}
- if (!assign_mv(cm, xd, b_mode, block,
+ if (!assign_mv(cm, xd, b_mode,
+#if CONFIG_REF_MV
+ j,
+#endif
+ block,
#if CONFIG_EXT_INTER
ref_mv[mv_idx],
#else
@@ -1307,12 +1408,20 @@
}
}
+#if CONFIG_REF_MV
+ mbmi->pred_mv[0].as_int = mi->bmi[3].pred_mv[0].as_int;
+ mbmi->pred_mv[1].as_int = mi->bmi[3].pred_mv[1].as_int;
+#endif
mi->mbmi.mode = b_mode;
mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
} else {
- xd->corrupted |= !assign_mv(cm, xd, mbmi->mode, mbmi->mv,
+ xd->corrupted |= !assign_mv(cm, xd, mbmi->mode,
+#if CONFIG_REF_MV
+ 0,
+#endif
+ mbmi->mv,
#if CONFIG_EXT_INTER
mbmi->mode == NEWFROMNEARMV ?
nearmv : nearestmv,
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index 930f73f..7134672 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -42,6 +42,9 @@
#if CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 4
static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
{{0, 1}, {4, 3}, {3, 2}, {5, 3}};
+#elif CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 5
+static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
+ {{0, 1}, {4, 3}, {6, 3}, {5, 3}, {7, 3}};
#else
static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
{{0, 1}, {2, 2}, {3, 2}};
@@ -882,7 +885,9 @@
#endif
vpx_writer *w) {
VP10_COMMON *const cm = &cpi->common;
+#if !CONFIG_REF_MV
const nmv_context *nmvc = &cm->fc->nmvc;
+#endif
const MACROBLOCK *x = &cpi->td.mb;
const MACROBLOCKD *xd = &x->e_mbd;
const struct segmentation *const seg = &cm->seg;
@@ -1070,20 +1075,39 @@
#else
if (b_mode == NEWMV) {
#endif // CONFIG_EXT_INTER
- for (ref = 0; ref < 1 + is_compound; ++ref)
+ for (ref = 0; ref < 1 + is_compound; ++ref) {
+#if CONFIG_REF_MV
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[ref]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[ref]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+#endif
vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv,
#if CONFIG_EXT_INTER
&mi->bmi[j].ref_mv[ref].as_mv,
#else
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
#endif // CONFIG_EXT_INTER
- nmvc, allow_hp);
+ nmvc, allow_hp);
+ }
}
#if CONFIG_EXT_INTER
else if (b_mode == NEAREST_NEWMV || b_mode == NEAR_NEWMV) {
+#if CONFIG_REF_MV
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[1]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[1]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+#endif
vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[1].as_mv,
&mi->bmi[j].ref_mv[1].as_mv, nmvc, allow_hp);
} else if (b_mode == NEW_NEARESTMV || b_mode == NEW_NEARMV) {
+#if CONFIG_REF_MV
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[0]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[0]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+#endif
vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[0].as_mv,
&mi->bmi[j].ref_mv[0].as_mv, nmvc, allow_hp);
}
@@ -1096,9 +1120,14 @@
#else
if (mode == NEWMV) {
#endif // CONFIG_EXT_INTER
- for (ref = 0; ref < 1 + is_compound; ++ref)
+ for (ref = 0; ref < 1 + is_compound; ++ref) {
+#if CONFIG_REF_MV
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[ref]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[ref]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+#endif
#if CONFIG_EXT_INTER
- {
if (mode == NEWFROMNEARMV)
vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][1].as_mv,
@@ -1108,13 +1137,25 @@
vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv, nmvc,
allow_hp);
-#if CONFIG_EXT_INTER
}
+#if CONFIG_EXT_INTER
} else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
+#if CONFIG_REF_MV
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[1]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[1]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+#endif
vp10_encode_mv(cpi, w, &mbmi->mv[1].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv, nmvc,
allow_hp);
} else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
+#if CONFIG_REF_MV
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[0]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[0]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+#endif
vp10_encode_mv(cpi, w, &mbmi->mv[0].as_mv,
&mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv, nmvc,
allow_hp);
@@ -2449,7 +2490,11 @@
counts->y_mode[i], INTRA_MODES, &header_bc);
vp10_write_nmv_probs(cm, cm->allow_high_precision_mv, &header_bc,
- &counts->mv);
+#if CONFIG_REF_MV
+ counts->mv);
+#else
+ &counts->mv);
+#endif
update_ext_tx_probs(cm, &header_bc);
#if CONFIG_SUPERTX
if (!xd->lossless[0])
diff --git a/vp10/encoder/block.h b/vp10/encoder/block.h
index a81627c..7921300 100644
--- a/vp10/encoder/block.h
+++ b/vp10/encoder/block.h
@@ -110,12 +110,21 @@
unsigned int pred_sse[MAX_REF_FRAMES];
int pred_mv_sad[MAX_REF_FRAMES];
+#if CONFIG_REF_MV
+ int *nmvjointcost;
+ int nmv_vec_cost[NMV_CONTEXTS][MV_JOINTS];
+ int *nmvcost[NMV_CONTEXTS][2];
+ int *nmvcost_hp[NMV_CONTEXTS][2];
+ int **mv_cost_stack[NMV_CONTEXTS];
+ int *nmvjointsadcost;
+#else
int nmvjointcost[MV_JOINTS];
int *nmvcost[2];
int *nmvcost_hp[2];
- int **mvcost;
-
int nmvjointsadcost[MV_JOINTS];
+#endif
+
+ int **mvcost;
int *nmvsadcost[2];
int *nmvsadcost_hp[2];
int **mvsadcost;
diff --git a/vp10/encoder/cost.c b/vp10/encoder/cost.c
index 7e33edf..0ed4140 100644
--- a/vp10/encoder/cost.c
+++ b/vp10/encoder/cost.c
@@ -13,9 +13,8 @@
#include "vp10/common/entropy.h"
/* round(-log2(i/256.) * (1 << VP9_PROB_COST_SHIFT))
- Begins and ends with a bogus entry to satisfy use of prob=0 in the firstpass.
- https://code.google.com/p/webm/issues/detail?id=1089 */
-const uint16_t vp10_prob_cost[257] = {
+ Begins with a bogus entry for simpler addressing. */
+const uint16_t vp10_prob_cost[256] = {
4096, 4096, 3584, 3284, 3072, 2907, 2772, 2659, 2560, 2473, 2395, 2325,
2260, 2201, 2147, 2096, 2048, 2003, 1961, 1921, 1883, 1847, 1813, 1780,
1748, 1718, 1689, 1661, 1635, 1609, 1584, 1559, 1536, 1513, 1491, 1470,
@@ -37,13 +36,14 @@
125, 122, 119, 115, 112, 109, 105, 102, 99, 95, 92, 89,
86, 82, 79, 76, 73, 70, 66, 63, 60, 57, 54, 51,
48, 45, 42, 38, 35, 32, 29, 26, 23, 20, 18, 15,
- 12, 9, 6, 3, 3};
+ 12, 9, 6, 3};
static void cost(int *costs, vpx_tree tree, const vpx_prob *probs,
int i, int c) {
const vpx_prob prob = probs[i / 2];
int b;
+ assert(prob != 0);
for (b = 0; b <= 1; ++b) {
const int cc = c + vp10_cost_bit(prob, b);
const vpx_tree_index ii = tree[i + b];
diff --git a/vp10/encoder/cost.h b/vp10/encoder/cost.h
index d4a9efb..56d9100 100644
--- a/vp10/encoder/cost.h
+++ b/vp10/encoder/cost.h
@@ -18,7 +18,7 @@
extern "C" {
#endif
-extern const uint16_t vp10_prob_cost[257];
+extern const uint16_t vp10_prob_cost[256];
// The factor to scale from cost in bits to cost in vp10_prob_cost units.
#define VP9_PROB_COST_SHIFT 9
diff --git a/vp10/encoder/encodemv.c b/vp10/encoder/encodemv.c
index 4124c4a..61429aa 100644
--- a/vp10/encoder/encodemv.c
+++ b/vp10/encoder/encodemv.c
@@ -157,9 +157,49 @@
}
void vp10_write_nmv_probs(VP10_COMMON *cm, int usehp, vpx_writer *w,
- nmv_context_counts *const counts) {
+ nmv_context_counts *const nmv_counts) {
int i, j;
+#if CONFIG_REF_MV
+ int nmv_ctx = 0;
+ for (nmv_ctx = 0; nmv_ctx < NMV_CONTEXTS; ++nmv_ctx) {
+ nmv_context *const mvc = &cm->fc->nmvc[nmv_ctx];
+ nmv_context_counts *const counts = &nmv_counts[nmv_ctx];
+ write_mv_update(vp10_mv_joint_tree, mvc->joints, counts->joints,
+ MV_JOINTS, w);
+
+ for (i = 0; i < 2; ++i) {
+ nmv_component *comp = &mvc->comps[i];
+ nmv_component_counts *comp_counts = &counts->comps[i];
+
+ update_mv(w, comp_counts->sign, &comp->sign, MV_UPDATE_PROB);
+ write_mv_update(vp10_mv_class_tree, comp->classes, comp_counts->classes,
+ MV_CLASSES, w);
+ write_mv_update(vp10_mv_class0_tree, comp->class0, comp_counts->class0,
+ CLASS0_SIZE, w);
+ for (j = 0; j < MV_OFFSET_BITS; ++j)
+ update_mv(w, comp_counts->bits[j], &comp->bits[j], MV_UPDATE_PROB);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ for (j = 0; j < CLASS0_SIZE; ++j)
+ write_mv_update(vp10_mv_fp_tree, mvc->comps[i].class0_fp[j],
+ counts->comps[i].class0_fp[j], MV_FP_SIZE, w);
+
+ write_mv_update(vp10_mv_fp_tree, mvc->comps[i].fp, counts->comps[i].fp,
+ MV_FP_SIZE, w);
+ }
+
+ if (usehp) {
+ for (i = 0; i < 2; ++i) {
+ update_mv(w, counts->comps[i].class0_hp, &mvc->comps[i].class0_hp,
+ MV_UPDATE_PROB);
+ update_mv(w, counts->comps[i].hp, &mvc->comps[i].hp, MV_UPDATE_PROB);
+ }
+ }
+ }
+#else
nmv_context *const mvc = &cm->fc->nmvc;
+ nmv_context_counts *const counts = nmv_counts;
write_mv_update(vp10_mv_joint_tree, mvc->joints, counts->joints, MV_JOINTS, w);
@@ -192,6 +232,7 @@
update_mv(w, counts->comps[i].hp, &mvc->comps[i].hp, MV_UPDATE_PROB);
}
}
+#endif
}
void vp10_encode_mv(VP10_COMP* cpi, vpx_writer* w,
@@ -227,27 +268,45 @@
#if CONFIG_EXT_INTER
static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
const int_mv mvs[2],
- nmv_context_counts *counts) {
+ nmv_context_counts *nmv_counts) {
int i;
PREDICTION_MODE mode = mbmi->mode;
int mv_idx = (mode == NEWFROMNEARMV);
+#if !CONFIG_REF_MV
+ nmv_context_counts *counts = nmv_counts;
+#endif
if (mode == NEWMV || mode == NEWFROMNEARMV || mode == NEW_NEWMV) {
for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][mv_idx].as_mv;
const MV diff = {mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col};
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[i]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[i]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
} else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv;
const MV diff = {mvs[1].as_mv.row - ref->row,
mvs[1].as_mv.col - ref->col};
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[1]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[1]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
} else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv;
const MV diff = {mvs[0].as_mv.row - ref->row,
mvs[0].as_mv.col - ref->col};
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[0]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[0]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
}
@@ -255,36 +314,67 @@
static void inc_mvs_sub8x8(const MODE_INFO *mi,
int block,
const int_mv mvs[2],
- nmv_context_counts *counts) {
+#if CONFIG_REF_MV
+ const MB_MODE_INFO_EXT *mbmi_ext,
+#endif
+ nmv_context_counts *nmv_counts) {
int i;
PREDICTION_MODE mode = mi->bmi[block].as_mode;
+#if CONFIG_REF_MV
+ const MB_MODE_INFO *mbmi = &mi->mbmi;
+#else
+ nmv_context_counts *counts = nmv_counts;
+#endif
if (mode == NEWMV || mode == NEWFROMNEARMV || mode == NEW_NEWMV) {
for (i = 0; i < 1 + has_second_ref(&mi->mbmi); ++i) {
const MV *ref = &mi->bmi[block].ref_mv[i].as_mv;
const MV diff = {mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col};
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[i]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[i]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
} else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
const MV *ref = &mi->bmi[block].ref_mv[1].as_mv;
const MV diff = {mvs[1].as_mv.row - ref->row,
mvs[1].as_mv.col - ref->col};
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[1]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[1]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
} else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
const MV *ref = &mi->bmi[block].ref_mv[0].as_mv;
const MV diff = {mvs[0].as_mv.row - ref->row,
mvs[0].as_mv.col - ref->col};
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[0]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[0]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref));
}
}
#else
static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
const int_mv mvs[2],
- nmv_context_counts *counts) {
+ nmv_context_counts *nmv_counts) {
int i;
+#if !CONFIG_REF_MV
+ nmv_context_counts *counts = nmv_counts;
+#endif
for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
+#if CONFIG_REF_MV
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[i]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[i]]);
+ nmv_context_counts *counts = &nmv_counts[nmv_ctx];
+#endif
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_mv;
const MV diff = {mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col};
@@ -310,10 +400,21 @@
#if CONFIG_EXT_INTER
if (have_newmv_in_inter_mode(mi->bmi[i].as_mode))
- inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, &td->counts->mv);
+ inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv,
+#if CONFIG_REF_MV
+ mbmi_ext,
+ td->counts->mv);
+#else
+ &td->counts->mv);
+#endif
#else
if (mi->bmi[i].as_mode == NEWMV)
- inc_mvs(mbmi, mbmi_ext, mi->bmi[i].as_mv, &td->counts->mv);
+ inc_mvs(mbmi, mbmi_ext, mi->bmi[i].as_mv,
+#if CONFIG_REF_MV
+ td->counts->mv);
+#else
+ &td->counts->mv);
+#endif
#endif // CONFIG_EXT_INTER
}
}
@@ -323,7 +424,12 @@
#else
if (mbmi->mode == NEWMV)
#endif // CONFIG_EXT_INTER
- inc_mvs(mbmi, mbmi_ext, mbmi->mv, &td->counts->mv);
+ inc_mvs(mbmi, mbmi_ext, mbmi->mv,
+#if CONFIG_REF_MV
+ td->counts->mv);
+#else
+ &td->counts->mv);
+#endif
}
}
diff --git a/vp10/encoder/encodemv.h b/vp10/encoder/encodemv.h
index 006f6d7..c753d34 100644
--- a/vp10/encoder/encodemv.h
+++ b/vp10/encoder/encodemv.h
@@ -21,7 +21,7 @@
void vp10_entropy_mv_init(void);
void vp10_write_nmv_probs(VP10_COMMON *cm, int usehp, vpx_writer *w,
- nmv_context_counts *const counts);
+ nmv_context_counts *const counts);
void vp10_encode_mv(VP10_COMP *cpi, vpx_writer* w, const MV* mv, const MV* ref,
const nmv_context* mvctx, int usehp);
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index 4f97c79..3f1dcf8 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -50,7 +50,7 @@
#include "./vp10_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "./vpx_scale_rtcd.h"
-#include "vpx/internal/vpx_psnr.h"
+#include "vpx_dsp/psnr.h"
#if CONFIG_INTERNAL_STATS
#include "vpx_dsp/ssim.h"
#endif
@@ -222,6 +222,22 @@
void vp10_set_high_precision_mv(VP10_COMP *cpi, int allow_high_precision_mv) {
MACROBLOCK *const mb = &cpi->td.mb;
cpi->common.allow_high_precision_mv = allow_high_precision_mv;
+
+#if CONFIG_REF_MV
+ if (cpi->common.allow_high_precision_mv) {
+ int i;
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ mb->mv_cost_stack[i] = mb->nmvcost_hp[i];
+ mb->mvsadcost = mb->nmvsadcost_hp;
+ }
+ } else {
+ int i;
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ mb->mv_cost_stack[i] = mb->nmvcost[i];
+ mb->mvsadcost = mb->nmvsadcost;
+ }
+ }
+#else
if (cpi->common.allow_high_precision_mv) {
mb->mvcost = mb->nmvcost_hp;
mb->mvsadcost = mb->nmvsadcost_hp;
@@ -229,6 +245,7 @@
mb->mvcost = mb->nmvcost;
mb->mvsadcost = mb->nmvsadcost;
}
+#endif
}
static void setup_frame(VP10_COMP *cpi) {
@@ -338,6 +355,9 @@
static void dealloc_compressor_data(VP10_COMP *cpi) {
VP10_COMMON *const cm = &cpi->common;
+#if CONFIG_REF_MV
+ int i;
+#endif
vpx_free(cpi->mbmi_ext_base);
cpi->mbmi_ext_base = NULL;
@@ -351,6 +371,19 @@
vpx_free(cpi->coding_context.last_frame_seg_map_copy);
cpi->coding_context.last_frame_seg_map_copy = NULL;
+#if CONFIG_REF_MV
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ vpx_free(cpi->nmv_costs[i][0]);
+ vpx_free(cpi->nmv_costs[i][1]);
+ vpx_free(cpi->nmv_costs_hp[i][0]);
+ vpx_free(cpi->nmv_costs_hp[i][1]);
+ cpi->nmv_costs[i][0] = NULL;
+ cpi->nmv_costs[i][1] = NULL;
+ cpi->nmv_costs_hp[i][0] = NULL;
+ cpi->nmv_costs_hp[i][1] = NULL;
+ }
+#endif
+
vpx_free(cpi->nmvcosts[0]);
vpx_free(cpi->nmvcosts[1]);
cpi->nmvcosts[0] = NULL;
@@ -412,12 +445,29 @@
static void save_coding_context(VP10_COMP *cpi) {
CODING_CONTEXT *const cc = &cpi->coding_context;
VP10_COMMON *cm = &cpi->common;
+#if CONFIG_REF_MV
+ int i;
+#endif
// Stores a snapshot of key state variables which can subsequently be
// restored with a call to vp10_restore_coding_context. These functions are
// intended for use in a re-code loop in vp10_compress_frame where the
// quantizer value is adjusted between loop iterations.
+#if CONFIG_REF_MV
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ vp10_copy(cc->nmv_vec_cost[i], cpi->td.mb.nmv_vec_cost[i]);
+ memcpy(cc->nmv_costs[i][0], cpi->nmv_costs[i][0],
+ MV_VALS * sizeof(*cpi->nmv_costs[i][0]));
+ memcpy(cc->nmv_costs[i][1], cpi->nmv_costs[i][1],
+ MV_VALS * sizeof(*cpi->nmv_costs[i][1]));
+ memcpy(cc->nmv_costs_hp[i][0], cpi->nmv_costs_hp[i][0],
+ MV_VALS * sizeof(*cpi->nmv_costs_hp[i][0]));
+ memcpy(cc->nmv_costs_hp[i][1], cpi->nmv_costs_hp[i][1],
+ MV_VALS * sizeof(*cpi->nmv_costs_hp[i][1]));
+ }
+#else
vp10_copy(cc->nmvjointcost, cpi->td.mb.nmvjointcost);
+#endif
memcpy(cc->nmvcosts[0], cpi->nmvcosts[0],
MV_VALS * sizeof(*cpi->nmvcosts[0]));
@@ -440,10 +490,27 @@
static void restore_coding_context(VP10_COMP *cpi) {
CODING_CONTEXT *const cc = &cpi->coding_context;
VP10_COMMON *cm = &cpi->common;
+#if CONFIG_REF_MV
+ int i;
+#endif
// Restore key state variables to the snapshot state stored in the
// previous call to vp10_save_coding_context.
+#if CONFIG_REF_MV
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ vp10_copy(cpi->td.mb.nmv_vec_cost[i], cc->nmv_vec_cost[i]);
+ memcpy(cpi->nmv_costs[i][0], cc->nmv_costs[i][0],
+ MV_VALS * sizeof(*cc->nmv_costs[i][0]));
+ memcpy(cpi->nmv_costs[i][1], cc->nmv_costs[i][1],
+ MV_VALS * sizeof(*cc->nmv_costs[i][1]));
+ memcpy(cpi->nmv_costs_hp[i][0], cc->nmv_costs_hp[i][0],
+ MV_VALS * sizeof(*cc->nmv_costs_hp[i][0]));
+ memcpy(cpi->nmv_costs_hp[i][1], cc->nmv_costs_hp[i][1],
+ MV_VALS * sizeof(*cc->nmv_costs_hp[i][1]));
+ }
+#else
vp10_copy(cpi->td.mb.nmvjointcost, cc->nmvjointcost);
+#endif
memcpy(cpi->nmvcosts[0], cc->nmvcosts[0], MV_VALS * sizeof(*cc->nmvcosts[0]));
memcpy(cpi->nmvcosts[1], cc->nmvcosts[1], MV_VALS * sizeof(*cc->nmvcosts[1]));
@@ -1560,12 +1627,14 @@
#endif
#define log2f(x) (log (x) / (float) M_LOG2_E)
+#if !CONFIG_REF_MV
static void cal_nmvjointsadcost(int *mvjointsadcost) {
mvjointsadcost[0] = 600;
mvjointsadcost[1] = 300;
mvjointsadcost[2] = 300;
mvjointsadcost[3] = 300;
}
+#endif
static void cal_nmvsadcosts(int *mvsadcost[2]) {
int i = 1;
@@ -1640,6 +1709,19 @@
realloc_segmentation_maps(cpi);
+#if CONFIG_REF_MV
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ CHECK_MEM_ERROR(cm, cpi->nmv_costs[i][0],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmv_costs[i][0])));
+ CHECK_MEM_ERROR(cm, cpi->nmv_costs[i][1],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmv_costs[i][1])));
+ CHECK_MEM_ERROR(cm, cpi->nmv_costs_hp[i][0],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmv_costs_hp[i][0])));
+ CHECK_MEM_ERROR(cm, cpi->nmv_costs_hp[i][1],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmv_costs_hp[i][1])));
+ }
+#endif
+
CHECK_MEM_ERROR(cm, cpi->nmvcosts[0],
vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts[0])));
CHECK_MEM_ERROR(cm, cpi->nmvcosts[1],
@@ -1714,15 +1796,24 @@
cpi->first_time_stamp_ever = INT64_MAX;
+#if CONFIG_REF_MV
+ for (i = 0; i < NMV_CONTEXTS; ++i) {
+ cpi->td.mb.nmvcost[i][0] = &cpi->nmv_costs[i][0][MV_MAX];
+ cpi->td.mb.nmvcost[i][1] = &cpi->nmv_costs[i][1][MV_MAX];
+ cpi->td.mb.nmvcost_hp[i][0] = &cpi->nmv_costs_hp[i][0][MV_MAX];
+ cpi->td.mb.nmvcost_hp[i][1] = &cpi->nmv_costs_hp[i][1][MV_MAX];
+ }
+#else
cal_nmvjointsadcost(cpi->td.mb.nmvjointsadcost);
cpi->td.mb.nmvcost[0] = &cpi->nmvcosts[0][MV_MAX];
cpi->td.mb.nmvcost[1] = &cpi->nmvcosts[1][MV_MAX];
+ cpi->td.mb.nmvcost_hp[0] = &cpi->nmvcosts_hp[0][MV_MAX];
+ cpi->td.mb.nmvcost_hp[1] = &cpi->nmvcosts_hp[1][MV_MAX];
+#endif
cpi->td.mb.nmvsadcost[0] = &cpi->nmvsadcosts[0][MV_MAX];
cpi->td.mb.nmvsadcost[1] = &cpi->nmvsadcosts[1][MV_MAX];
cal_nmvsadcosts(cpi->td.mb.nmvsadcost);
- cpi->td.mb.nmvcost_hp[0] = &cpi->nmvcosts_hp[0][MV_MAX];
- cpi->td.mb.nmvcost_hp[1] = &cpi->nmvcosts_hp[1][MV_MAX];
cpi->td.mb.nmvsadcost_hp[0] = &cpi->nmvsadcosts_hp[0][MV_MAX];
cpi->td.mb.nmvsadcost_hp[1] = &cpi->nmvsadcosts_hp[1][MV_MAX];
cal_nmvsadcosts_hp(cpi->td.mb.nmvsadcost_hp);
@@ -2033,271 +2124,16 @@
#endif
}
-/* 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
-
-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;
-
-#if CONFIG_VP9_HIGHBITDEPTH
-static void calc_highbd_psnr(const YV12_BUFFER_CONFIG *a,
- const YV12_BUFFER_CONFIG *b,
- PSNR_STATS *psnr,
- unsigned int bit_depth,
- unsigned int 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) {
- const int w = widths[i];
- const int h = heights[i];
- const uint32_t samples = w * h;
- uint64_t sse;
- if (a->flags & YV12_FLAG_HIGHBITDEPTH) {
- if (input_shift) {
- sse = highbd_get_sse_shift(a_planes[i], a_strides[i],
- b_planes[i], b_strides[i], w, h,
- input_shift);
- } else {
- sse = highbd_get_sse(a_planes[i], a_strides[i],
- b_planes[i], b_strides[i], w, h);
- }
- } else {
- sse = get_sse(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] = vpx_sse_to_psnr(samples, peak, (double)sse);
-
- total_sse += sse;
- total_samples += samples;
- }
-
- psnr->sse[0] = total_sse;
- psnr->samples[0] = total_samples;
- psnr->psnr[0] = vpx_sse_to_psnr((double)total_samples, peak,
- (double)total_sse);
-}
-
-#else // !CONFIG_VP9_HIGHBITDEPTH
-
-static void calc_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b,
- PSNR_STATS *psnr) {
- static const double peak = 255.0;
- 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;
-
- for (i = 0; i < 3; ++i) {
- const int w = widths[i];
- const int h = heights[i];
- const uint32_t samples = w * h;
- const uint64_t sse = get_sse(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] = vpx_sse_to_psnr(samples, peak, (double)sse);
-
- total_sse += sse;
- total_samples += samples;
- }
-
- psnr->sse[0] = total_sse;
- psnr->samples[0] = total_samples;
- psnr->psnr[0] = vpx_sse_to_psnr((double)total_samples, peak,
- (double)total_sse);
-}
-#endif // CONFIG_VP9_HIGHBITDEPTH
static void generate_psnr_packet(VP10_COMP *cpi) {
struct vpx_codec_cx_pkt pkt;
int i;
PSNR_STATS psnr;
#if CONFIG_VP9_HIGHBITDEPTH
- calc_highbd_psnr(cpi->Source, cpi->common.frame_to_show, &psnr,
- cpi->td.mb.e_mbd.bd, cpi->oxcf.input_bit_depth);
+ vpx_calc_highbd_psnr(cpi->Source, cpi->common.frame_to_show, &psnr,
+ cpi->td.mb.e_mbd.bd, cpi->oxcf.input_bit_depth);
#else
- calc_psnr(cpi->Source, cpi->common.frame_to_show, &psnr);
+ vpx_calc_psnr(cpi->Source, cpi->common.frame_to_show, &psnr);
#endif
for (i = 0; i < 4; ++i) {
@@ -2955,7 +2791,7 @@
vpx_clear_system_state();
- recon_err = vp10_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ recon_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
if (cpi->twopass.total_left_stats.coded_error != 0.0)
fprintf(f, "%10u %dx%d %10d %10d %d %d %10d %10d %10d %10d"
@@ -3380,12 +3216,12 @@
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- kf_err = vp10_highbd_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ kf_err = vpx_highbd_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
} else {
- kf_err = vp10_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ kf_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
}
#else
- kf_err = vp10_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ kf_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
#endif // CONFIG_VP9_HIGHBITDEPTH
// Prevent possible divide by zero error below for perfect KF
@@ -3804,13 +3640,13 @@
if (cpi->rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- cpi->ambient_err = vp10_highbd_get_y_sse(cpi->Source,
+ cpi->ambient_err = vpx_highbd_get_y_sse(cpi->Source,
get_frame_new_buffer(cm));
} else {
- cpi->ambient_err = vp10_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ cpi->ambient_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
}
#else
- cpi->ambient_err = vp10_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ cpi->ambient_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
#endif // CONFIG_VP9_HIGHBITDEPTH
}
@@ -4193,9 +4029,9 @@
vpx_clear_system_state();
// TODO(yaowu): unify these two versions into one.
#if CONFIG_VP9_HIGHBITDEPTH
- calc_highbd_psnr(orig, recon, &psnr, cpi->td.mb.e_mbd.bd, in_bit_depth);
+ vpx_calc_highbd_psnr(orig, recon, &psnr, bit_depth, in_bit_depth);
#else
- calc_psnr(orig, recon, &psnr);
+ vpx_calc_psnr(orig, recon, &psnr);
#endif // CONFIG_VP9_HIGHBITDEPTH
adjust_image_stat(psnr.psnr[1], psnr.psnr[2], psnr.psnr[3],
@@ -4259,9 +4095,10 @@
}
}
- frame_all = vpx_calc_fastssim(orig, recon, &y, &u, &v, bit_depth);
+ frame_all = vpx_calc_fastssim(orig, recon, &y, &u, &v,
+ bit_depth, in_bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
- frame_all = vpx_psnrhvs(orig, recon, &y, &u, &v, bit_depth);
+ frame_all = vpx_psnrhvs(orig, recon, &y, &u, &v, bit_depth, in_bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
@@ -4557,28 +4394,6 @@
return 0;
}
-int64_t vp10_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 vp10_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
-
int vp10_get_quantizer(VP10_COMP *cpi) {
return cpi->common.base_qindex;
}
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index cc20765..292494c 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -55,6 +55,12 @@
int nmvcosts[2][MV_VALS];
int nmvcosts_hp[2][MV_VALS];
+#if CONFIG_REF_MV
+ int nmv_vec_cost[NMV_CONTEXTS][MV_JOINTS];
+ int nmv_costs[NMV_CONTEXTS][2][MV_VALS];
+ int nmv_costs_hp[NMV_CONTEXTS][2][MV_VALS];
+#endif
+
unsigned char *last_frame_seg_map_copy;
// 0 = Intra, Last, GF, ARF
@@ -352,6 +358,11 @@
CODING_CONTEXT coding_context;
+#if CONFIG_REF_MV
+ int *nmv_costs[NMV_CONTEXTS][2];
+ int *nmv_costs_hp[NMV_CONTEXTS][2];
+#endif
+
int *nmvcosts[2];
int *nmvcosts_hp[2];
int *nmvsadcosts[2];
@@ -633,12 +644,6 @@
return get_token_alloc(tile_mb_rows, tile_mb_cols);
}
-int64_t vp10_get_y_sse(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b);
-#if CONFIG_VP9_HIGHBITDEPTH
-int64_t vp10_highbd_get_y_sse(const YV12_BUFFER_CONFIG *a,
- const YV12_BUFFER_CONFIG *b);
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
void vp10_alloc_compressor_data(VP10_COMP *cpi);
void vp10_scale_references(VP10_COMP *cpi);
diff --git a/vp10/encoder/hybrid_fwd_txfm.c b/vp10/encoder/hybrid_fwd_txfm.c
index 0f59259..6507f98 100644
--- a/vp10/encoder/hybrid_fwd_txfm.c
+++ b/vp10/encoder/hybrid_fwd_txfm.c
@@ -69,8 +69,6 @@
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
- vp10_fht4x4(src_diff, coeff, diff_stride, tx_type);
- break;
case DST_DST:
case DCT_DST:
case DST_DCT:
@@ -78,8 +76,7 @@
case ADST_DST:
case DST_FLIPADST:
case FLIPADST_DST:
- // Use C version since DST exists only in C
- vp10_fht4x4_c(src_diff, coeff, diff_stride, tx_type);
+ vp10_fht4x4(src_diff, coeff, diff_stride, tx_type);
break;
case IDTX:
fwd_idtx_c(src_diff, coeff, diff_stride, 4);
diff --git a/vp10/encoder/mcomp.c b/vp10/encoder/mcomp.c
index dd19e02..6e3b06a 100644
--- a/vp10/encoder/mcomp.c
+++ b/vp10/encoder/mcomp.c
@@ -97,12 +97,22 @@
static int mvsad_err_cost(const MACROBLOCK *x, const MV *mv, const MV *ref,
int sad_per_bit) {
+#if CONFIG_REF_MV
+ const MV diff = { (mv->row - ref->row) << 3,
+ (mv->col - ref->col) << 3 };
+ return ROUND_POWER_OF_TWO(
+ (unsigned)mv_cost(&diff, x->nmvjointsadcost, x->mvsadcost) *
+ sad_per_bit,
+ VP9_PROB_COST_SHIFT);
+#else
const MV diff = { mv->row - ref->row,
mv->col - ref->col };
+
return ROUND_POWER_OF_TWO(
(unsigned)mv_cost(&diff, x->nmvjointsadcost, x->nmvsadcost) *
sad_per_bit,
VP9_PROB_COST_SHIFT);
+#endif
}
void vp10_init_dsmotion_compensation(search_site_config *cfg, int stride) {
diff --git a/vp10/encoder/picklpf.c b/vp10/encoder/picklpf.c
index f116c00..cb2c1c7 100644
--- a/vp10/encoder/picklpf.c
+++ b/vp10/encoder/picklpf.c
@@ -13,6 +13,7 @@
#include "./vpx_scale_rtcd.h"
+#include "vpx_dsp/psnr.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
@@ -56,12 +57,12 @@
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- filt_err = vp10_highbd_get_y_sse(sd, cm->frame_to_show);
+ filt_err = vpx_highbd_get_y_sse(sd, cm->frame_to_show);
} else {
- filt_err = vp10_get_y_sse(sd, cm->frame_to_show);
+ filt_err = vpx_get_y_sse(sd, cm->frame_to_show);
}
#else
- filt_err = vp10_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
diff --git a/vp10/encoder/pickrst.c b/vp10/encoder/pickrst.c
index 79cda43..9982836 100644
--- a/vp10/encoder/pickrst.c
+++ b/vp10/encoder/pickrst.c
@@ -14,6 +14,7 @@
#include "./vpx_scale_rtcd.h"
+#include "vpx_dsp/psnr.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
@@ -36,12 +37,12 @@
rsi, 1, partial_frame);
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- filt_err = vp10_highbd_get_y_sse(sd, cm->frame_to_show);
+ filt_err = vpx_highbd_get_y_sse(sd, cm->frame_to_show);
} else {
- filt_err = vp10_get_y_sse(sd, cm->frame_to_show);
+ filt_err = vpx_get_y_sse(sd, cm->frame_to_show);
}
#else
- filt_err = vp10_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
diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c
index bf73064..044ced1 100644
--- a/vp10/encoder/rd.c
+++ b/vp10/encoder/rd.c
@@ -331,6 +331,18 @@
}
}
+#if CONFIG_REF_MV
+void vp10_set_mvcost(MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame) {
+ MB_MODE_INFO_EXT *mbmi_ext = x->mbmi_ext;
+ int nmv_ctx = vp10_nmv_ctx(mbmi_ext->ref_mv_count[ref_frame],
+ mbmi_ext->ref_mv_stack[ref_frame]);
+ x->mvcost = x->mv_cost_stack[nmv_ctx];
+ x->nmvjointcost = x->nmv_vec_cost[nmv_ctx];
+ x->mvsadcost = x->mvcost;
+ x->nmvjointsadcost = x->nmvjointcost;
+}
+#endif
+
void vp10_initialize_rd_consts(VP10_COMP *cpi) {
VP10_COMMON *const cm = &cpi->common;
MACROBLOCK *const x = &cpi->td.mb;
@@ -349,68 +361,87 @@
set_block_thresholds(cm, rd);
- fill_token_costs(x->token_costs, cm->fc->coef_probs);
-
- if (cpi->sf.partition_search_type != VAR_BASED_PARTITION ||
- cm->frame_type == KEY_FRAME) {
- for (i = 0; i < PARTITION_CONTEXTS; ++i)
- vp10_cost_tokens(cpi->partition_cost[i], cm->fc->partition_prob[i],
- vp10_partition_tree);
- }
-
- fill_mode_costs(cpi);
-
if (!frame_is_intra_only(cm)) {
- vp10_build_nmv_cost_table(x->nmvjointcost,
- cm->allow_high_precision_mv ? x->nmvcost_hp
- : x->nmvcost,
- &cm->fc->nmvc, cm->allow_high_precision_mv);
#if CONFIG_REF_MV
- for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i) {
- cpi->newmv_mode_cost[i][0] = vp10_cost_bit(cm->fc->newmv_prob[i], 0);
- cpi->newmv_mode_cost[i][1] = vp10_cost_bit(cm->fc->newmv_prob[i], 1);
+ int nmv_ctx;
+ for (nmv_ctx = 0; nmv_ctx < NMV_CONTEXTS; ++nmv_ctx) {
+ vp10_build_nmv_cost_table(
+ x->nmv_vec_cost[nmv_ctx],
+ cm->allow_high_precision_mv ? x->nmvcost_hp[nmv_ctx]
+ : x->nmvcost[nmv_ctx],
+ &cm->fc->nmvc[nmv_ctx], cm->allow_high_precision_mv);
+ }
+ x->mvcost = x->mv_cost_stack[0];
+ x->nmvjointcost = x->nmv_vec_cost[0];
+ x->mvsadcost = x->mvcost;
+ x->nmvjointsadcost = x->nmvjointcost;
+#else
+ vp10_build_nmv_cost_table(
+ x->nmvjointcost,
+ cm->allow_high_precision_mv ? x->nmvcost_hp : x->nmvcost, &cm->fc->nmvc,
+ cm->allow_high_precision_mv);
+#endif
+ }
+ if (cpi->oxcf.pass != 1) {
+ fill_token_costs(x->token_costs, cm->fc->coef_probs);
+
+ if (cpi->sf.partition_search_type != VAR_BASED_PARTITION ||
+ cm->frame_type == KEY_FRAME) {
+ for (i = 0; i < PARTITION_CONTEXTS; ++i)
+ vp10_cost_tokens(cpi->partition_cost[i], cm->fc->partition_prob[i],
+ vp10_partition_tree);
}
- for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i) {
- cpi->zeromv_mode_cost[i][0] = vp10_cost_bit(cm->fc->zeromv_prob[i], 0);
- cpi->zeromv_mode_cost[i][1] = vp10_cost_bit(cm->fc->zeromv_prob[i], 1);
- }
+ fill_mode_costs(cpi);
- for (i = 0; i < REFMV_MODE_CONTEXTS; ++i) {
- cpi->refmv_mode_cost[i][0] = vp10_cost_bit(cm->fc->refmv_prob[i], 0);
- cpi->refmv_mode_cost[i][1] = vp10_cost_bit(cm->fc->refmv_prob[i], 1);
- }
+ if (!frame_is_intra_only(cm)) {
+#if CONFIG_REF_MV
+ for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i) {
+ cpi->newmv_mode_cost[i][0] = vp10_cost_bit(cm->fc->newmv_prob[i], 0);
+ cpi->newmv_mode_cost[i][1] = vp10_cost_bit(cm->fc->newmv_prob[i], 1);
+ }
- for (i = 0; i < DRL_MODE_CONTEXTS; ++i) {
- cpi->drl_mode_cost0[i][0] = vp10_cost_bit(cm->fc->drl_prob0[i], 0);
- cpi->drl_mode_cost0[i][1] = vp10_cost_bit(cm->fc->drl_prob0[i], 1);
- }
+ for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i) {
+ cpi->zeromv_mode_cost[i][0] = vp10_cost_bit(cm->fc->zeromv_prob[i], 0);
+ cpi->zeromv_mode_cost[i][1] = vp10_cost_bit(cm->fc->zeromv_prob[i], 1);
+ }
- for (i = 0; i < DRL_MODE_CONTEXTS; ++i) {
- cpi->drl_mode_cost1[i][0] = vp10_cost_bit(cm->fc->drl_prob1[i], 0);
- cpi->drl_mode_cost1[i][1] = vp10_cost_bit(cm->fc->drl_prob1[i], 1);
- }
+ for (i = 0; i < REFMV_MODE_CONTEXTS; ++i) {
+ cpi->refmv_mode_cost[i][0] = vp10_cost_bit(cm->fc->refmv_prob[i], 0);
+ cpi->refmv_mode_cost[i][1] = vp10_cost_bit(cm->fc->refmv_prob[i], 1);
+ }
+
+ for (i = 0; i < DRL_MODE_CONTEXTS; ++i) {
+ cpi->drl_mode_cost0[i][0] = vp10_cost_bit(cm->fc->drl_prob0[i], 0);
+ cpi->drl_mode_cost0[i][1] = vp10_cost_bit(cm->fc->drl_prob0[i], 1);
+ }
+
+ for (i = 0; i < DRL_MODE_CONTEXTS; ++i) {
+ cpi->drl_mode_cost1[i][0] = vp10_cost_bit(cm->fc->drl_prob1[i], 0);
+ cpi->drl_mode_cost1[i][1] = vp10_cost_bit(cm->fc->drl_prob1[i], 1);
+ }
#if CONFIG_EXT_INTER
- cpi->new2mv_mode_cost[0] = vp10_cost_bit(cm->fc->new2mv_prob, 0);
- cpi->new2mv_mode_cost[1] = vp10_cost_bit(cm->fc->new2mv_prob, 1);
+ cpi->new2mv_mode_cost[0] = vp10_cost_bit(cm->fc->new2mv_prob, 0);
+ cpi->new2mv_mode_cost[1] = vp10_cost_bit(cm->fc->new2mv_prob, 1);
#endif // CONFIG_EXT_INTER
#else
- for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
- vp10_cost_tokens((int *)cpi->inter_mode_cost[i],
- cm->fc->inter_mode_probs[i], vp10_inter_mode_tree);
+ for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
+ vp10_cost_tokens((int *)cpi->inter_mode_cost[i],
+ cm->fc->inter_mode_probs[i], vp10_inter_mode_tree);
#endif
#if CONFIG_EXT_INTER
- for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
- vp10_cost_tokens((int *)cpi->inter_compound_mode_cost[i],
- cm->fc->inter_compound_mode_probs[i],
- vp10_inter_compound_mode_tree);
+ for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
+ vp10_cost_tokens((int *)cpi->inter_compound_mode_cost[i],
+ cm->fc->inter_compound_mode_probs[i],
+ vp10_inter_compound_mode_tree);
#endif // CONFIG_EXT_INTER
#if CONFIG_OBMC
- for (i = BLOCK_8X8; i < BLOCK_SIZES; i++) {
- cpi->obmc_cost[i][0] = vp10_cost_bit(cm->fc->obmc_prob[i], 0);
- cpi->obmc_cost[i][1] = vp10_cost_bit(cm->fc->obmc_prob[i], 1);
- }
+ for (i = BLOCK_8X8; i < BLOCK_SIZES; i++) {
+ cpi->obmc_cost[i][0] = vp10_cost_bit(cm->fc->obmc_prob[i], 0);
+ cpi->obmc_cost[i][1] = vp10_cost_bit(cm->fc->obmc_prob[i], 1);
+ }
#endif // CONFIG_OBMC
+ }
}
}
diff --git a/vp10/encoder/rd.h b/vp10/encoder/rd.h
index 5d6f8e6..fdbe431 100644
--- a/vp10/encoder/rd.h
+++ b/vp10/encoder/rd.h
@@ -292,6 +292,10 @@
void vp10_init_me_luts(void);
+#if CONFIG_REF_MV
+void vp10_set_mvcost(MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame);
+#endif
+
void vp10_get_entropy_contexts(BLOCK_SIZE bsize, TX_SIZE tx_size,
const struct macroblockd_plane *pd,
ENTROPY_CONTEXT t_above[16],
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index de12828..7604a22 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -539,47 +539,70 @@
cost = token_costs[0][0][pt][EOB_TOKEN];
c = 0;
} else {
- int band_left = *band_count++;
+ if (use_fast_coef_costing) {
+ int band_left = *band_count++;
- // dc token
- int v = qcoeff[0];
- int16_t prev_t;
- EXTRABIT e;
- vp10_get_token_extra(v, &prev_t, &e);
- cost = (*token_costs)[0][pt][prev_t] +
- vp10_get_cost(prev_t, e, cat6_high_cost);
+ // dc token
+ int v = qcoeff[0];
+ int16_t prev_t;
+ cost = vp10_get_token_cost(v, &prev_t, cat6_high_cost);
+ cost += (*token_costs)[0][pt][prev_t];
- token_cache[0] = vp10_pt_energy_class[prev_t];
- ++token_costs;
+ token_cache[0] = vp10_pt_energy_class[prev_t];
+ ++token_costs;
- // ac tokens
- for (c = 1; c < eob; c++) {
- const int rc = scan[c];
- int16_t t;
+ // ac tokens
+ for (c = 1; c < eob; c++) {
+ const int rc = scan[c];
+ int16_t t;
- v = qcoeff[rc];
- vp10_get_token_extra(v, &t, &e);
- if (use_fast_coef_costing) {
- cost += (*token_costs)[!prev_t][!prev_t][t] +
- vp10_get_cost(t, e, cat6_high_cost);
- } else {
- pt = get_coef_context(nb, token_cache, c);
- cost += (*token_costs)[!prev_t][pt][t] +
- vp10_get_cost(t, e, cat6_high_cost);
- token_cache[rc] = vp10_pt_energy_class[t];
+ v = qcoeff[rc];
+ cost += vp10_get_token_cost(v, &t, cat6_high_cost);
+ cost += (*token_costs)[!prev_t][!prev_t][t];
+ prev_t = t;
+ if (!--band_left) {
+ band_left = *band_count++;
+ ++token_costs;
+ }
}
- prev_t = t;
- if (!--band_left) {
- band_left = *band_count++;
- ++token_costs;
- }
- }
- // eob token
- if (band_left) {
- if (use_fast_coef_costing) {
+ // eob token
+ if (band_left)
cost += (*token_costs)[0][!prev_t][EOB_TOKEN];
- } else {
+
+ } else { // !use_fast_coef_costing
+ int band_left = *band_count++;
+
+ // dc token
+ int v = qcoeff[0];
+ int16_t tok;
+ unsigned int (*tok_cost_ptr)[COEFF_CONTEXTS][ENTROPY_TOKENS];
+ cost = vp10_get_token_cost(v, &tok, cat6_high_cost);
+ cost += (*token_costs)[0][pt][tok];
+
+ token_cache[0] = vp10_pt_energy_class[tok];
+ ++token_costs;
+
+ tok_cost_ptr = &((*token_costs)[!tok]);
+
+ // ac tokens
+ for (c = 1; c < eob; c++) {
+ const int rc = scan[c];
+
+ v = qcoeff[rc];
+ cost += vp10_get_token_cost(v, &tok, cat6_high_cost);
+ pt = get_coef_context(nb, token_cache, c);
+ cost += (*tok_cost_ptr)[pt][tok];
+ token_cache[rc] = vp10_pt_energy_class[tok];
+ if (!--band_left) {
+ band_left = *band_count++;
+ ++token_costs;
+ }
+ tok_cost_ptr = &((*token_costs)[!tok]);
+ }
+
+ // eob token
+ if (band_left) {
pt = get_coef_context(nb, token_cache, c);
cost += (*token_costs)[0][pt][EOB_TOKEN];
}
@@ -658,6 +681,10 @@
plane_bsize, tx_size, &arg);
{
+#if CONFIG_VP9_HIGHBITDEPTH
+ const VP10_COMP *cpi = args->cpi;
+ const uint32_t hbd_shift = (cpi->common.bit_depth - 8) * 2;
+#endif
const int bs = 4 << tx_size;
const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
const vpx_variance_fn_t variance = args->cpi->fn_ptr[tx_bsize].vf;
@@ -674,8 +701,12 @@
const int16_t *diff = &p->src_diff[4 * (blk_row * diff_stride + blk_col)];
unsigned int tmp;
-
+#if CONFIG_VP9_HIGHBITDEPTH
+ sse = (int64_t)ROUND_POWER_OF_TWO(
+ vpx_sum_squares_2d_i16(diff, diff_stride, bs), hbd_shift) * 16;
+#else
sse = (int64_t)vpx_sum_squares_2d_i16(diff, diff_stride, bs) * 16;
+#endif
variance(src, src_stride, dst, dst_stride, &tmp);
dist = (int64_t)tmp * 16;
}
@@ -2332,6 +2363,7 @@
#if CONFIG_VP9_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, rec_buffer_alloc_16[32 * 32]);
uint8_t *rec_buffer;
+ const uint32_t hbd_shift = (cpi->common.bit_depth - 8) * 2;
#else
DECLARE_ALIGNED(16, uint8_t, rec_buffer[32 * 32]);
#endif
@@ -2372,11 +2404,21 @@
for (idy = 0; idy < blocks_height; idy += 2) {
for (idx = 0; idx < blocks_width; idx += 2) {
const int16_t *d = diff + 4 * idy * diff_stride + 4 * idx;
+#if CONFIG_VP9_HIGHBITDEPTH
+ tmp_sse += ROUND_POWER_OF_TWO(
+ vpx_sum_squares_2d_i16(d, diff_stride, 8), hbd_shift);
+#else
tmp_sse += vpx_sum_squares_2d_i16(d, diff_stride, 8);
+#endif
}
}
} else {
+#if CONFIG_VP9_HIGHBITDEPTH
+ tmp_sse = ROUND_POWER_OF_TWO(
+ vpx_sum_squares_2d_i16(diff, diff_stride, bh), hbd_shift);
+#else
tmp_sse = vpx_sum_squares_2d_i16(diff, diff_stride, bh);
+#endif
}
*bsse += (int64_t)tmp_sse * 16;
@@ -3512,6 +3554,20 @@
mic->bmi[i].as_mode = mode;
+#if CONFIG_REF_MV
+ if (mode == NEWMV) {
+ mic->bmi[i].pred_mv[0].as_int =
+ mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_int;
+ if (is_compound)
+ mic->bmi[i].pred_mv[1].as_int =
+ mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_int;
+ } else {
+ mic->bmi[i].pred_mv[0].as_int = this_mv[0].as_int;
+ if (is_compound)
+ mic->bmi[i].pred_mv[1].as_int = this_mv[1].as_int;
+ }
+#endif
+
for (idy = 0; idy < num_4x4_blocks_high; ++idy)
for (idx = 0; idx < num_4x4_blocks_wide; ++idx)
memmove(&mic->bmi[i + idy * 2 + idx], &mic->bmi[i], sizeof(mic->bmi[i]));
@@ -3955,6 +4011,10 @@
tmp_mv.col >>= 3;
tmp_mv.row >>= 3;
+#if CONFIG_REF_MV
+ vp10_set_mvcost(x, refs[id]);
+#endif
+
// Small-range full-pixel motion search.
bestsme = vp10_refining_search_8p_c(x, &tmp_mv, sadpb,
search_range,
@@ -4252,6 +4312,9 @@
vp10_set_mv_search_range(x, &bsi->ref_mv[0]->as_mv);
+#if CONFIG_REF_MV
+ vp10_set_mvcost(x, mbmi->ref_frame[0]);
+#endif
bestsme = vp10_full_pixel_search(
cpi, x, bsize, &mvp_full, step_param, sadpb,
cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
@@ -4788,6 +4851,10 @@
pred_mv[1] = x->mbmi_ext->ref_mvs[ref][1].as_mv;
pred_mv[2] = x->pred_mv[ref];
+#if CONFIG_REF_MV
+ vp10_set_mvcost(x, ref);
+#endif
+
if (scaled_ref_frame) {
int i;
// Swap out the reference frame for a version that's been scaled to
@@ -7366,6 +7433,15 @@
*mbmi = best_mbmode;
x->skip |= best_skip2;
+#if CONFIG_REF_MV
+ for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
+ if (mbmi->mode != NEWMV)
+ mbmi->pred_mv[i].as_int = mbmi->mv[i].as_int;
+ else
+ mbmi->pred_mv[i].as_int = mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_int;
+ }
+#endif
+
for (i = 0; i < REFERENCE_MODES; ++i) {
if (best_pred_rd[i] == INT64_MAX)
best_pred_diff[i] = INT_MIN;
@@ -8292,6 +8368,10 @@
mbmi->mv[0].as_int = xd->mi[0]->bmi[3].as_mv[0].as_int;
mbmi->mv[1].as_int = xd->mi[0]->bmi[3].as_mv[1].as_int;
+#if CONFIG_REF_MV
+ mbmi->pred_mv[0].as_int = xd->mi[0]->bmi[3].pred_mv[0].as_int;
+ mbmi->pred_mv[1].as_int = xd->mi[0]->bmi[3].pred_mv[1].as_int;
+#endif
}
for (i = 0; i < REFERENCE_MODES; ++i) {
diff --git a/vp10/encoder/temporal_filter.c b/vp10/encoder/temporal_filter.c
index 035b66a..afe555d 100644
--- a/vp10/encoder/temporal_filter.c
+++ b/vp10/encoder/temporal_filter.c
@@ -293,6 +293,13 @@
step_param = mv_sf->reduce_first_step_size;
step_param = VPXMIN(step_param, MAX_MVSEARCH_STEPS - 2);
+#if CONFIG_REF_MV
+ x->mvcost = x->mv_cost_stack[0];
+ x->nmvjointcost = x->nmv_vec_cost[0];
+ x->mvsadcost = x->mvcost;
+ x->nmvjointsadcost = x->nmvjointcost;
+#endif
+
// Ignore mv costing by sending NULL pointer instead of cost arrays
vp10_hex_search(x, &best_ref_mv1_full, step_param, sadpb, 1,
cond_cost_list(cpi, cost_list),
diff --git a/vp10/encoder/tokenize.c b/vp10/encoder/tokenize.c
index 0aaeb2a..5cae8e3 100644
--- a/vp10/encoder/tokenize.c
+++ b/vp10/encoder/tokenize.c
@@ -50,6 +50,35 @@
const TOKENVALUE *vp10_dct_cat_lt_10_value_tokens = dct_cat_lt_10_value_tokens +
(sizeof(dct_cat_lt_10_value_tokens) / sizeof(*dct_cat_lt_10_value_tokens))
/ 2;
+// The corresponding costs of the extrabits for the tokens in the above table
+// are stored in the table below. The values are obtained from looking up the
+// entry for the specified extrabits in the table corresponding to the token
+// (as defined in cost element vp10_extra_bits)
+// e.g. {9, 63} maps to cat5_cost[63 >> 1], {1, 1} maps to sign_cost[1 >> 1]
+static const int dct_cat_lt_10_value_cost[] = {
+ 3773, 3750, 3704, 3681, 3623, 3600, 3554, 3531,
+ 3432, 3409, 3363, 3340, 3282, 3259, 3213, 3190,
+ 3136, 3113, 3067, 3044, 2986, 2963, 2917, 2894,
+ 2795, 2772, 2726, 2703, 2645, 2622, 2576, 2553,
+ 3197, 3116, 3058, 2977, 2881, 2800,
+ 2742, 2661, 2615, 2534, 2476, 2395,
+ 2299, 2218, 2160, 2079,
+ 2566, 2427, 2334, 2195, 2023, 1884, 1791, 1652,
+ 1893, 1696, 1453, 1256, 1229, 864,
+ 512, 512, 512, 512, 0,
+ 512, 512, 512, 512,
+ 864, 1229, 1256, 1453, 1696, 1893,
+ 1652, 1791, 1884, 2023, 2195, 2334, 2427, 2566,
+ 2079, 2160, 2218, 2299, 2395, 2476, 2534, 2615,
+ 2661, 2742, 2800, 2881, 2977, 3058, 3116, 3197,
+ 2553, 2576, 2622, 2645, 2703, 2726, 2772, 2795,
+ 2894, 2917, 2963, 2986, 3044, 3067, 3113, 3136,
+ 3190, 3213, 3259, 3282, 3340, 3363, 3409, 3432,
+ 3531, 3554, 3600, 3623, 3681, 3704, 3750, 3773,
+};
+const int *vp10_dct_cat_lt_10_value_cost = dct_cat_lt_10_value_cost +
+ (sizeof(dct_cat_lt_10_value_cost) / sizeof(*dct_cat_lt_10_value_cost))
+ / 2;
// Array indices are identical to previously-existing CONTEXT_NODE indices
const vpx_tree_index vp10_coef_tree[TREE_SIZE(ENTROPY_TOKENS)] = {
diff --git a/vp10/encoder/tokenize.h b/vp10/encoder/tokenize.h
index 12f5f1f..46b7f3f 100644
--- a/vp10/encoder/tokenize.h
+++ b/vp10/encoder/tokenize.h
@@ -76,6 +76,7 @@
*/
extern const TOKENVALUE *vp10_dct_value_tokens_ptr;
extern const TOKENVALUE *vp10_dct_cat_lt_10_value_tokens;
+extern const int *vp10_dct_cat_lt_10_value_cost;
extern const int16_t vp10_cat6_low_cost[256];
extern const int vp10_cat6_high_cost[64];
extern const int vp10_cat6_high10_high_cost[256];
@@ -119,6 +120,18 @@
return vp10_dct_cat_lt_10_value_tokens[v].token;
}
+static INLINE int vp10_get_token_cost(int v, int16_t *token,
+ const int *cat6_high_table) {
+ if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) {
+ EXTRABIT extrabits;
+ *token = CATEGORY6_TOKEN;
+ extrabits = abs(v) - CAT6_MIN_VAL;
+ return vp10_cat6_low_cost[extrabits & 0xff]
+ + cat6_high_table[extrabits >> 8];
+ }
+ *token = vp10_dct_cat_lt_10_value_tokens[v].token;
+ return vp10_dct_cat_lt_10_value_cost[v];
+}
#ifdef __cplusplus
} // extern "C"
diff --git a/vp10/encoder/x86/dct_sse2.c b/vp10/encoder/x86/dct_sse2.c
index 976fe45..1cba803 100644
--- a/vp10/encoder/x86/dct_sse2.c
+++ b/vp10/encoder/x86/dct_sse2.c
@@ -172,6 +172,42 @@
transpose_4x4(in);
}
+#if CONFIG_EXT_TX
+static void fdst4_sse2(__m128i *in) {
+ const __m128i k__cospi_p16_p16 = _mm_set1_epi16((int16_t) cospi_16_64);
+ const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
+ const __m128i k__cospi_p08_m24 = pair_set_epi16(cospi_8_64, -cospi_24_64);
+ const __m128i k__cospi_p24_p08 = pair_set_epi16(cospi_24_64, cospi_8_64);
+ const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING);
+
+ __m128i u[4], v[4];
+
+ u[0] = _mm_unpacklo_epi16(in[0], in[1]);
+ u[1] = _mm_unpacklo_epi16(in[3], in[2]);
+
+ v[0] = _mm_add_epi16(u[0], u[1]);
+ v[1] = _mm_sub_epi16(u[0], u[1]);
+
+ u[0] = _mm_madd_epi16(v[0], k__cospi_p24_p08);
+ u[1] = _mm_madd_epi16(v[1], k__cospi_p16_p16);
+ u[2] = _mm_madd_epi16(v[0], k__cospi_p08_m24);
+ u[3] = _mm_madd_epi16(v[1], k__cospi_p16_m16);
+
+ v[0] = _mm_add_epi32(u[0], k__DCT_CONST_ROUNDING);
+ v[1] = _mm_add_epi32(u[1], k__DCT_CONST_ROUNDING);
+ v[2] = _mm_add_epi32(u[2], k__DCT_CONST_ROUNDING);
+ v[3] = _mm_add_epi32(u[3], k__DCT_CONST_ROUNDING);
+ u[0] = _mm_srai_epi32(v[0], DCT_CONST_BITS);
+ u[1] = _mm_srai_epi32(v[1], DCT_CONST_BITS);
+ u[2] = _mm_srai_epi32(v[2], DCT_CONST_BITS);
+ u[3] = _mm_srai_epi32(v[3], DCT_CONST_BITS);
+
+ in[0] = _mm_packs_epi32(u[0], u[2]);
+ in[1] = _mm_packs_epi32(u[1], u[3]);
+ transpose_4x4(in);
+}
+#endif // CONFIG_EXT_TX
+
void vp10_fht4x4_sse2(const int16_t *input, tran_low_t *output,
int stride, int tx_type) {
__m128i in[4];
@@ -229,6 +265,48 @@
fadst4_sse2(in);
write_buffer_4x4(output, in);
break;
+ case DST_DST:
+ load_buffer_4x4(input, in, stride, 0, 0);
+ fdst4_sse2(in);
+ fdst4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
+ case DCT_DST:
+ load_buffer_4x4(input, in, stride, 0, 0);
+ fdct4_sse2(in);
+ fdst4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
+ case DST_DCT:
+ load_buffer_4x4(input, in, stride, 0, 0);
+ fdst4_sse2(in);
+ fdct4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
+ case DST_ADST:
+ load_buffer_4x4(input, in, stride, 0, 0);
+ fdst4_sse2(in);
+ fadst4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
+ case ADST_DST:
+ load_buffer_4x4(input, in, stride, 0, 0);
+ fadst4_sse2(in);
+ fdst4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
+ case DST_FLIPADST:
+ load_buffer_4x4(input, in, stride, 0, 1);
+ fdst4_sse2(in);
+ fadst4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
+ case FLIPADST_DST:
+ load_buffer_4x4(input, in, stride, 1, 0);
+ fadst4_sse2(in);
+ fdst4_sse2(in);
+ write_buffer_4x4(output, in);
+ break;
#endif // CONFIG_EXT_TX
default:
assert(0);
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index b1c2e11..edfd60c 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -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"
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 69d5fa7..d407f5e 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -16,7 +16,7 @@
#include "./vpx_config.h"
#include "./vpx_dsp_rtcd.h"
#include "./vpx_scale_rtcd.h"
-#include "vpx/internal/vpx_psnr.h"
+#include "vpx_dsp/psnr.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_dsp/vpx_filter.h"
#if CONFIG_INTERNAL_STATS
@@ -2140,271 +2140,15 @@
#endif
}
-/* 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
-
-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;
-
-#if CONFIG_VP9_HIGHBITDEPTH
-static void calc_highbd_psnr(const YV12_BUFFER_CONFIG *a,
- const YV12_BUFFER_CONFIG *b,
- PSNR_STATS *psnr,
- unsigned int bit_depth,
- unsigned int 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) {
- const int w = widths[i];
- const int h = heights[i];
- const uint32_t samples = w * h;
- uint64_t sse;
- if (a->flags & YV12_FLAG_HIGHBITDEPTH) {
- if (input_shift) {
- sse = highbd_get_sse_shift(a_planes[i], a_strides[i],
- b_planes[i], b_strides[i], w, h,
- input_shift);
- } else {
- sse = highbd_get_sse(a_planes[i], a_strides[i],
- b_planes[i], b_strides[i], w, h);
- }
- } else {
- sse = get_sse(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] = vpx_sse_to_psnr(samples, peak, (double)sse);
-
- total_sse += sse;
- total_samples += samples;
- }
-
- psnr->sse[0] = total_sse;
- psnr->samples[0] = total_samples;
- psnr->psnr[0] = vpx_sse_to_psnr((double)total_samples, peak,
- (double)total_sse);
-}
-
-#else // !CONFIG_VP9_HIGHBITDEPTH
-
-static void calc_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b,
- PSNR_STATS *psnr) {
- static const double peak = 255.0;
- 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;
-
- for (i = 0; i < 3; ++i) {
- const int w = widths[i];
- const int h = heights[i];
- const uint32_t samples = w * h;
- const uint64_t sse = get_sse(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] = vpx_sse_to_psnr(samples, peak, (double)sse);
-
- total_sse += sse;
- total_samples += samples;
- }
-
- psnr->sse[0] = total_sse;
- psnr->samples[0] = total_samples;
- psnr->psnr[0] = vpx_sse_to_psnr((double)total_samples, peak,
- (double)total_sse);
-}
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
static void generate_psnr_packet(VP9_COMP *cpi) {
struct vpx_codec_cx_pkt pkt;
int i;
PSNR_STATS psnr;
#if CONFIG_VP9_HIGHBITDEPTH
- calc_highbd_psnr(cpi->Source, cpi->common.frame_to_show, &psnr,
- cpi->td.mb.e_mbd.bd, cpi->oxcf.input_bit_depth);
+ vpx_calc_highbd_psnr(cpi->Source, cpi->common.frame_to_show, &psnr,
+ cpi->td.mb.e_mbd.bd, cpi->oxcf.input_bit_depth);
#else
- calc_psnr(cpi->Source, cpi->common.frame_to_show, &psnr);
+ vpx_calc_psnr(cpi->Source, cpi->common.frame_to_show, &psnr);
#endif
for (i = 0; i < 4; ++i) {
@@ -3061,7 +2805,7 @@
vpx_clear_system_state();
- recon_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ recon_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
if (cpi->twopass.total_left_stats.coded_error != 0.0)
fprintf(f, "%10u %dx%d %10d %10d %d %d %10d %10d %10d %10d"
@@ -3571,12 +3315,12 @@
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- kf_err = vp9_highbd_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ kf_err = vpx_highbd_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
} else {
- kf_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ kf_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
}
#else
- kf_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ kf_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
#endif // CONFIG_VP9_HIGHBITDEPTH
// Prevent possible divide by zero error below for perfect KF
@@ -3967,13 +3711,13 @@
if (cpi->rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
- cpi->ambient_err = vp9_highbd_get_y_sse(cpi->Source,
+ cpi->ambient_err = vpx_highbd_get_y_sse(cpi->Source,
get_frame_new_buffer(cm));
} else {
- cpi->ambient_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ cpi->ambient_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
}
#else
- cpi->ambient_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
+ cpi->ambient_err = vpx_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
#endif // CONFIG_VP9_HIGHBITDEPTH
}
@@ -4570,9 +4314,7 @@
if (cm->show_frame) {
uint32_t bit_depth = 8;
-#if CONFIG_VP9_HIGHBITDEPTH
uint32_t in_bit_depth = 8;
-#endif
cpi->count++;
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
@@ -4587,10 +4329,10 @@
YV12_BUFFER_CONFIG *pp = &cm->post_proc_buffer;
PSNR_STATS psnr;
#if CONFIG_VP9_HIGHBITDEPTH
- calc_highbd_psnr(orig, recon, &psnr, cpi->td.mb.e_mbd.bd,
- in_bit_depth);
+ vpx_calc_highbd_psnr(orig, recon, &psnr, cpi->td.mb.e_mbd.bd,
+ in_bit_depth);
#else
- calc_psnr(orig, recon, &psnr);
+ vpx_calc_psnr(orig, recon, &psnr);
#endif // CONFIG_VP9_HIGHBITDEPTH
adjust_image_stat(psnr.psnr[1], psnr.psnr[2], psnr.psnr[3],
@@ -4621,10 +4363,10 @@
vpx_clear_system_state();
#if CONFIG_VP9_HIGHBITDEPTH
- calc_highbd_psnr(orig, pp, &psnr2, cpi->td.mb.e_mbd.bd,
+ vpx_calc_highbd_psnr(orig, pp, &psnr2, cpi->td.mb.e_mbd.bd,
cpi->oxcf.input_bit_depth);
#else
- calc_psnr(orig, pp, &psnr2);
+ vpx_calc_psnr(orig, pp, &psnr2);
#endif // CONFIG_VP9_HIGHBITDEPTH
cpi->totalp_sq_error += psnr2.sse[0];
@@ -4710,13 +4452,13 @@
{
double y, u, v, frame_all;
frame_all = vpx_calc_fastssim(cpi->Source, cm->frame_to_show, &y, &u,
- &v, bit_depth);
+ &v, bit_depth, in_bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
}
{
double y, u, v, frame_all;
frame_all = vpx_psnrhvs(cpi->Source, cm->frame_to_show, &y, &u, &v,
- bit_depth);
+ bit_depth, in_bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
@@ -4844,28 +4586,6 @@
return;
}
-int64_t vp9_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 vp9_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
-
int vp9_get_quantizer(VP9_COMP *cpi) {
return cpi->common.base_qindex;
}
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 8759cbe..017fa61 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -608,12 +608,6 @@
return get_token_alloc(tile_mb_rows, tile_mb_cols);
}
-int64_t vp9_get_y_sse(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b);
-#if CONFIG_VP9_HIGHBITDEPTH
-int64_t vp9_highbd_get_y_sse(const YV12_BUFFER_CONFIG *a,
- const YV12_BUFFER_CONFIG *b);
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
void vp9_scale_references(VP9_COMP *cpi);
void vp9_update_reference_frames(VP9_COMP *cpi);
diff --git a/vp9/encoder/vp9_picklpf.c b/vp9/encoder/vp9_picklpf.c
index f6b1dfc..80ab238 100644
--- a/vp9/encoder/vp9_picklpf.c
+++ b/vp9/encoder/vp9_picklpf.c
@@ -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 @@
#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
diff --git a/vpx/internal/vpx_psnr.h b/vpx/internal/vpx_psnr.h
deleted file mode 100644
index 0e90085..0000000
--- a/vpx/internal/vpx_psnr.h
+++ /dev/null
@@ -1,36 +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 VPX_INTERNAL_VPX_PSNR_H_
-#define VPX_INTERNAL_VPX_PSNR_H_
-
-#define MAX_PSNR 100.0
-
-#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_
diff --git a/vpx/src/vpx_psnr.c b/vpx/src/vpx_psnr.c
deleted file mode 100644
index 27a6180..0000000
--- a/vpx/src/vpx_psnr.c
+++ /dev/null
@@ -1,23 +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.
- */
-
-#include <math.h>
-
-#include "vpx/internal/vpx_psnr.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;
- }
-}
diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk
index ccdef04..b77f458 100644
--- a/vpx/vpx_codec.mk
+++ b/vpx/vpx_codec.mk
@@ -36,10 +36,8 @@
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
diff --git a/vpx_dsp/fastssim.c b/vpx_dsp/fastssim.c
index e3746f0..9b10d3a 100644
--- a/vpx_dsp/fastssim.c
+++ b/vpx_dsp/fastssim.c
@@ -141,7 +141,7 @@
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 bd, uint32_t shift) {
uint32_t *dst1;
uint32_t *dst2;
int w;
@@ -162,7 +162,7 @@
int i1;
i0 = 2 * i;
i1 = FS_MINI(i0 + 1, _w);
- if (bit_depth == 8) {
+ 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];
@@ -172,12 +172,14 @@
} 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];
+ 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);
}
}
}
@@ -467,21 +469,21 @@
static double calc_ssim(const uint8_t *_src, int _systride,
const uint8_t *_dst, int _dystride,
- int _w, int _h, uint32_t bit_depth) {
+ 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, bit_depth);
+ _w, _h, _bd, _shift);
for (l = 0; l < FS_NLEVELS - 1; l++) {
- fs_calc_structure(&ctx, l, bit_depth);
+ fs_calc_structure(&ctx, l, _bd);
ret *= fs_average(&ctx, l);
fs_downsample_level(&ctx, l + 1);
}
- fs_calc_structure(&ctx, l, bit_depth);
- fs_apply_luminance(&ctx, l, bit_depth);
+ fs_calc_structure(&ctx, l, _bd);
+ fs_apply_luminance(&ctx, l, _bd);
ret *= fs_average(&ctx, l);
fs_ctx_clear(&ctx);
return ret;
@@ -490,18 +492,22 @@
double vpx_calc_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
double *ssim_y, double *ssim_u, double *ssim_v,
- uint32_t bit_depth) {
+ 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, bit_depth);
+ 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, bit_depth);
+ 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, bit_depth);
+ source->uv_crop_height, in_bd, bd_shift);
ssimv = (*ssim_y) * .8 + .1 * ((*ssim_u) + (*ssim_v));
return convert_ssim_db(ssimv, 1.0);
diff --git a/vpx_dsp/psnr.c b/vpx_dsp/psnr.c
new file mode 100644
index 0000000..1655f11
--- /dev/null
+++ b/vpx_dsp/psnr.c
@@ -0,0 +1,296 @@
+/*
+* 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) {
+ const int w = widths[i];
+ const int h = heights[i];
+ const uint32_t samples = w * h;
+ uint64_t sse;
+ if (a->flags & YV12_FLAG_HIGHBITDEPTH) {
+ if (input_shift) {
+ sse = highbd_get_sse_shift(a_planes[i], a_strides[i],
+ b_planes[i], b_strides[i], w, h,
+ input_shift);
+ } else {
+ sse = highbd_get_sse(a_planes[i], a_strides[i],
+ b_planes[i], b_strides[i], w, h);
+ }
+ } else {
+ sse = get_sse(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] = vpx_sse_to_psnr(samples, peak, (double)sse);
+
+ total_sse += sse;
+ total_samples += samples;
+ }
+
+ psnr->sse[0] = total_sse;
+ psnr->samples[0] = total_samples;
+ psnr->psnr[0] = vpx_sse_to_psnr((double)total_samples, peak,
+ (double)total_sse);
+}
+
+#endif // !CONFIG_VP9_HIGHBITDEPTH
+
+void vpx_calc_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b,
+ PSNR_STATS *psnr) {
+ static const double peak = 255.0;
+ 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;
+
+ for (i = 0; i < 3; ++i) {
+ const int w = widths[i];
+ const int h = heights[i];
+ const uint32_t samples = w * h;
+ const uint64_t sse = get_sse(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] = vpx_sse_to_psnr(samples, peak, (double)sse);
+
+ total_sse += sse;
+ total_samples += samples;
+ }
+
+ psnr->sse[0] = total_sse;
+ psnr->samples[0] = total_samples;
+ psnr->psnr[0] = vpx_sse_to_psnr((double)total_samples, peak,
+ (double)total_sse);
+}
diff --git a/vpx_dsp/psnr.h b/vpx_dsp/psnr.h
new file mode 100644
index 0000000..e25b450
--- /dev/null
+++ b/vpx_dsp/psnr.h
@@ -0,0 +1,63 @@
+/*
+* 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.
+*/
+
+#ifndef VPX_DSP_PSNR_H_
+#define VPX_DSP_PSNR_H_
+
+
+#include "vpx_scale/yv12config.h"
+
+#define MAX_PSNR 100.0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ double psnr[4]; // total/y/u/v
+ uint64_t sse[4]; // total/y/u/v
+ uint32_t samples[4]; // total/y/u/v
+} PSNR_STATS;
+
+// 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);
+int64_t vpx_get_y_sse(const YV12_BUFFER_CONFIG *a,
+ const YV12_BUFFER_CONFIG *b);
+#if CONFIG_VP9_HIGHBITDEPTH
+int64_t vpx_highbd_get_y_sse(const YV12_BUFFER_CONFIG *a,
+ const YV12_BUFFER_CONFIG *b);
+void vpx_calc_highbd_psnr(const YV12_BUFFER_CONFIG *a,
+ const YV12_BUFFER_CONFIG *b,
+ PSNR_STATS *psnr,
+ unsigned int bit_depth,
+ unsigned int in_bit_depth);
+#endif
+void vpx_calc_psnr(const YV12_BUFFER_CONFIG *a,
+ const YV12_BUFFER_CONFIG *b,
+ PSNR_STATS *psnr);
+
+double vpx_psnrhvs(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest,
+ double *phvs_y, double *phvs_u,
+ double *phvs_v, uint32_t bd, uint32_t in_bd);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+#endif // VPX_DSP_PSNR_H_
diff --git a/vpx_dsp/psnrhvs.c b/vpx_dsp/psnrhvs.c
index 4d3d6ee..095ba5d 100644
--- a/vpx_dsp/psnrhvs.c
+++ b/vpx_dsp/psnrhvs.c
@@ -19,7 +19,7 @@
#include "./vpx_dsp_rtcd.h"
#include "vpx_dsp/ssim.h"
#include "vpx_ports/system_state.h"
-#include "vpx/internal/vpx_psnr.h"
+#include "vpx_dsp/psnr.h"
#if !defined(M_PI)
# define M_PI (3.141592653589793238462643)
@@ -118,7 +118,8 @@
static double calc_psnrhvs(const unsigned char *src, int _systride,
const unsigned char *dst, int _dystride,
double _par, int _w, int _h, int _step,
- const double _csf[8][8], uint32_t bit_depth) {
+ const double _csf[8][8], uint32_t bit_depth,
+ uint32_t _shift) {
double ret;
const uint8_t *_src8 = src;
const uint8_t *_dst8 = dst;
@@ -172,12 +173,12 @@
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
- if (bit_depth == 8) {
+ if (bit_depth == 8 && _shift == 0) {
dct_s[i * 8 + j] = _src8[(y + i) * _systride + (j + x)];
dct_d[i * 8 + j] = _dst8[(y + i) * _dystride + (j + x)];
} else if (bit_depth == 10 || bit_depth == 12) {
- dct_s[i * 8 + j] = _src16[(y + i) * _systride + (j + x)];
- dct_d[i * 8 + j] = _dst16[(y + i) * _dystride + (j + x)];
+ dct_s[i * 8 + j] = _src16[(y + i) * _systride + (j + x)] >> _shift;
+ dct_d[i * 8 + j] = _dst16[(y + i) * _dystride + (j + x)] >> _shift;
}
s_gmean += dct_s[i * 8 + j];
d_gmean += dct_d[i * 8 + j];
@@ -248,27 +249,34 @@
return ret;
}
-double vpx_psnrhvs(const YV12_BUFFER_CONFIG *source,
+double vpx_psnrhvs(const YV12_BUFFER_CONFIG *src,
const YV12_BUFFER_CONFIG *dest, double *y_psnrhvs,
- double *u_psnrhvs, double *v_psnrhvs, uint32_t bit_depth) {
+ double *u_psnrhvs, double *v_psnrhvs,
+ uint32_t bd, uint32_t in_bd) {
double psnrhvs;
const double par = 1.0;
const int step = 7;
+ uint32_t bd_shift = 0;
vpx_clear_system_state();
- assert(bit_depth == 8 || bit_depth == 10 || bit_depth == 12);
+ assert(bd == 8 || bd == 10 || bd == 12);
+ assert(bd >= in_bd);
- *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, bit_depth);
- *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, bit_depth);
+ bd_shift = bd - in_bd;
- *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, bit_depth);
+ *y_psnrhvs = calc_psnrhvs(src->y_buffer, src->y_stride, dest->y_buffer,
+ dest->y_stride, par, src->y_crop_width,
+ src->y_crop_height, step, csf_y, bd,
+ bd_shift);
+ *u_psnrhvs = calc_psnrhvs(src->u_buffer, src->uv_stride, dest->u_buffer,
+ dest->uv_stride, par, src->uv_crop_width,
+ src->uv_crop_height, step, csf_cb420, bd,
+ bd_shift);
+ *v_psnrhvs = calc_psnrhvs(src->v_buffer, src->uv_stride, dest->v_buffer,
+ dest->uv_stride, par, src->uv_crop_width,
+ src->uv_crop_height, step, csf_cr420, bd,
+ bd_shift);
psnrhvs = (*y_psnrhvs) * .8 + .1 * ((*u_psnrhvs) + (*v_psnrhvs));
- return convert_score_db(psnrhvs, 1.0, bit_depth);
+ return convert_score_db(psnrhvs, 1.0, in_bd);
}
diff --git a/vpx_dsp/ssim.h b/vpx_dsp/ssim.h
index 6c59540..6b91d2a 100644
--- a/vpx_dsp/ssim.h
+++ b/vpx_dsp/ssim.h
@@ -73,12 +73,7 @@
double vpx_calc_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
double *ssim_y, double *ssim_u,
- double *ssim_v, uint32_t bit_depth);
-
-double vpx_psnrhvs(const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *dest,
- double *phvs_y, double *phvs_u,
- double *phvs_v, uint32_t bit_depth);
+ double *ssim_v, uint32_t bd, uint32_t in_bd);
#if CONFIG_VP9_HIGHBITDEPTH
double vpx_highbd_calc_ssim(const YV12_BUFFER_CONFIG *source,
diff --git a/vpx_dsp/vpx_dsp.mk b/vpx_dsp/vpx_dsp.mk
index a44f948..dbb41aa 100644
--- a/vpx_dsp/vpx_dsp.mk
+++ b/vpx_dsp/vpx_dsp.mk
@@ -22,6 +22,8 @@
DSP_SRCS-yes += bitwriter.c
DSP_SRCS-yes += bitwriter_buffer.c
DSP_SRCS-yes += bitwriter_buffer.h
+DSP_SRCS-yes += psnr.c
+DSP_SRCS-yes += psnr.h
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += ssim.c
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += ssim.h
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += psnrhvs.c