Merge "Fix a couple of minor bugs in vp10_has_right and vp10_has_bottom" into nextgenv2
diff --git a/configure b/configure
index 9769880..5eec2a1 100755
--- a/configure
+++ b/configure
@@ -283,6 +283,7 @@
loop_restoration
ext_partition
obmc
+ affine_motion
"
CONFIG_LIST="
dependency_tracking
diff --git a/test/vp10_convolve_test.cc b/test/vp10_convolve_test.cc
index af34ffc..07b0dda 100644
--- a/test/vp10_convolve_test.cc
+++ b/test/vp10_convolve_test.cc
@@ -11,10 +11,10 @@
namespace {
TEST(VP10ConvolveTest, vp10_convolve8) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
- INTERP_FILTER interp_filter = EIGHTTAP;
+ INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
- ptrdiff_t filter_size = filter_params.tap;
+ ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint8_t src[12 * 12];
int src_stride = filter_size;
@@ -39,9 +39,9 @@
subpel_y_q4, y_step_q4, avg);
const int16_t* x_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_x_q4);
+ vp10_get_interp_filter_subpel_kernel(filter_params, subpel_x_q4);
const int16_t* y_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
+ vp10_get_interp_filter_subpel_kernel(filter_params, subpel_y_q4);
vpx_convolve8_c(src + src_stride * filter_center + filter_center, src_stride,
dst1, dst_stride, x_filter, 16, y_filter, 16, w, h);
@@ -49,10 +49,10 @@
}
TEST(VP10ConvolveTest, vp10_convolve) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
- INTERP_FILTER interp_filter = EIGHTTAP;
+ INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
- ptrdiff_t filter_size = filter_params.tap;
+ ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint8_t src[12 * 12];
int src_stride = filter_size;
@@ -78,9 +78,9 @@
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);
+ vp10_get_interp_filter_subpel_kernel(filter_params, subpel_x_q4);
const int16_t* y_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
+ vp10_get_interp_filter_subpel_kernel(filter_params, subpel_y_q4);
int temp[12];
int dst_ref = 0;
@@ -100,10 +100,10 @@
TEST(VP10ConvolveTest, vp10_convolve_avg) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
- INTERP_FILTER interp_filter = EIGHTTAP;
+ INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
- ptrdiff_t filter_size = filter_params.tap;
+ ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint8_t src0[12 * 12];
uint8_t src1[12 * 12];
@@ -157,10 +157,10 @@
#if CONFIG_VP9_HIGHBITDEPTH
TEST(VP10ConvolveTest, vp10_highbd_convolve) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
- INTERP_FILTER interp_filter = EIGHTTAP;
+ INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
- ptrdiff_t filter_size = filter_params.tap;
+ ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint16_t src[12 * 12];
int src_stride = filter_size;
@@ -188,9 +188,9 @@
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);
+ vp10_get_interp_filter_subpel_kernel(filter_params, subpel_x_q4);
const int16_t* y_filter =
- vp10_get_interp_filter_kernel(filter_params, subpel_y_q4);
+ vp10_get_interp_filter_subpel_kernel(filter_params, subpel_y_q4);
int temp[12];
int dst_ref = 0;
@@ -211,10 +211,10 @@
TEST(VP10ConvolveTest, vp10_highbd_convolve_avg) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
- INTERP_FILTER interp_filter = EIGHTTAP;
+ INTERP_FILTER interp_filter = EIGHTTAP_REGULAR;
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
- ptrdiff_t filter_size = filter_params.tap;
+ ptrdiff_t filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint16_t src0[12 * 12];
uint16_t src1[12 * 12];
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index 3cea6e5..f96aa2e 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -39,8 +39,7 @@
} FRAME_TYPE;
#if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
-#define IsInterpolatingFilter(filter) \
- (vp10_filter_kernels[filter][0][SUBPEL_TAPS / 2 - 1] == 128)
+#define IsInterpolatingFilter(filter) (vp10_is_interpolating_filter(filter))
#else
#define IsInterpolatingFilter(filter) (1)
#endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c
index c56c88c..8bb653c 100644
--- a/vp10/common/entropymode.c
+++ b/vp10/common/entropymode.c
@@ -1348,23 +1348,23 @@
#if CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 4
const vpx_tree_index vp10_switchable_interp_tree
[TREE_SIZE(SWITCHABLE_FILTERS)] = {
- -EIGHTTAP, 2,
- 4, -EIGHTTAP_SHARP,
+ -EIGHTTAP_REGULAR, 2,
+ 4, -MULTITAP_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,
+ -EIGHTTAP_REGULAR, 2,
4, 6,
-EIGHTTAP_SMOOTH, -EIGHTTAP_SMOOTH2,
- -EIGHTTAP_SHARP, -EIGHTTAP_SHARP2,
+ -MULTITAP_SHARP, -MULTITAP_SHARP2,
};
#else
const vpx_tree_index vp10_switchable_interp_tree
[TREE_SIZE(SWITCHABLE_FILTERS)] = {
- -EIGHTTAP, 2,
- -EIGHTTAP_SMOOTH, -EIGHTTAP_SHARP
+ -EIGHTTAP_REGULAR, 2,
+ -EIGHTTAP_SMOOTH, -MULTITAP_SHARP
};
#endif // CONFIG_EXT_INTERP
diff --git a/vp10/common/filter.c b/vp10/common/filter.c
index d9bfcbc..2023cd6 100644
--- a/vp10/common/filter.c
+++ b/vp10/common/filter.c
@@ -32,8 +32,9 @@
{ 0, 0, 0, 8, 120, 0, 0, 0 }
};
+#if USE_TEMPORALFILTER_12TAP
DECLARE_ALIGNED(16, static const int16_t,
- sub_pel_filters_12sharp[16][12]) = {
+ sub_pel_filters_temporalfilter_12[SUBPEL_SHIFTS][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},
@@ -52,10 +53,11 @@
{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_TEMPORALFILTER_12TAP
+#if CONFIG_EXT_INTERP
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8[SUBPEL_SHIFTS]) = {
-#if CONFIG_EXT_INTERP
// intfilt 0.575
{0, 0, 0, 128, 0, 0, 0, 0},
{0, 1, -5, 126, 8, -3, 1, 0},
@@ -73,30 +75,10 @@
{0, 3, -9, 27, 118, -14, 4, -1},
{-1, 2, -6, 18, 123, -10, 3, -1},
{0, 1, -3, 8, 126, -5, 1, 0},
-#else
- // Lagrangian interpolation filter
- { 0, 0, 0, 128, 0, 0, 0, 0},
- { 0, 1, -5, 126, 8, -3, 1, 0},
- { -1, 3, -10, 122, 18, -6, 2, 0},
- { -1, 4, -13, 118, 27, -9, 3, -1},
- { -1, 4, -16, 112, 37, -11, 4, -1},
- { -1, 5, -18, 105, 48, -14, 4, -1},
- { -1, 5, -19, 97, 58, -16, 5, -1},
- { -1, 6, -19, 88, 68, -18, 5, -1},
- { -1, 6, -19, 78, 78, -19, 6, -1},
- { -1, 5, -18, 68, 88, -19, 6, -1},
- { -1, 5, -16, 58, 97, -19, 5, -1},
- { -1, 4, -14, 48, 105, -18, 5, -1},
- { -1, 4, -11, 37, 112, -16, 4, -1},
- { -1, 3, -9, 27, 118, -13, 4, -1},
- { 0, 2, -6, 18, 122, -10, 3, -1},
- { 0, 1, -3, 8, 126, -5, 1, 0}
-#endif // CONFIG_EXT_INTERP
};
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8sharp[SUBPEL_SHIFTS]) = {
-#if CONFIG_EXT_INTERP
// intfilt 0.8
{0, 0, 0, 128, 0, 0, 0, 0},
{-1, 2, -6, 127, 9, -4, 2, -1},
@@ -114,29 +96,9 @@
{-2, 5, -11, 28, 119, -16, 7, -2},
{-2, 4, -7, 18, 124, -12, 5, -2},
{-1, 2, -4, 9, 127, -6, 2, -1},
-#else
- // DCT based filter
- {0, 0, 0, 128, 0, 0, 0, 0},
- {-1, 3, -7, 127, 8, -3, 1, 0},
- {-2, 5, -13, 125, 17, -6, 3, -1},
- {-3, 7, -17, 121, 27, -10, 5, -2},
- {-4, 9, -20, 115, 37, -13, 6, -2},
- {-4, 10, -23, 108, 48, -16, 8, -3},
- {-4, 10, -24, 100, 59, -19, 9, -3},
- {-4, 11, -24, 90, 70, -21, 10, -4},
- {-4, 11, -23, 80, 80, -23, 11, -4},
- {-4, 10, -21, 70, 90, -24, 11, -4},
- {-3, 9, -19, 59, 100, -24, 10, -4},
- {-3, 8, -16, 48, 108, -23, 10, -4},
- {-2, 6, -13, 37, 115, -20, 9, -4},
- {-2, 5, -10, 27, 121, -17, 7, -3},
- {-1, 3, -6, 17, 125, -13, 5, -2},
- {0, 1, -3, 8, 127, -7, 3, -1}
-#endif // CONFIG_EXT_INTERP
};
-#if CONFIG_EXT_INTERP && (SWITCHABLE_FILTERS == 4 || SWITCHABLE_FILTERS == 5)
-
+#if SWITCHABLE_FILTERS >= 4
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8smooth2[SUBPEL_SHIFTS]) = {
// freqmultiplier = 0.35
@@ -178,7 +140,74 @@
{0, 2, -12, 37, 94, 14, -9, 2},
{0, 2, -11, 31, 95, 19, -10, 2},
};
-#else
+#endif // SWITCHABLE_FILTERS >= 4
+
+#if SWITCHABLE_FILTERS == 5
+DECLARE_ALIGNED(16, static const int16_t,
+ sub_pel_filters_12sharp[SUBPEL_SHIFTS][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
+
+#else // CONFIG_EXT_INTERP
+
+DECLARE_ALIGNED(256, static const InterpKernel,
+ sub_pel_filters_8[SUBPEL_SHIFTS]) = {
+ // Lagrangian interpolation filter
+ { 0, 0, 0, 128, 0, 0, 0, 0},
+ { 0, 1, -5, 126, 8, -3, 1, 0},
+ { -1, 3, -10, 122, 18, -6, 2, 0},
+ { -1, 4, -13, 118, 27, -9, 3, -1},
+ { -1, 4, -16, 112, 37, -11, 4, -1},
+ { -1, 5, -18, 105, 48, -14, 4, -1},
+ { -1, 5, -19, 97, 58, -16, 5, -1},
+ { -1, 6, -19, 88, 68, -18, 5, -1},
+ { -1, 6, -19, 78, 78, -19, 6, -1},
+ { -1, 5, -18, 68, 88, -19, 6, -1},
+ { -1, 5, -16, 58, 97, -19, 5, -1},
+ { -1, 4, -14, 48, 105, -18, 5, -1},
+ { -1, 4, -11, 37, 112, -16, 4, -1},
+ { -1, 3, -9, 27, 118, -13, 4, -1},
+ { 0, 2, -6, 18, 122, -10, 3, -1},
+ { 0, 1, -3, 8, 126, -5, 1, 0}
+};
+
+DECLARE_ALIGNED(256, static const InterpKernel,
+ sub_pel_filters_8sharp[SUBPEL_SHIFTS]) = {
+ // DCT based filter
+ {0, 0, 0, 128, 0, 0, 0, 0},
+ {-1, 3, -7, 127, 8, -3, 1, 0},
+ {-2, 5, -13, 125, 17, -6, 3, -1},
+ {-3, 7, -17, 121, 27, -10, 5, -2},
+ {-4, 9, -20, 115, 37, -13, 6, -2},
+ {-4, 10, -23, 108, 48, -16, 8, -3},
+ {-4, 10, -24, 100, 59, -19, 9, -3},
+ {-4, 11, -24, 90, 70, -21, 10, -4},
+ {-4, 11, -23, 80, 80, -23, 11, -4},
+ {-4, 10, -21, 70, 90, -24, 11, -4},
+ {-3, 9, -19, 59, 100, -24, 10, -4},
+ {-3, 8, -16, 48, 108, -23, 10, -4},
+ {-2, 6, -13, 37, 115, -20, 9, -4},
+ {-2, 5, -10, 27, 121, -17, 7, -3},
+ {-1, 3, -6, 17, 125, -13, 5, -2},
+ {0, 1, -3, 8, 127, -7, 3, -1}
+};
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8smooth[SUBPEL_SHIFTS]) = {
@@ -202,53 +231,60 @@
};
#endif // CONFIG_EXT_INTERP
-const InterpKernel *vp10_filter_kernels[SWITCHABLE_FILTERS + 1] = {
- sub_pel_filters_8,
- sub_pel_filters_8smooth,
- 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] = {
- 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
+ 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
};
#endif // CONFIG_EXT_INTRA
+#if CONFIG_EXT_INTERP
static const InterpFilterParams
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},
{(const int16_t*)sub_pel_filters_8sharp, SUBPEL_TAPS, SUBPEL_SHIFTS},
-#if CONFIG_EXT_INTERP && SWITCHABLE_FILTERS == 4
+#if 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},
+#endif
+#if SWITCHABLE_FILTERS == 5
{(const int16_t*)sub_pel_filters_12sharp, 12, SUBPEL_SHIFTS},
#endif
{(const int16_t*)bilinear_filters, SUBPEL_TAPS, SUBPEL_SHIFTS}
};
-
-#if FILTER_12TAP
-static const InterpFilterParams vp10_interp_filter_12tap = {
- (const int16_t*)sub_pel_filters_12sharp, 12, SUBPEL_SHIFTS
+#else
+static const InterpFilterParams
+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},
+ {(const int16_t*)sub_pel_filters_8sharp, SUBPEL_TAPS, SUBPEL_SHIFTS},
+ {(const int16_t*)bilinear_filters, SUBPEL_TAPS, SUBPEL_SHIFTS}
};
-#endif
+#endif // CONFIG_EXT_INTERP
+
+#if USE_TEMPORALFILTER_12TAP
+static const InterpFilterParams vp10_interp_temporalfilter_12tap = {
+ (const int16_t*)sub_pel_filters_temporalfilter_12, 12, SUBPEL_SHIFTS
+};
+#endif // USE_TEMPORALFILTER_12TAP
InterpFilterParams vp10_get_interp_filter_params(
const INTERP_FILTER interp_filter) {
-#if FILTER_12TAP
- if (interp_filter == SHARP_FILTER_12TAP)
- return vp10_interp_filter_12tap;
-#endif
+#if USE_TEMPORALFILTER_12TAP
+ if (interp_filter == TEMPORALFILTER_12TAP)
+ return vp10_interp_temporalfilter_12tap;
+#endif // USE_TEMPORALFILTER_12TAP
return vp10_interp_filter_params_list[interp_filter];
}
+
+const int16_t *vp10_get_interp_filter_kernel(
+ const INTERP_FILTER interp_filter) {
+#if USE_TEMPORALFILTER_12TAP
+ if (interp_filter == TEMPORALFILTER_12TAP)
+ return vp10_interp_temporalfilter_12tap.filter_ptr;
+#endif // USE_TEMPORALFILTER_12TAP
+ return (const int16_t*)
+ vp10_interp_filter_params_list[interp_filter].filter_ptr;
+}
diff --git a/vp10/common/filter.h b/vp10/common/filter.h
index df46ca8..74a0c99 100644
--- a/vp10/common/filter.h
+++ b/vp10/common/filter.h
@@ -21,33 +21,29 @@
extern "C" {
#endif
-#define EIGHTTAP 0
+#define EIGHTTAP_REGULAR 0
#define EIGHTTAP_SMOOTH 1
-#define EIGHTTAP_SHARP 2
+#define MULTITAP_SHARP 2
#if CONFIG_EXT_INTERP
+#define MAX_SUBPEL_TAPS 12
#define SUPPORT_NONINTERPOLATING_FILTERS 0 /* turn it on for experimentation */
#define SWITCHABLE_FILTERS 5 /* Number of switchable filters */
-#if SWITCHABLE_FILTERS == 4
-
+#if SWITCHABLE_FILTERS >= 4
#define EIGHTTAP_SMOOTH2 3
-
-#elif SWITCHABLE_FILTERS == 5
-
-#define EIGHTTAP_SMOOTH2 3
-#define EIGHTTAP_SHARP2 4
-
+#endif
+#if SWITCHABLE_FILTERS == 5
+#define MULTITAP_SHARP2 4
#endif // SWITCHABLE_FILTERS
#else
#define SWITCHABLE_FILTERS 3 /* Number of switchable filters */
#endif // CONFIG_EXT_INTERP
-// TODO(jingning): Align the experiment flags and clean this up.
-#define FILTER_12TAP (!CONFIG_EXT_INTERP)
-#if FILTER_12TAP
-#define SHARP_FILTER_12TAP (SWITCHABLE_FILTERS + 1)
+#define USE_TEMPORALFILTER_12TAP 1
+#if USE_TEMPORALFILTER_12TAP
+#define TEMPORALFILTER_12TAP (SWITCHABLE_FILTERS + 1)
#endif
// The codec can operate in four possible inter prediction filter mode:
@@ -59,8 +55,6 @@
typedef uint8_t INTERP_FILTER;
-extern const InterpKernel *vp10_filter_kernels[SWITCHABLE_FILTERS + 1];
-
#if CONFIG_EXT_INTRA
typedef enum {
INTRA_FILTER_LINEAR,
@@ -75,15 +69,25 @@
typedef struct InterpFilterParams {
const int16_t* filter_ptr;
- uint16_t tap;
+ uint16_t taps;
uint16_t subpel_shifts;
} InterpFilterParams;
InterpFilterParams vp10_get_interp_filter_params(
const INTERP_FILTER interp_filter);
-static INLINE const int16_t* vp10_get_interp_filter_kernel(
+
+const int16_t *vp10_get_interp_filter_kernel(
+ const INTERP_FILTER interp_filter);
+
+static INLINE const int16_t* vp10_get_interp_filter_subpel_kernel(
const InterpFilterParams filter_params, const int subpel) {
- return filter_params.filter_ptr + filter_params.tap * subpel;
+ return filter_params.filter_ptr + filter_params.taps * subpel;
+}
+
+static INLINE int vp10_is_interpolating_filter(
+ const INTERP_FILTER interp_filter) {
+ const InterpFilterParams ip = vp10_get_interp_filter_params(interp_filter);
+ return (ip.filter_ptr[ip.taps / 2 - 1] == 128);
}
#ifdef __cplusplus
} // extern "C"
diff --git a/vp10/common/pred_common.c b/vp10/common/pred_common.c
index 4dd6841..3646961 100644
--- a/vp10/common/pred_common.c
+++ b/vp10/common/pred_common.c
@@ -46,13 +46,13 @@
PREDICTION_MODE mode = left_mbmi->mode;
if (is_inter_block(left_mbmi)) {
switch (left_mbmi->interp_filter) {
- case EIGHTTAP:
+ case EIGHTTAP_REGULAR:
left_type = INTRA_FILTER_8TAP;
break;
case EIGHTTAP_SMOOTH:
left_type = INTRA_FILTER_8TAP_SMOOTH;
break;
- case EIGHTTAP_SHARP:
+ case MULTITAP_SHARP:
left_type = INTRA_FILTER_8TAP_SHARP;
break;
case BILINEAR:
@@ -76,13 +76,13 @@
if (xd->up_available && above_mbmi->sb_type >= BLOCK_8X8) {
if (is_inter_block(above_mbmi)) {
switch (above_mbmi->interp_filter) {
- case EIGHTTAP:
+ case EIGHTTAP_REGULAR:
above_type = INTRA_FILTER_8TAP;
break;
case EIGHTTAP_SMOOTH:
above_type = INTRA_FILTER_8TAP_SMOOTH;
break;
- case EIGHTTAP_SHARP:
+ case MULTITAP_SHARP:
above_type = INTRA_FILTER_8TAP_SHARP;
break;
case BILINEAR:
diff --git a/vp10/common/reconinter.h b/vp10/common/reconinter.h
index 6499999..0e7fa4c 100644
--- a/vp10/common/reconinter.h
+++ b/vp10/common/reconinter.h
@@ -30,23 +30,26 @@
int xs, int ys) {
InterpFilterParams interp_filter_params =
vp10_get_interp_filter_params(interp_filter);
- if (interp_filter_params.tap == SUBPEL_TAPS) {
- const InterpKernel *kernel = vp10_filter_kernels[interp_filter];
+ if (interp_filter_params.taps == SUBPEL_TAPS) {
+ const int16_t *kernel_x =
+ vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_x);
+ const int16_t *kernel_y =
+ vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_y);
#if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
if (IsInterpolatingFilter(interp_filter)) {
// Interpolating filter
sf->predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
- kernel[subpel_x], xs, kernel[subpel_y], ys, w, h);
+ kernel_x, xs, kernel_y, ys, w, h);
} else {
sf->predict_ni[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
- kernel[subpel_x], xs, kernel[subpel_y], ys, w, h);
+ kernel_x, xs, kernel_y, ys, w, h);
}
#else
sf->predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
- kernel[subpel_x], xs, kernel[subpel_y], ys, w, h);
+ kernel_x, xs, kernel_y, ys, w, h);
#endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
} else {
// ref > 0 means this is the second reference frame
@@ -69,23 +72,26 @@
int xs, int ys, int bd) {
InterpFilterParams interp_filter_params =
vp10_get_interp_filter_params(interp_filter);
- if (interp_filter_params.tap == SUBPEL_TAPS) {
- const InterpKernel *kernel = vp10_filter_kernels[interp_filter];
+ if (interp_filter_params.taps == SUBPEL_TAPS) {
+ const int16_t *kernel_x =
+ vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_x);
+ const int16_t *kernel_y =
+ vp10_get_interp_filter_subpel_kernel(interp_filter_params, subpel_y);
#if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
if (IsInterpolatingFilter(interp_filter)) {
// Interpolating filter
sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
- kernel[subpel_x], xs, kernel[subpel_y], ys, w, h, bd);
+ kernel_x, xs, kernel_y, ys, w, h, bd);
} else {
sf->highbd_predict_ni[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
- kernel[subpel_x], xs, kernel[subpel_y], ys, w, h, bd);
+ kernel_x, xs, kernel_y, ys, w, h, bd);
}
#else
sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
- kernel[subpel_x], xs, kernel[subpel_y], ys, w, h, bd);
+ kernel_x, xs, kernel_y, ys, w, h, bd);
#endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS
} else {
// ref > 0 means this is the second reference frame
diff --git a/vp10/common/reconintra.c b/vp10/common/reconintra.c
index e2ab952..76d50c6 100644
--- a/vp10/common/reconintra.c
+++ b/vp10/common/reconintra.c
@@ -334,8 +334,9 @@
}
} else {
if (!flags[shift]) {
+ const int16_t *filter = vp10_intra_filter_kernels[filter_type][shift];
vpx_convolve8_horiz(src + pad_size, 2 * bs, buf[shift], 2 * bs,
- vp10_intra_filter_kernels[filter_type][shift], 16,
+ filter, 16,
NULL, 16, 2 * bs, 2 * bs < 16 ? 2 : 1);
flags[shift] = 1;
}
@@ -465,9 +466,10 @@
}
} else {
if (!flags[shift]) {
+ const int16_t *filter = vp10_intra_filter_kernels[filter_type][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,
+ filter, 16,
2 * bs < 16 ? 4 : 4, 2 * bs);
flags[shift] = 1;
}
diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c
index 679adc6..ecc971a 100644
--- a/vp10/common/thread_common.c
+++ b/vp10/common/thread_common.c
@@ -365,6 +365,11 @@
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
for (j = 0; j < SWITCHABLE_FILTERS; j++)
cm->counts.switchable_interp[i][j] += counts->switchable_interp[i][j];
+#if CONFIG_OBMC
+ for (i = 0; i < BLOCK_SIZES; i++)
+ for (j = 0; j < 2; j++)
+ cm->counts.obmc[i][j] += counts->obmc[i][j];
+#endif // CONFIG_OBMC
#if CONFIG_REF_MV
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
diff --git a/vp10/common/vp10_convolve.c b/vp10/common/vp10_convolve.c
index 33a8542..8fdd8f1 100644
--- a/vp10/common/vp10_convolve.c
+++ b/vp10/common/vp10_convolve.c
@@ -15,14 +15,15 @@
const InterpFilterParams filter_params,
const int subpel_x_q4, int x_step_q4, int avg) {
int x, y;
- int filter_size = filter_params.tap;
+ int filter_size = filter_params.taps;
src -= filter_size / 2 - 1;
for (y = 0; y < h; ++y) {
int x_q4 = subpel_x_q4;
for (x = 0; x < w; ++x) {
const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
const int16_t *x_filter =
- vp10_get_interp_filter_kernel(filter_params, x_q4 & SUBPEL_MASK);
+ vp10_get_interp_filter_subpel_kernel(
+ filter_params, x_q4 & SUBPEL_MASK);
int k, sum = 0;
for (k = 0; k < filter_size; ++k) sum += src_x[k] * x_filter[k];
if (avg) {
@@ -43,7 +44,7 @@
const InterpFilterParams filter_params,
const int subpel_y_q4, int y_step_q4, int avg) {
int x, y;
- int filter_size = filter_params.tap;
+ int filter_size = filter_params.taps;
src -= src_stride * (filter_size / 2 - 1);
for (x = 0; x < w; ++x) {
@@ -51,7 +52,8 @@
for (y = 0; y < h; ++y) {
const uint8_t *const src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
const int16_t *y_filter =
- vp10_get_interp_filter_kernel(filter_params, y_q4 & SUBPEL_MASK);
+ vp10_get_interp_filter_subpel_kernel(
+ filter_params, y_q4 & SUBPEL_MASK);
int k, sum = 0;
for (k = 0; k < filter_size; ++k)
sum += src_y[k * src_stride] * y_filter[k];
@@ -96,7 +98,7 @@
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;
+ int filter_size = filter_params.taps;
int ignore_horiz = x_step_q4 == 16 && subpel_x_q4 == 0;
int ignore_vert = y_step_q4 == 16 && subpel_y_q4 == 0;
@@ -104,7 +106,7 @@
assert(h <= MAX_BLOCK_HEIGHT);
assert(y_step_q4 <= MAX_STEP);
assert(x_step_q4 <= MAX_STEP);
- assert(filter_params.tap <= MAX_FILTER_TAP);
+ assert(filter_params.taps <= MAX_FILTER_TAP);
if (ignore_horiz && ignore_vert) {
convolve_copy(src, src_stride, dst, dst_stride, w, h, avg);
@@ -140,14 +142,15 @@
const int subpel_x_q4, int x_step_q4, int avg,
int bd) {
int x, y;
- int filter_size = filter_params.tap;
+ int filter_size = filter_params.taps;
src -= filter_size / 2 - 1;
for (y = 0; y < h; ++y) {
int x_q4 = subpel_x_q4;
for (x = 0; x < w; ++x) {
const uint16_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
const int16_t *x_filter =
- vp10_get_interp_filter_kernel(filter_params, x_q4 & SUBPEL_MASK);
+ vp10_get_interp_filter_subpel_kernel(
+ filter_params, x_q4 & SUBPEL_MASK);
int k, sum = 0;
for (k = 0; k < filter_size; ++k) sum += src_x[k] * x_filter[k];
if (avg)
@@ -170,7 +173,7 @@
const int subpel_y_q4, int y_step_q4, int avg,
int bd) {
int x, y;
- int filter_size = filter_params.tap;
+ int filter_size = filter_params.taps;
src -= src_stride * (filter_size / 2 - 1);
for (x = 0; x < w; ++x) {
@@ -178,7 +181,8 @@
for (y = 0; y < h; ++y) {
const uint16_t *const src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
const int16_t *y_filter =
- vp10_get_interp_filter_kernel(filter_params, y_q4 & SUBPEL_MASK);
+ vp10_get_interp_filter_subpel_kernel(
+ filter_params, y_q4 & SUBPEL_MASK);
int k, sum = 0;
for (k = 0; k < filter_size; ++k)
sum += src_y[k * src_stride] * y_filter[k];
@@ -228,7 +232,7 @@
int bd) {
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
- int filter_size = filter_params.tap;
+ int filter_size = filter_params.taps;
int ignore_horiz = x_step_q4 == 16 && subpel_x_q4 == 0;
int ignore_vert = y_step_q4 == 16 && subpel_y_q4 == 0;
@@ -236,7 +240,7 @@
assert(h <= MAX_BLOCK_HEIGHT);
assert(y_step_q4 <= MAX_STEP);
assert(x_step_q4 <= MAX_STEP);
- assert(filter_params.tap <= MAX_FILTER_TAP);
+ assert(filter_params.taps <= MAX_FILTER_TAP);
if (ignore_horiz && ignore_vert) {
highbd_convolve_copy(src, src_stride, dst, dst_stride, w, h, avg, bd);
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index a1b1534..4136f14 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -737,7 +737,7 @@
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
- int filter_size = filter_params.tap;
+ int filter_size = filter_params.taps;
if (subpel_x ||
#if CONFIG_EXT_INTERP
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index 7e0ee7d..fccd3c8 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -805,7 +805,7 @@
FRAME_COUNTS *counts = xd->counts;
INTERP_FILTER type;
#if CONFIG_EXT_INTERP
- if (!vp10_is_interp_needed(xd)) return EIGHTTAP;
+ if (!vp10_is_interp_needed(xd)) return EIGHTTAP_REGULAR;
#endif
type = (INTERP_FILTER)vpx_read_tree(r, vp10_switchable_interp_tree,
cm->fc->switchable_interp_prob[ctx]);
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index 6385f2f..fa6c2cb 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -868,7 +868,7 @@
const int ctx = vp10_get_pred_context_switchable_interp(xd);
#if CONFIG_EXT_INTERP
if (!vp10_is_interp_needed(xd)) {
- assert(mbmi->interp_filter == EIGHTTAP);
+ assert(mbmi->interp_filter == EIGHTTAP_REGULAR);
return;
}
#endif
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 7548456..d3ea94b 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -4021,22 +4021,22 @@
#if CONFIG_EXT_INTERP
if (!is_alt_ref &&
threshes[EIGHTTAP_SMOOTH2] > threshes[EIGHTTAP_SMOOTH] &&
- threshes[EIGHTTAP_SMOOTH2] > threshes[EIGHTTAP] &&
- threshes[EIGHTTAP_SMOOTH2] > threshes[EIGHTTAP_SHARP] &&
+ threshes[EIGHTTAP_SMOOTH2] > threshes[EIGHTTAP_REGULAR] &&
+ threshes[EIGHTTAP_SMOOTH2] > threshes[MULTITAP_SHARP] &&
threshes[EIGHTTAP_SMOOTH2] > threshes[SWITCHABLE - 1]) {
return EIGHTTAP_SMOOTH2;
}
#endif // CONFIG_EXT_INTERP
if (!is_alt_ref &&
- threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP] &&
- threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP_SHARP] &&
+ threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP_REGULAR] &&
+ threshes[EIGHTTAP_SMOOTH] > threshes[MULTITAP_SHARP] &&
threshes[EIGHTTAP_SMOOTH] > threshes[SWITCHABLE - 1]) {
return EIGHTTAP_SMOOTH;
- } else if (threshes[EIGHTTAP_SHARP] > threshes[EIGHTTAP] &&
- threshes[EIGHTTAP_SHARP] > threshes[SWITCHABLE - 1]) {
- return EIGHTTAP_SHARP;
- } else if (threshes[EIGHTTAP] > threshes[SWITCHABLE - 1]) {
- return EIGHTTAP;
+ } else if (threshes[MULTITAP_SHARP] > threshes[EIGHTTAP_REGULAR] &&
+ threshes[MULTITAP_SHARP] > threshes[SWITCHABLE - 1]) {
+ return MULTITAP_SHARP;
+ } else if (threshes[EIGHTTAP_REGULAR] > threshes[SWITCHABLE - 1]) {
+ return EIGHTTAP_REGULAR;
} else {
return SWITCHABLE;
}
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index d39d39e..fc9e2e9 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -410,6 +410,15 @@
vpx_free(cpi->active_map.map);
cpi->active_map.map = NULL;
+#if CONFIG_AFFINE_MOTION
+ {
+ // Free up-sampled reference buffers.
+ int i;
+ for (i = 0; i < MAX_REF_FRAMES; i++)
+ vpx_free_frame_buffer(&cpi->upsampled_ref_bufs[i].buf);
+ }
+#endif
+
vp10_free_ref_frame_buffers(cm->buffer_pool);
#if CONFIG_VP9_POSTPROC
vp10_free_postproc_buffers(cm);
@@ -744,6 +753,26 @@
NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled last source buffer");
+
+#if CONFIG_AFFINE_MOTION
+ {
+ // Allocate up-sampled reference buffers.
+ int i;
+
+ for (i = 0; i < MAX_REF_FRAMES; i++)
+ if (vpx_realloc_frame_buffer(&cpi->upsampled_ref_bufs[i].buf,
+ (cm->width << 3), (cm->height << 3),
+ cm->subsampling_x, cm->subsampling_y,
+#if CONFIG_VP9_HIGHBITDEPTH
+ cm->use_highbitdepth,
+#endif
+ (VP9_ENC_BORDER_IN_PIXELS << 3),
+ cm->byte_alignment,
+ NULL, NULL, NULL))
+ vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate up-sampled reference frame buffer");
+ }
+#endif
}
@@ -2353,10 +2382,11 @@
#if CONFIG_VP9_HIGHBITDEPTH
static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
- YV12_BUFFER_CONFIG *dst, int bd) {
+ YV12_BUFFER_CONFIG *dst, int planes,
+ int bd) {
#else
static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
- YV12_BUFFER_CONFIG *dst) {
+ YV12_BUFFER_CONFIG *dst, int planes) {
#endif // CONFIG_VP9_HIGHBITDEPTH
const int src_w = src->y_crop_width;
const int src_h = src->y_crop_height;
@@ -2366,12 +2396,15 @@
const int src_strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
uint8_t *const dsts[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
- const InterpKernel *const kernel = vp10_filter_kernels[EIGHTTAP];
+ const InterpFilterParams interp_filter_params =
+ vp10_get_interp_filter_params(EIGHTTAP_REGULAR);
+ const int16_t *kernel = interp_filter_params.filter_ptr;
+ const int taps = interp_filter_params.taps;
int x, y, i;
for (y = 0; y < dst_h; y += 16) {
for (x = 0; x < dst_w; x += 16) {
- for (i = 0; i < MAX_MB_PLANE; ++i) {
+ for (i = 0; i < planes; ++i) {
const int factor = (i == 0 || i == 3 ? 1 : 2);
const int x_q4 = x * (16 / factor) * src_w / dst_w;
const int y_q4 = y * (16 / factor) * src_h / dst_h;
@@ -2384,26 +2417,29 @@
#if CONFIG_VP9_HIGHBITDEPTH
if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
vpx_highbd_convolve8(src_ptr, src_stride, dst_ptr, dst_stride,
- kernel[x_q4 & 0xf], 16 * src_w / dst_w,
- kernel[y_q4 & 0xf], 16 * src_h / dst_h,
+ &kernel[(x_q4 & 0xf) * taps], 16 * src_w / dst_w,
+ &kernel[(y_q4 & 0xf) * taps], 16 * src_h / dst_h,
16 / factor, 16 / factor, bd);
} else {
- vpx_convolve8(src_ptr, src_stride, dst_ptr, dst_stride,
- kernel[x_q4 & 0xf], 16 * src_w / dst_w,
- kernel[y_q4 & 0xf], 16 * src_h / dst_h,
+ vpx_scaled_2d(src_ptr, src_stride, dst_ptr, dst_stride,
+ &kernel[(x_q4 & 0xf) * taps], 16 * src_w / dst_w,
+ &kernel[(y_q4 & 0xf) * taps], 16 * src_h / dst_h,
16 / factor, 16 / factor);
}
#else
- vpx_convolve8(src_ptr, src_stride, dst_ptr, dst_stride,
- kernel[x_q4 & 0xf], 16 * src_w / dst_w,
- kernel[y_q4 & 0xf], 16 * src_h / dst_h,
+ vpx_scaled_2d(src_ptr, src_stride, dst_ptr, dst_stride,
+ &kernel[(x_q4 & 0xf) * taps], 16 * src_w / dst_w,
+ &kernel[(y_q4 & 0xf) * taps], 16 * src_h / dst_h,
16 / factor, 16 / factor);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
}
}
- vpx_extend_frame_borders(dst);
+ if (planes == 1)
+ vpx_extend_frame_borders_y(dst);
+ else
+ vpx_extend_frame_borders(dst);
}
static int scale_down(VP10_COMP *cpi, int q) {
@@ -2459,6 +2495,45 @@
return force_recode;
}
+#if CONFIG_AFFINE_MOTION
+static INLINE int get_free_upsampled_ref_buf(EncRefCntBuffer *ubufs) {
+ int i;
+
+ for (i = 0; i < MAX_REF_FRAMES; i++) {
+ if (!ubufs[i].ref_count) {
+ return i;
+ }
+ }
+ return INVALID_IDX;
+}
+
+// Up-sample reference frames.
+static INLINE int upsample_ref_frame(RefCntBuffer *bufs,
+#if CONFIG_VP9_HIGHBITDEPTH
+ EncRefCntBuffer *ubufs, int new_idx,
+ int bit_depth) {
+#else
+ EncRefCntBuffer *ubufs, int new_idx) {
+#endif
+ int new_uidx = get_free_upsampled_ref_buf(ubufs);
+
+ if (new_uidx == INVALID_IDX) {
+ return INVALID_IDX;
+ } else {
+ const YV12_BUFFER_CONFIG *const ref = &bufs[new_idx].buf;
+ YV12_BUFFER_CONFIG *upsampled_ref = &ubufs[new_uidx].buf;
+
+ // Currently, only Y plane is up-sampled, U, V are not used.
+#if CONFIG_VP9_HIGHBITDEPTH
+ scale_and_extend_frame(ref, upsampled_ref, 1, bit_depth);
+#else
+ scale_and_extend_frame(ref, upsampled_ref, 1);
+#endif
+ return new_uidx;
+ }
+}
+#endif
+
void vp10_update_reference_frames(VP10_COMP *cpi) {
VP10_COMMON * const cm = &cpi->common;
BufferPool *const pool = cm->buffer_pool;
@@ -2466,6 +2541,17 @@
int ref_frame;
#endif // CONFIG_EXT_REFS
+#if CONFIG_AFFINE_MOTION
+ // Always up-sample the current encoded frame.
+#if CONFIG_VP9_HIGHBITDEPTH
+ int new_uidx = upsample_ref_frame(pool->frame_bufs, cpi->upsampled_ref_bufs,
+ cm->new_fb_idx, (int)cm->bit_depth);
+#else
+ int new_uidx = upsample_ref_frame(pool->frame_bufs, cpi->upsampled_ref_bufs,
+ cm->new_fb_idx);
+#endif
+#endif
+
// At this point the new frame has been encoded.
// If any buffer copy / swapping is signaled it should be done here.
if (cm->frame_type == KEY_FRAME) {
@@ -2473,6 +2559,13 @@
&cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
+
+#if CONFIG_AFFINE_MOTION
+ uref_cnt_fb(cpi->upsampled_ref_bufs,
+ &cpi->upsampled_ref_idx[cpi->gld_fb_idx], new_uidx);
+ uref_cnt_fb(cpi->upsampled_ref_bufs,
+ &cpi->upsampled_ref_idx[cpi->alt_fb_idx], new_uidx);
+#endif
} else if (vp10_preserve_existing_gf(cpi)) {
// We have decided to preserve the previously existing golden frame as our
// new ARF frame. However, in the short term in function
@@ -2486,7 +2579,10 @@
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
-
+#if CONFIG_AFFINE_MOTION
+ uref_cnt_fb(cpi->upsampled_ref_bufs,
+ &cpi->upsampled_ref_idx[cpi->alt_fb_idx], new_uidx);
+#endif
tmp = cpi->alt_fb_idx;
cpi->alt_fb_idx = cpi->gld_fb_idx;
cpi->gld_fb_idx = tmp;
@@ -2500,6 +2596,10 @@
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[arf_idx], cm->new_fb_idx);
+#if CONFIG_AFFINE_MOTION
+ uref_cnt_fb(cpi->upsampled_ref_bufs,
+ &cpi->upsampled_ref_idx[cpi->alt_fb_idx], new_uidx);
+#endif
memcpy(cpi->interp_filter_selected[ALTREF_FRAME],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
@@ -2508,6 +2608,10 @@
if (cpi->refresh_golden_frame) {
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
+#if CONFIG_AFFINE_MOTION
+ uref_cnt_fb(cpi->upsampled_ref_bufs,
+ &cpi->upsampled_ref_idx[cpi->gld_fb_idx], new_uidx);
+#endif
if (!cpi->rc.is_src_frame_alt_ref)
memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
cpi->interp_filter_selected[0],
@@ -2542,6 +2646,10 @@
if (cpi->refresh_last_frame) {
ref_cnt_fb(pool->frame_bufs,
&cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
+#if CONFIG_AFFINE_MOTION
+ uref_cnt_fb(cpi->upsampled_ref_bufs,
+ &cpi->upsampled_ref_idx[cpi->lst_fb_idx], new_uidx);
+#endif
if (!cpi->rc.is_src_frame_alt_ref) {
memcpy(cpi->interp_filter_selected[LAST_FRAME],
cpi->interp_filter_selected[0],
@@ -2675,7 +2783,8 @@
cm->byte_alignment, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffer");
- scale_and_extend_frame(ref, &new_fb_ptr->buf, (int)cm->bit_depth);
+ scale_and_extend_frame(ref, &new_fb_ptr->buf, MAX_MB_PLANE,
+ (int)cm->bit_depth);
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
alloc_frame_mvs(cm, new_fb);
}
@@ -2700,11 +2809,39 @@
cm->byte_alignment, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffer");
- scale_and_extend_frame(ref, &new_fb_ptr->buf);
+ scale_and_extend_frame(ref, &new_fb_ptr->buf, MAX_MB_PLANE);
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
alloc_frame_mvs(cm, new_fb);
}
#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_AFFINE_MOTION
+ {
+ const int map_idx = get_ref_frame_map_idx(cpi, ref_frame);
+ EncRefCntBuffer *ubuf =
+ &cpi->upsampled_ref_bufs[cpi->upsampled_ref_idx[map_idx]];
+
+ if (vpx_realloc_frame_buffer(&ubuf->buf,
+ (cm->width << 3), (cm->height << 3),
+ cm->subsampling_x, cm->subsampling_y,
+#if CONFIG_VP9_HIGHBITDEPTH
+ cm->use_highbitdepth,
+#endif
+ (VP9_ENC_BORDER_IN_PIXELS << 3),
+ cm->byte_alignment,
+ NULL, NULL, NULL))
+ vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate up-sampled frame buffer");
+#if CONFIG_VP9_HIGHBITDEPTH
+ scale_and_extend_frame(&new_fb_ptr->buf, &ubuf->buf, MAX_MB_PLANE,
+ (int)cm->bit_depth);
+#else
+ scale_and_extend_frame(&new_fb_ptr->buf, &ubuf->buf, MAX_MB_PLANE);
+#endif
+ cpi->scaled_ref_idx[ref_frame - LAST_FRAME] = new_fb;
+ alloc_frame_mvs(cm, new_fb);
+ }
+#endif
} else {
const int buf_idx = get_ref_frame_buf_idx(cpi, ref_frame);
RefCntBuffer *const buf = &pool->frame_bufs[buf_idx];
@@ -3522,10 +3659,10 @@
cpi->refresh_alt_ref_frame)
return mask;
for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref)
- for (ifilter = EIGHTTAP; ifilter < SWITCHABLE_FILTERS; ++ifilter)
+ for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
- for (ifilter = EIGHTTAP; ifilter < SWITCHABLE_FILTERS; ++ifilter) {
+ for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter) {
if ((ref_total[LAST_FRAME] &&
cpi->interp_filter_selected[LAST_FRAME][ifilter] == 0) &&
#if CONFIG_EXT_REFS
@@ -3784,6 +3921,17 @@
}
}
+#if CONFIG_AFFINE_MOTION
+static INLINE void init_upsampled_ref_frame_bufs(VP10_COMP *cpi) {
+ int i;
+
+ for (i = 0; i < MAX_REF_FRAMES; ++i) {
+ cpi->upsampled_ref_bufs[i].ref_count = 0;
+ cpi->upsampled_ref_idx[i] = INVALID_IDX;
+ }
+}
+#endif
+
static void check_initial_width(VP10_COMP *cpi,
#if CONFIG_VP9_HIGHBITDEPTH
int use_highbitdepth,
@@ -3806,7 +3954,9 @@
alloc_raw_frame_buffers(cpi);
init_ref_frame_bufs(cm);
alloc_util_frame_buffers(cpi);
-
+#if CONFIG_AFFINE_MOTION
+ init_upsampled_ref_frame_bufs(cpi);
+#endif
init_motion_estimation(cpi); // TODO(agrange) This can be removed.
cpi->initial_width = cm->width;
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index 292494c..efde0fc 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -286,6 +286,13 @@
double worst;
} ImageStat;
+#if CONFIG_AFFINE_MOTION
+typedef struct {
+ int ref_count;
+ YV12_BUFFER_CONFIG buf;
+} EncRefCntBuffer;
+#endif
+
typedef struct VP10_COMP {
QUANTS quants;
ThreadData td;
@@ -304,6 +311,12 @@
YV12_BUFFER_CONFIG *unscaled_last_source;
YV12_BUFFER_CONFIG scaled_last_source;
+#if CONFIG_AFFINE_MOTION
+ // Up-sampled reference buffers
+ EncRefCntBuffer upsampled_ref_bufs[MAX_REF_FRAMES];
+ int upsampled_ref_idx[MAX_REF_FRAMES];
+#endif
+
TileDataEnc *tile_data;
int allocated_tiles; // Keep track of memory allocated for tiles.
@@ -688,6 +701,20 @@
#define LAYER_IDS_TO_IDX(sl, tl, num_tl) ((sl) * (num_tl) + (tl))
+#if CONFIG_AFFINE_MOTION
+// Update up-sampled reference frame index.
+static INLINE void uref_cnt_fb(EncRefCntBuffer *ubufs, int *uidx,
+ int new_uidx) {
+ const int ref_index = *uidx;
+
+ if (ref_index >= 0 && ubufs[ref_index].ref_count > 0)
+ ubufs[ref_index].ref_count--;
+
+ *uidx = new_uidx;
+ ubufs[new_uidx].ref_count++;
+}
+#endif
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp10/encoder/mbgraph.c b/vp10/encoder/mbgraph.c
index 2d3a33e..1f467b8 100644
--- a/vp10/encoder/mbgraph.c
+++ b/vp10/encoder/mbgraph.c
@@ -64,7 +64,11 @@
&v_fn_ptr, 0, mv_sf->subpel_iters_per_step,
cond_cost_list(cpi, cost_list),
NULL, NULL,
+#if CONFIG_AFFINE_MOTION
+ &distortion, &sse, NULL, 0, 0, 0);
+#else
&distortion, &sse, NULL, 0, 0);
+#endif
}
#if CONFIG_EXT_INTER
diff --git a/vp10/encoder/mcomp.c b/vp10/encoder/mcomp.c
index 6e3b06a..8949f76 100644
--- a/vp10/encoder/mcomp.c
+++ b/vp10/encoder/mcomp.c
@@ -208,6 +208,32 @@
v = INT_MAX; \
}
+#define CHECK_BETTER0(v, r, c) CHECK_BETTER(v, r, c)
+
+#if CONFIG_AFFINE_MOTION
+static INLINE const uint8_t *upre(const uint8_t *buf, int stride,
+ int r, int c) {
+ return &buf[(r) * stride + (c)];
+}
+
+/* checks if (r, c) has better score than previous best */
+#define CHECK_BETTER1(v, r, c) \
+ if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
+ thismse = upsampled_pref_error(xd, vfp, z, src_stride, \
+ upre(y, y_stride, r, c), y_stride, \
+ second_pred, w, h, &sse); \
+ if ((v = MVC(r, c) + thismse) < besterr) { \
+ besterr = v; \
+ br = r; \
+ bc = c; \
+ *distortion = thismse; \
+ *sse1 = sse; \
+ } \
+ } else { \
+ v = INT_MAX; \
+ }
+#endif
+
#define FIRST_LEVEL_CHECKS \
{ \
unsigned int left, right, up, down, diag; \
@@ -276,7 +302,7 @@
// TODO(yunqingwang): SECOND_LEVEL_CHECKS_BEST was a rewrote of
// SECOND_LEVEL_CHECKS, and SECOND_LEVEL_CHECKS should be rewritten
// later in the same way.
-#define SECOND_LEVEL_CHECKS_BEST \
+#define SECOND_LEVEL_CHECKS_BEST(k) \
{ \
unsigned int second; \
int br0 = br; \
@@ -287,10 +313,10 @@
} else if (tr != br && tc == bc) { \
kr = br - tr; \
} \
- CHECK_BETTER(second, br0 + kr, bc0); \
- CHECK_BETTER(second, br0, bc0 + kc); \
+ CHECK_BETTER##k(second, br0 + kr, bc0); \
+ CHECK_BETTER##k(second, br0, bc0 + kc); \
if (br0 != br || bc0 != bc) { \
- CHECK_BETTER(second, br0 + kr, bc0 + kc); \
+ CHECK_BETTER##k(second, br0 + kr, bc0 + kc); \
} \
}
@@ -412,7 +438,11 @@
int *distortion,
unsigned int *sse1,
const uint8_t *second_pred,
+#if CONFIG_AFFINE_MOTION
+ int w, int h, int use_upsampled_ref) {
+#else
int w, int h) {
+#endif
SETUP_SUBPEL_SEARCH;
besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp,
z, src_stride, y, y_stride, second_pred,
@@ -425,6 +455,9 @@
(void) allow_hp;
(void) forced_stop;
(void) hstep;
+#if CONFIG_AFFINE_MOTION
+ (void) use_upsampled_ref;
+#endif
if (cost_list &&
cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
@@ -491,8 +524,17 @@
int *distortion,
unsigned int *sse1,
const uint8_t *second_pred,
+#if CONFIG_AFFINE_MOTION
+ int w, int h,
+ int use_upsampled_ref) {
+#else
int w, int h) {
+#endif
SETUP_SUBPEL_SEARCH;
+#if CONFIG_AFFINE_MOTION
+ (void) use_upsampled_ref;
+#endif
+
besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp,
z, src_stride, y, y_stride, second_pred,
w, h, offset, mvjcost, mvcost,
@@ -565,8 +607,16 @@
int *distortion,
unsigned int *sse1,
const uint8_t *second_pred,
+#if CONFIG_AFFINE_MOTION
+ int w, int h, int use_upsampled_ref) {
+#else
int w, int h) {
+#endif
SETUP_SUBPEL_SEARCH;
+#if CONFIG_AFFINE_MOTION
+ (void) use_upsampled_ref;
+#endif
+
besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp,
z, src_stride, y, y_stride, second_pred,
w, h, offset, mvjcost, mvcost,
@@ -655,6 +705,101 @@
{0, -1}, {0, 1}, {-1, 0}, {1, 0}
};
+
+#if CONFIG_AFFINE_MOTION
+#if CONFIG_VP9_HIGHBITDEPTH
+static void highbd_comp_avg_upsampled_pred(uint16_t *comp_pred,
+ const uint8_t *pred8,
+ int width, int height,
+ const uint8_t *ref8,
+ int ref_stride) {
+ int i, j;
+ int stride = ref_stride << 3;
+
+ uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
+ uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
+ for (i = 0; i < height; ++i) {
+ for (j = 0; j < width; ++j) {
+ const int tmp = pred[j] + ref[(j << 3)];
+ comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
+ }
+ comp_pred += width;
+ pred += width;
+ ref += stride;
+ }
+}
+
+static void highbd_upsampled_pred(uint16_t *comp_pred,
+ int width, int height,
+ const uint8_t *ref8,
+ int ref_stride) {
+ int i, j;
+ int stride = ref_stride << 3;
+
+ uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
+ for (i = 0; i < height; ++i) {
+ for (j = 0; j < width; ++j) {
+ comp_pred[j] = ref[(j << 3)];
+ }
+ comp_pred += width;
+ ref += stride;
+ }
+}
+#endif
+
+static int upsampled_pref_error(const MACROBLOCKD *xd,
+ const vp9_variance_fn_ptr_t *vfp,
+ const uint8_t *const src, const int src_stride,
+ const uint8_t *const y, int y_stride,
+ const uint8_t *second_pred,
+ int w, int h, unsigned int *sse) {
+ unsigned int besterr;
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+ DECLARE_ALIGNED(16, uint16_t, pred16[64 * 64]);
+ if (second_pred != NULL)
+ highbd_comp_avg_upsampled_pred(pred16, second_pred, w, h, y,
+ y_stride);
+ else
+ highbd_upsampled_pred(pred16, w, h, y, y_stride);
+
+ besterr = vfp->vf(CONVERT_TO_BYTEPTR(pred16), w, src, src_stride,
+ sse);
+ } else {
+ DECLARE_ALIGNED(16, uint8_t, pred[64 * 64]);
+#else
+ DECLARE_ALIGNED(16, uint8_t, pred[64 * 64]);
+ (void) xd;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ if (second_pred != NULL)
+ vpx_comp_avg_upsampled_pred(pred, second_pred, w, h, y,
+ y_stride);
+ else
+ vpx_upsampled_pred(pred, w, h, y, y_stride);
+
+ besterr = vfp->vf(pred, w, src, src_stride, sse);
+#if CONFIG_VP9_HIGHBITDEPTH
+ }
+#endif
+return besterr;
+}
+
+static unsigned int upsampled_setup_center_error(
+ const MACROBLOCKD *xd, const MV *bestmv, const MV *ref_mv,
+ int error_per_bit, const vp9_variance_fn_ptr_t *vfp,
+ const uint8_t *const src, const int src_stride,
+ const uint8_t *const y, int y_stride, const uint8_t *second_pred,
+ int w, int h, int offset, int *mvjcost, int *mvcost[2],
+ unsigned int *sse1, int *distortion) {
+ unsigned int besterr = upsampled_pref_error(xd, vfp, src, src_stride,
+ y + offset, y_stride, second_pred,
+ w, h, sse1);
+ *distortion = besterr;
+ besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
+ return besterr;
+}
+#endif
+
int vp10_find_best_sub_pixel_tree(const MACROBLOCK *x,
MV *bestmv, const MV *ref_mv,
int allow_hp,
@@ -667,14 +812,18 @@
int *distortion,
unsigned int *sse1,
const uint8_t *second_pred,
+#if CONFIG_AFFINE_MOTION
+ int w, int h, int use_upsampled_ref) {
+#else
int w, int h) {
+#endif
const uint8_t *const z = x->plane[0].src.buf;
const uint8_t *const src_address = z;
const int src_stride = x->plane[0].src.stride;
const MACROBLOCKD *xd = &x->e_mbd;
unsigned int besterr = INT_MAX;
unsigned int sse;
- int thismse;
+ unsigned int thismse;
const int y_stride = xd->plane[0].pre[0].stride;
const int offset = bestmv->row * y_stride + bestmv->col;
const uint8_t *const y = xd->plane[0].pre[0].buf;
@@ -703,10 +852,19 @@
bestmv->row *= 8;
bestmv->col *= 8;
- besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp,
- z, src_stride, y, y_stride, second_pred,
- w, h, offset, mvjcost, mvcost,
- sse1, distortion);
+#if CONFIG_AFFINE_MOTION
+ // use_upsampled_ref can be 0 or 1
+ if (use_upsampled_ref)
+ besterr = upsampled_setup_center_error(xd, bestmv, ref_mv, error_per_bit,
+ vfp, z, src_stride, y, y_stride,
+ second_pred, w, h, (offset << 3),
+ mvjcost, mvcost, sse1, distortion);
+ else
+#endif
+ besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp,
+ z, src_stride, y, y_stride, second_pred,
+ w, h, offset, mvjcost, mvcost,
+ sse1, distortion);
(void) cost_list; // to silence compiler warning
@@ -716,16 +874,29 @@
tr = br + search_step[idx].row;
tc = bc + search_step[idx].col;
if (tc >= minc && tc <= maxc && tr >= minr && tr <= maxr) {
- const uint8_t *const pre_address = y + (tr >> 3) * y_stride + (tc >> 3);
- MV this_mv;
- this_mv.row = tr;
- this_mv.col = tc;
- if (second_pred == NULL)
- thismse = vfp->svf(pre_address, y_stride, sp(tc), sp(tr),
- src_address, src_stride, &sse);
- else
- thismse = vfp->svaf(pre_address, y_stride, sp(tc), sp(tr),
- src_address, src_stride, &sse, second_pred);
+ MV this_mv = {tr, tc};
+
+#if CONFIG_AFFINE_MOTION
+ if (use_upsampled_ref) {
+ const uint8_t *const pre_address = y + tr * y_stride + tc;
+
+ thismse = upsampled_pref_error(xd, vfp, src_address, src_stride,
+ pre_address, y_stride, second_pred,
+ w, h, &sse);
+ } else {
+#endif
+ const uint8_t *const pre_address = y + (tr >> 3) * y_stride +
+ (tc >> 3);
+ if (second_pred == NULL)
+ thismse = vfp->svf(pre_address, y_stride, sp(tc), sp(tr),
+ src_address, src_stride, &sse);
+ else
+ thismse = vfp->svaf(pre_address, y_stride, sp(tc), sp(tr),
+ src_address, src_stride, &sse, second_pred);
+#if CONFIG_AFFINE_MOTION
+ }
+#endif
+
cost_array[idx] = thismse +
mv_err_cost(&this_mv, ref_mv, mvjcost, mvcost, error_per_bit);
@@ -747,14 +918,29 @@
tc = bc + kc;
tr = br + kr;
if (tc >= minc && tc <= maxc && tr >= minr && tr <= maxr) {
- const uint8_t *const pre_address = y + (tr >> 3) * y_stride + (tc >> 3);
MV this_mv = {tr, tc};
- if (second_pred == NULL)
- thismse = vfp->svf(pre_address, y_stride, sp(tc), sp(tr),
- src_address, src_stride, &sse);
- else
- thismse = vfp->svaf(pre_address, y_stride, sp(tc), sp(tr),
- src_address, src_stride, &sse, second_pred);
+
+#if CONFIG_AFFINE_MOTION
+ if (use_upsampled_ref) {
+ const uint8_t *const pre_address = y + tr * y_stride + tc;
+
+ thismse = upsampled_pref_error(xd, vfp, src_address, src_stride,
+ pre_address, y_stride, second_pred,
+ w, h, &sse);
+ } else {
+#endif
+ const uint8_t *const pre_address = y + (tr >> 3) * y_stride + (tc >> 3);
+
+ if (second_pred == NULL)
+ thismse = vfp->svf(pre_address, y_stride, sp(tc), sp(tr),
+ src_address, src_stride, &sse);
+ else
+ thismse = vfp->svaf(pre_address, y_stride, sp(tc), sp(tr),
+ src_address, src_stride, &sse, second_pred);
+#if CONFIG_AFFINE_MOTION
+ }
+#endif
+
cost_array[4] = thismse +
mv_err_cost(&this_mv, ref_mv, mvjcost, mvcost, error_per_bit);
@@ -776,8 +962,17 @@
bc = tc;
}
- if (iters_per_step > 1 && best_idx != -1)
- SECOND_LEVEL_CHECKS_BEST;
+ if (iters_per_step > 1 && best_idx != -1) {
+#if CONFIG_AFFINE_MOTION
+ if (use_upsampled_ref) {
+ SECOND_LEVEL_CHECKS_BEST(1);
+ } else {
+#endif
+ SECOND_LEVEL_CHECKS_BEST(0);
+#if CONFIG_AFFINE_MOTION
+ }
+#endif
+ }
tr = br;
tc = bc;
diff --git a/vp10/encoder/mcomp.h b/vp10/encoder/mcomp.h
index 9d1ab2a..3063b99 100644
--- a/vp10/encoder/mcomp.h
+++ b/vp10/encoder/mcomp.h
@@ -116,7 +116,11 @@
int *mvjcost, int *mvcost[2],
int *distortion, unsigned int *sse1,
const uint8_t *second_pred,
+#if CONFIG_AFFINE_MOTION
+ int w, int h, int use_upsampled_ref);
+#else
int w, int h);
+#endif
extern fractional_mv_step_fp vp10_find_best_sub_pixel_tree;
extern fractional_mv_step_fp vp10_find_best_sub_pixel_tree_pruned;
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index ff07489..96edc0f 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -2404,7 +2404,7 @@
MACROBLOCKD *xd = &x->e_mbd;
const struct macroblock_plane *const p = &x->plane[plane];
struct macroblockd_plane *const pd = &xd->plane[plane];
- unsigned int tmp;
+ int64_t tmp;
tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
@@ -2472,7 +2472,7 @@
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
tmp = ROUNDZ_POWER_OF_TWO(tmp, (xd->bd - 8) * 2);
#endif // CONFIG_VP9_HIGHBITDEPTH
- *bsse += (int64_t)tmp * 16;
+ *bsse += tmp * 16;
if (p->eobs[block] > 0) {
const int lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
@@ -2544,12 +2544,12 @@
}
}
} else {
- cpi->fn_ptr[txm_bsize].vf(src, src_stride,
- rec_buffer, 32, &tmp);
+ uint32_t this_dist;
+ cpi->fn_ptr[txm_bsize].vf(src, src_stride, rec_buffer, 32, &this_dist);
+ tmp = this_dist;
}
}
- *dist += (int64_t)tmp * 16;
-
+ *dist += tmp * 16;
*rate += cost_coeffs(x, plane, block, coeff_ctx, tx_size,
scan_order->scan, scan_order->neighbors, 0);
*skip &= (p->eobs[block] == 0);
@@ -3929,7 +3929,8 @@
int_mv* ref_mv_sub8x8[2],
#endif
int_mv single_newmv[MAX_REF_FRAMES],
- int *rate_mv) {
+ int *rate_mv,
+ const int block) {
const VP10_COMMON *const cm = &cpi->common;
const int pw = 4 * num_4x4_blocks_wide_lookup[bsize];
const int ph = 4 * num_4x4_blocks_high_lookup[bsize];
@@ -4076,6 +4077,40 @@
if (bestsme < INT_MAX) {
int dis; /* TODO: use dis in distortion calculation later. */
unsigned int sse;
+#if CONFIG_AFFINE_MOTION
+ // Use up-sampled reference frames.
+ struct macroblockd_plane *const pd = &xd->plane[0];
+ struct buf_2d backup_pred = pd->pre[0];
+ const YV12_BUFFER_CONFIG *upsampled_ref =
+ get_upsampled_ref(cpi, refs[id]);
+
+ // Set pred for Y plane
+ setup_pred_plane(&pd->pre[0], upsampled_ref->y_buffer,
+ upsampled_ref->y_stride, (mi_row << 3), (mi_col << 3),
+ NULL, pd->subsampling_x, pd->subsampling_y);
+
+ // If bsize < BLOCK_8X8, adjust pred pointer for this block
+ if (bsize < BLOCK_8X8)
+ pd->pre[0].buf =
+ &pd->pre[0].buf[(vp10_raster_block_offset(BLOCK_8X8, block,
+ pd->pre[0].stride)) << 3];
+
+ bestsme = cpi->find_fractional_mv_step(
+ x, &tmp_mv,
+ &ref_mv[id].as_mv,
+ cpi->common.allow_high_precision_mv,
+ x->errorperbit,
+ &cpi->fn_ptr[bsize],
+ 0, cpi->sf.mv.subpel_iters_per_step,
+ NULL,
+ x->nmvjointcost, x->mvcost,
+ &dis, &sse, second_pred,
+ pw, ph, 1);
+
+ // Restore the reference frames.
+ pd->pre[0] = backup_pred;
+#else
+ (void) block;
bestsme = cpi->find_fractional_mv_step(
x, &tmp_mv,
&ref_mv[id].as_mv,
@@ -4087,6 +4122,7 @@
x->nmvjointcost, x->mvcost,
&dis, &sse, second_pred,
pw, ph);
+#endif
}
// Restore the pointer to the first (possibly scaled) prediction buffer.
@@ -4367,6 +4403,43 @@
if (bestsme < INT_MAX) {
int distortion;
+#if CONFIG_AFFINE_MOTION
+ const int pw = 4 * num_4x4_blocks_wide_lookup[bsize];
+ const int ph = 4 * num_4x4_blocks_high_lookup[bsize];
+ // Use up-sampled reference frames.
+ struct macroblockd_plane *const pd = &xd->plane[0];
+ struct buf_2d backup_pred = pd->pre[0];
+ const YV12_BUFFER_CONFIG *upsampled_ref =
+ get_upsampled_ref(cpi, mbmi->ref_frame[0]);
+
+ // Set pred for Y plane
+ setup_pred_plane(&pd->pre[0], upsampled_ref->y_buffer,
+ upsampled_ref->y_stride,
+ (mi_row << 3), (mi_col << 3),
+ NULL, pd->subsampling_x, pd->subsampling_y);
+
+ // adjust pred pointer for this block
+ pd->pre[0].buf =
+ &pd->pre[0].buf[(vp10_raster_block_offset(BLOCK_8X8, i,
+ pd->pre[0].stride)) << 3];
+
+ cpi->find_fractional_mv_step(
+ x,
+ new_mv,
+ &bsi->ref_mv[0]->as_mv,
+ cm->allow_high_precision_mv,
+ x->errorperbit, &cpi->fn_ptr[bsize],
+ cpi->sf.mv.subpel_force_stop,
+ cpi->sf.mv.subpel_iters_per_step,
+ cond_cost_list(cpi, cost_list),
+ x->nmvjointcost, x->mvcost,
+ &distortion,
+ &x->pred_sse[mbmi->ref_frame[0]],
+ NULL, pw, ph, 1);
+
+ // Restore the reference frames.
+ pd->pre[0] = backup_pred;
+#else
cpi->find_fractional_mv_step(
x,
new_mv,
@@ -4380,6 +4453,7 @@
&distortion,
&x->pred_sse[mbmi->ref_frame[0]],
NULL, 0, 0);
+#endif
// save motion search result for use in compound prediction
#if CONFIG_EXT_INTER
@@ -4413,7 +4487,7 @@
#else
this_mode == NEWMV &&
#endif // CONFIG_EXT_INTER
- mbmi->interp_filter == EIGHTTAP) {
+ mbmi->interp_filter == EIGHTTAP_REGULAR) {
// adjust src pointers
mi_buf_shift(x, i);
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
@@ -4426,7 +4500,7 @@
#else
seg_mvs[i],
#endif // CONFIG_EXT_INTER
- &rate_mv);
+ &rate_mv, i);
#if CONFIG_EXT_INTER
compound_seg_newmvs[i][0].as_int =
frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
@@ -4975,6 +5049,33 @@
if (bestsme < INT_MAX) {
int dis; /* TODO: use dis in distortion calculation later. */
+#if CONFIG_AFFINE_MOTION
+ const int pw = 4 * num_4x4_blocks_wide_lookup[bsize];
+ const int ph = 4 * num_4x4_blocks_high_lookup[bsize];
+ // Use up-sampled reference frames.
+ struct macroblockd_plane *const pd = &xd->plane[0];
+ struct buf_2d backup_pred = pd->pre[0];
+ const YV12_BUFFER_CONFIG *upsampled_ref = get_upsampled_ref(cpi, ref);
+
+ // Set pred for Y plane
+ setup_pred_plane(&pd->pre[0], upsampled_ref->y_buffer,
+ upsampled_ref->y_stride, (mi_row << 3), (mi_col << 3),
+ NULL, pd->subsampling_x, pd->subsampling_y);
+
+ bestsme = cpi->find_fractional_mv_step(x, &tmp_mv->as_mv, &ref_mv,
+ cm->allow_high_precision_mv,
+ x->errorperbit,
+ &cpi->fn_ptr[bsize],
+ cpi->sf.mv.subpel_force_stop,
+ cpi->sf.mv.subpel_iters_per_step,
+ cond_cost_list(cpi, cost_list),
+ x->nmvjointcost, x->mvcost,
+ &dis, &x->pred_sse[ref], NULL,
+ pw, ph, 1);
+
+ // Restore the reference frames.
+ pd->pre[0] = backup_pred;
+#else
cpi->find_fractional_mv_step(x, &tmp_mv->as_mv, &ref_mv,
cm->allow_high_precision_mv,
x->errorperbit,
@@ -4984,6 +5085,7 @@
cond_cost_list(cpi, cost_list),
x->nmvjointcost, x->mvcost,
&dis, &x->pred_sse[ref], NULL, 0, 0);
+#endif
}
*rate_mv = vp10_mv_bit_cost(&tmp_mv->as_mv, &ref_mv,
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
@@ -5139,11 +5241,11 @@
}
if (cm->interp_filter != BILINEAR) {
if (x->source_variance < cpi->sf.disable_filter_search_var_thresh) {
- best_filter = EIGHTTAP;
+ best_filter = EIGHTTAP_REGULAR;
}
#if CONFIG_EXT_INTERP
else if (!vp10_is_interp_needed(xd) && cm->interp_filter == SWITCHABLE) {
- best_filter = EIGHTTAP;
+ best_filter = EIGHTTAP_REGULAR;
}
#endif
}
@@ -5328,7 +5430,7 @@
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
joint_motion_search(cpi, x, bsize, frame_mv,
- mi_row, mi_col, NULL, single_newmv, &rate_mv);
+ mi_row, mi_col, NULL, single_newmv, &rate_mv, 0);
} else {
rate_mv = vp10_mv_bit_cost(&frame_mv[refs[0]].as_mv,
&x->mbmi_ext->ref_mvs[refs[0]][0].as_mv,
@@ -5358,7 +5460,7 @@
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
joint_motion_search(cpi, x, bsize, frame_mv,
mi_row, mi_col,
- single_newmv, &rate_mv);
+ single_newmv, &rate_mv, 0);
} else {
rate_mv = vp10_mv_bit_cost(&frame_mv[refs[0]].as_mv,
&x->mbmi_ext->ref_mvs[refs[0]][0].as_mv,
@@ -6871,7 +6973,7 @@
#endif // CONFIG_EXT_INTRA
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
- mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
+ mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
: cm->interp_filter;
mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
#if CONFIG_OBMC
@@ -7696,7 +7798,7 @@
x->skip = 1;
if (cm->interp_filter != BILINEAR) {
- best_filter = EIGHTTAP;
+ best_filter = EIGHTTAP_REGULAR;
if (cm->interp_filter == SWITCHABLE &&
#if CONFIG_EXT_INTERP
vp10_is_interp_needed(xd) &&
@@ -8039,7 +8141,7 @@
mbmi->ref_frame[1] = second_ref_frame;
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
- mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
+ mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
: cm->interp_filter;
x->skip = 0;
set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
@@ -8123,9 +8225,9 @@
mbmi->tx_type = DCT_DCT;
if (cm->interp_filter != BILINEAR) {
- tmp_best_filter = EIGHTTAP;
+ tmp_best_filter = EIGHTTAP_REGULAR;
if (x->source_variance < sf->disable_filter_search_var_thresh) {
- tmp_best_filter = EIGHTTAP;
+ tmp_best_filter = EIGHTTAP_REGULAR;
} else if (sf->adaptive_pred_interp_filter == 1 &&
ctx->pred_interp_filter < SWITCHABLE) {
tmp_best_filter = ctx->pred_interp_filter;
@@ -8153,7 +8255,7 @@
mi_row, mi_col);
#if CONFIG_EXT_INTERP
if (!vp10_is_interp_needed(xd) && cm->interp_filter == SWITCHABLE &&
- mbmi->interp_filter != EIGHTTAP) // invalid configuration
+ mbmi->interp_filter != EIGHTTAP_REGULAR) // invalid config
continue;
#endif // CONFIG_EXT_INTERP
if (tmp_rd == INT64_MAX)
@@ -8225,8 +8327,8 @@
mi_row, mi_col);
#if CONFIG_EXT_INTERP
if (!vp10_is_interp_needed(xd) && cm->interp_filter == SWITCHABLE &&
- mbmi->interp_filter != EIGHTTAP) {
- mbmi->interp_filter = EIGHTTAP;
+ mbmi->interp_filter != EIGHTTAP_REGULAR) {
+ mbmi->interp_filter = EIGHTTAP_REGULAR;
tmp_rd = rd_pick_best_sub8x8_mode(cpi, x,
&x->mbmi_ext->ref_mvs[ref_frame][0],
second_ref, best_yrd, &rate, &rate_y,
diff --git a/vp10/encoder/rdopt.h b/vp10/encoder/rdopt.h
index 066bf69..f4d9b95 100644
--- a/vp10/encoder/rdopt.h
+++ b/vp10/encoder/rdopt.h
@@ -102,6 +102,23 @@
uint8_t *tmp_buf[MAX_MB_PLANE],
int tmp_stride[MAX_MB_PLANE]);
#endif // CONFIG_OBMC
+
+#if CONFIG_AFFINE_MOTION
+static INLINE const YV12_BUFFER_CONFIG *get_upsampled_ref(VP10_COMP *cpi,
+ const int ref) {
+ // Use up-sampled reference frames.
+ int ref_idx = 0;
+ if (ref == LAST_FRAME)
+ ref_idx = cpi->lst_fb_idx;
+ else if (ref == GOLDEN_FRAME)
+ ref_idx = cpi->gld_fb_idx;
+ else if (ref == ALTREF_FRAME)
+ ref_idx = cpi->alt_fb_idx;
+
+ return &cpi->upsampled_ref_bufs[cpi->upsampled_ref_idx[ref_idx]].buf;
+}
+#endif
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp10/encoder/speed_features.h b/vp10/encoder/speed_features.h
index a696e83..4f931d8 100644
--- a/vp10/encoder/speed_features.h
+++ b/vp10/encoder/speed_features.h
@@ -176,9 +176,9 @@
} MODE_SEARCH_SKIP_LOGIC;
typedef enum {
- FLAG_SKIP_EIGHTTAP = 1 << EIGHTTAP,
+ FLAG_SKIP_EIGHTTAP_REGULAR = 1 << EIGHTTAP_REGULAR,
FLAG_SKIP_EIGHTTAP_SMOOTH = 1 << EIGHTTAP_SMOOTH,
- FLAG_SKIP_EIGHTTAP_SHARP = 1 << EIGHTTAP_SHARP,
+ FLAG_SKIP_MULTITAP_SHARP = 1 << MULTITAP_SHARP,
} INTERP_FILTER_MASK;
typedef enum {
diff --git a/vp10/encoder/temporal_filter.c b/vp10/encoder/temporal_filter.c
index b4db251..3e1246a 100644
--- a/vp10/encoder/temporal_filter.c
+++ b/vp10/encoder/temporal_filter.c
@@ -48,15 +48,12 @@
enum mv_precision mv_precision_uv;
int uv_stride;
-#if FILTER_12TAP
- const INTERP_FILTER interp_filter = SHARP_FILTER_12TAP;
- (void)xd;
-#elif SWITCHABLE_FILTERS == 5
- const INTERP_FILTER interp_filter = EIGHTTAP_SHARP2;
+#if USE_TEMPORALFILTER_12TAP
+ const INTERP_FILTER interp_filter = TEMPORALFILTER_12TAP;
(void)xd;
#else
const INTERP_FILTER interp_filter = xd->mi[0]->mbmi.interp_filter;
-#endif
+#endif // USE_TEMPORALFILTER_12TAP
if (uv_block_width == 8) {
uv_stride = (stride + 1) >> 1;
@@ -98,28 +95,28 @@
}
#endif // CONFIG_VP9_HIGHBITDEPTH
vp10_build_inter_predictor(y_mb_ptr, stride,
- &pred[0], 16,
- &mv,
- scale,
- 16, 16,
- which_mv,
- interp_filter, MV_PRECISION_Q3, x, y);
+ &pred[0], 16,
+ &mv,
+ scale,
+ 16, 16,
+ which_mv,
+ interp_filter, MV_PRECISION_Q3, x, y);
vp10_build_inter_predictor(u_mb_ptr, uv_stride,
- &pred[256], uv_block_width,
- &mv,
- scale,
- uv_block_width, uv_block_height,
- which_mv,
- interp_filter, mv_precision_uv, x, y);
+ &pred[256], uv_block_width,
+ &mv,
+ scale,
+ uv_block_width, uv_block_height,
+ which_mv,
+ interp_filter, mv_precision_uv, x, y);
vp10_build_inter_predictor(v_mb_ptr, uv_stride,
- &pred[512], uv_block_width,
- &mv,
- scale,
- uv_block_width, uv_block_height,
- which_mv,
- interp_filter, mv_precision_uv, x, y);
+ &pred[512], uv_block_width,
+ &mv,
+ scale,
+ uv_block_width, uv_block_height,
+ which_mv,
+ interp_filter, mv_precision_uv, x, y);
}
void vp10_temporal_filter_init(void) {
@@ -131,14 +128,14 @@
}
void vp10_temporal_filter_apply_c(uint8_t *frame1,
- unsigned int stride,
- uint8_t *frame2,
- unsigned int block_width,
- unsigned int block_height,
- int strength,
- int filter_weight,
- unsigned int *accumulator,
- uint16_t *count) {
+ unsigned int stride,
+ uint8_t *frame2,
+ unsigned int block_width,
+ unsigned int block_height,
+ int strength,
+ int filter_weight,
+ unsigned int *accumulator,
+ uint16_t *count) {
unsigned int i, j, k;
int modifier;
int byte = 0;
@@ -199,14 +196,14 @@
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_temporal_filter_apply_c(uint8_t *frame1_8,
- unsigned int stride,
- uint8_t *frame2_8,
- unsigned int block_width,
- unsigned int block_height,
- int strength,
- int filter_weight,
- unsigned int *accumulator,
- uint16_t *count) {
+ unsigned int stride,
+ uint8_t *frame2_8,
+ unsigned int block_width,
+ unsigned int block_height,
+ int strength,
+ int filter_weight,
+ unsigned int *accumulator,
+ uint16_t *count) {
uint16_t *frame1 = CONVERT_TO_SHORTPTR(frame1_8);
uint16_t *frame2 = CONVERT_TO_SHORTPTR(frame2_8);
unsigned int i, j, k;
@@ -323,7 +320,11 @@
0, mv_sf->subpel_iters_per_step,
cond_cost_list(cpi, cost_list),
NULL, NULL,
+#if CONFIG_AFFINE_MOTION
+ &distortion, &sse, NULL, 0, 0, 0);
+#else
&distortion, &sse, NULL, 0, 0);
+#endif
// Restore input state
x->plane[0].src = src;
diff --git a/vpx_dsp/variance.c b/vpx_dsp/variance.c
index e8bddb0..3b6c419 100644
--- a/vpx_dsp/variance.c
+++ b/vpx_dsp/variance.c
@@ -272,6 +272,41 @@
}
}
+#if CONFIG_AFFINE_MOTION
+// Get pred block from up-sampled reference.
+void vpx_upsampled_pred_c(uint8_t *comp_pred,
+ int width, int height,
+ const uint8_t *ref, int ref_stride) {
+ int i, j, k;
+ int stride = ref_stride << 3;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0, k = 0; j < width; j++, k += 8) {
+ comp_pred[j] = ref[k];
+ }
+ comp_pred += width;
+ ref += stride;
+ }
+}
+
+void vpx_comp_avg_upsampled_pred_c(uint8_t *comp_pred, const uint8_t *pred,
+ int width, int height,
+ const uint8_t *ref, int ref_stride) {
+ int i, j;
+ int stride = ref_stride << 3;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ const int tmp = ref[(j << 3)] + pred[j];
+ comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
+ }
+ comp_pred += width;
+ pred += width;
+ ref += stride;
+ }
+}
+#endif
+
#if CONFIG_VP9_HIGHBITDEPTH
static void highbd_variance64(const uint8_t *a8, int a_stride,
const uint8_t *b8, int b_stride,
diff --git a/vpx_dsp/vpx_dsp_rtcd_defs.pl b/vpx_dsp/vpx_dsp_rtcd_defs.pl
index 5457d00..8d1afdf 100644
--- a/vpx_dsp/vpx_dsp_rtcd_defs.pl
+++ b/vpx_dsp/vpx_dsp_rtcd_defs.pl
@@ -1464,6 +1464,13 @@
add_proto qw/void vpx_comp_avg_pred/, "uint8_t *comp_pred, const uint8_t *pred, int width, int height, const uint8_t *ref, int ref_stride";
+if (vpx_config("CONFIG_AFFINE_MOTION") eq "yes") {
+ add_proto qw/void vpx_upsampled_pred/, "uint8_t *comp_pred, int width, int height, const uint8_t *ref, int ref_stride";
+ specialize qw/vpx_upsampled_pred sse2/;
+ add_proto qw/void vpx_comp_avg_upsampled_pred/, "uint8_t *comp_pred, const uint8_t *pred, int width, int height, const uint8_t *ref, int ref_stride";
+ specialize qw/vpx_comp_avg_upsampled_pred sse2/;
+}
+
#
# Subpixel Variance
#
diff --git a/vpx_dsp/x86/variance_sse2.c b/vpx_dsp/x86/variance_sse2.c
index e6c9365..7943c84 100644
--- a/vpx_dsp/x86/variance_sse2.c
+++ b/vpx_dsp/x86/variance_sse2.c
@@ -475,3 +475,232 @@
#undef FNS
#undef FN
#endif // CONFIG_USE_X86INC
+
+#if CONFIG_AFFINE_MOTION
+void vpx_upsampled_pred_sse2(uint8_t *comp_pred,
+ int width, int height,
+ const uint8_t *ref, int ref_stride) {
+ int i, j;
+ int stride = ref_stride << 3;
+
+ if (width >= 16) {
+ // read 16 points at one time
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j+= 16) {
+ __m128i s0 = _mm_loadu_si128((const __m128i *)ref);
+ __m128i s1 = _mm_loadu_si128((const __m128i *)(ref + 16));
+ __m128i s2 = _mm_loadu_si128((const __m128i *)(ref + 32));
+ __m128i s3 = _mm_loadu_si128((const __m128i *)(ref + 48));
+ __m128i s4 = _mm_loadu_si128((const __m128i *)(ref + 64));
+ __m128i s5 = _mm_loadu_si128((const __m128i *)(ref + 80));
+ __m128i s6 = _mm_loadu_si128((const __m128i *)(ref + 96));
+ __m128i s7 = _mm_loadu_si128((const __m128i *)(ref + 112));
+ __m128i t0, t1, t2, t3;
+
+ t0 = _mm_unpacklo_epi8(s0, s1);
+ s1 = _mm_unpackhi_epi8(s0, s1);
+ t1 = _mm_unpacklo_epi8(s2, s3);
+ s3 = _mm_unpackhi_epi8(s2, s3);
+ t2 = _mm_unpacklo_epi8(s4, s5);
+ s5 = _mm_unpackhi_epi8(s4, s5);
+ t3 = _mm_unpacklo_epi8(s6, s7);
+ s7 = _mm_unpackhi_epi8(s6, s7);
+
+ s0 = _mm_unpacklo_epi8(t0, s1);
+ s2 = _mm_unpacklo_epi8(t1, s3);
+ s4 = _mm_unpacklo_epi8(t2, s5);
+ s6 = _mm_unpacklo_epi8(t3, s7);
+
+ *(int *)comp_pred = _mm_cvtsi128_si32(s0);
+ *(int *)(comp_pred + 4) = _mm_cvtsi128_si32(s2);
+ *(int *)(comp_pred + 8) = _mm_cvtsi128_si32(s4);
+ *(int *)(comp_pred + 12) = _mm_cvtsi128_si32(s6);
+
+ comp_pred += 16;
+ ref += 16 * 8;
+ }
+ ref += stride - (width << 3);
+ }
+ } else if (width >= 8) {
+ // read 8 points at one time
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j+= 8) {
+ __m128i s0 = _mm_loadu_si128((const __m128i *)ref);
+ __m128i s1 = _mm_loadu_si128((const __m128i *)(ref + 16));
+ __m128i s2 = _mm_loadu_si128((const __m128i *)(ref + 32));
+ __m128i s3 = _mm_loadu_si128((const __m128i *)(ref + 48));
+ __m128i t0, t1;
+
+ t0 = _mm_unpacklo_epi8(s0, s1);
+ s1 = _mm_unpackhi_epi8(s0, s1);
+ t1 = _mm_unpacklo_epi8(s2, s3);
+ s3 = _mm_unpackhi_epi8(s2, s3);
+
+ s0 = _mm_unpacklo_epi8(t0, s1);
+ s2 = _mm_unpacklo_epi8(t1, s3);
+
+ *(int *)comp_pred = _mm_cvtsi128_si32(s0);
+ *(int *)(comp_pred + 4) = _mm_cvtsi128_si32(s2);
+ comp_pred += 8;
+ ref += 8 * 8;
+ }
+ ref += stride - (width << 3);
+ }
+ } else {
+ // read 4 points at one time
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j+= 4) {
+ __m128i s0 = _mm_loadu_si128((const __m128i *)ref);
+ __m128i s1 = _mm_loadu_si128((const __m128i *)(ref + 16));
+ __m128i t0;
+
+ t0 = _mm_unpacklo_epi8(s0, s1);
+ s1 = _mm_unpackhi_epi8(s0, s1);
+ s0 = _mm_unpacklo_epi8(t0, s1);
+
+ *(int *)comp_pred = _mm_cvtsi128_si32(s0);
+
+ comp_pred += 4;
+ ref += 4 * 8;
+ }
+ ref += stride - (width << 3);
+ }
+ }
+}
+
+void vpx_comp_avg_upsampled_pred_sse2(uint8_t *comp_pred, const uint8_t *pred,
+ int width, int height,
+ const uint8_t *ref, int ref_stride) {
+ const __m128i zero = _mm_set1_epi16(0);
+ const __m128i one = _mm_set1_epi16(1);
+ int i, j;
+ int stride = ref_stride << 3;
+
+ if (width >= 16) {
+ // read 16 points at one time
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j+= 16) {
+ __m128i s0 = _mm_loadu_si128((const __m128i *)ref);
+ __m128i s1 = _mm_loadu_si128((const __m128i *)(ref + 16));
+ __m128i s2 = _mm_loadu_si128((const __m128i *)(ref + 32));
+ __m128i s3 = _mm_loadu_si128((const __m128i *)(ref + 48));
+ __m128i s4 = _mm_loadu_si128((const __m128i *)(ref + 64));
+ __m128i s5 = _mm_loadu_si128((const __m128i *)(ref + 80));
+ __m128i s6 = _mm_loadu_si128((const __m128i *)(ref + 96));
+ __m128i s7 = _mm_loadu_si128((const __m128i *)(ref + 112));
+ __m128i p0 = _mm_loadu_si128((const __m128i *)pred);
+ __m128i p1;
+ __m128i t0, t1, t2, t3;
+
+ t0 = _mm_unpacklo_epi8(s0, s1);
+ s1 = _mm_unpackhi_epi8(s0, s1);
+ t1 = _mm_unpacklo_epi8(s2, s3);
+ s3 = _mm_unpackhi_epi8(s2, s3);
+ t2 = _mm_unpacklo_epi8(s4, s5);
+ s5 = _mm_unpackhi_epi8(s4, s5);
+ t3 = _mm_unpacklo_epi8(s6, s7);
+ s7 = _mm_unpackhi_epi8(s6, s7);
+
+ s0 = _mm_unpacklo_epi8(t0, s1);
+ s2 = _mm_unpacklo_epi8(t1, s3);
+ s4 = _mm_unpacklo_epi8(t2, s5);
+ s6 = _mm_unpacklo_epi8(t3, s7);
+
+ s0 = _mm_unpacklo_epi32(s0, s2);
+ s4 = _mm_unpacklo_epi32(s4, s6);
+ s0 = _mm_unpacklo_epi8(s0, zero);
+ s4 = _mm_unpacklo_epi8(s4, zero);
+
+ p1 = _mm_unpackhi_epi8(p0, zero);
+ p0 = _mm_unpacklo_epi8(p0, zero);
+ p0 = _mm_adds_epu16(s0, p0);
+ p1 = _mm_adds_epu16(s4, p1);
+ p0 = _mm_adds_epu16(p0, one);
+ p1 = _mm_adds_epu16(p1, one);
+
+ p0 = _mm_srli_epi16(p0, 1);
+ p1 = _mm_srli_epi16(p1, 1);
+ p0 = _mm_packus_epi16(p0, p1);
+
+ *(int *)comp_pred = _mm_cvtsi128_si32(p0);
+ p0 = _mm_srli_si128(p0, 4);
+ *(int *)(comp_pred + 4) = _mm_cvtsi128_si32(p0);
+ p0 = _mm_srli_si128(p0, 4);
+ *(int *)(comp_pred + 8) = _mm_cvtsi128_si32(p0);
+ p0 = _mm_srli_si128(p0, 4);
+ *(int *)(comp_pred + 12) = _mm_cvtsi128_si32(p0);
+
+ comp_pred += 16;
+ pred += 16;
+ ref += 16 * 8;
+ }
+ ref += stride - (width << 3);
+ }
+ } else if (width >= 8) {
+ // read 8 points at one time
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j+= 8) {
+ __m128i s0 = _mm_loadu_si128((const __m128i *)ref);
+ __m128i s1 = _mm_loadu_si128((const __m128i *)(ref + 16));
+ __m128i s2 = _mm_loadu_si128((const __m128i *)(ref + 32));
+ __m128i s3 = _mm_loadu_si128((const __m128i *)(ref + 48));
+ __m128i p0 = _mm_loadl_epi64((const __m128i *)pred);
+ __m128i t0, t1;
+
+ t0 = _mm_unpacklo_epi8(s0, s1);
+ s1 = _mm_unpackhi_epi8(s0, s1);
+ t1 = _mm_unpacklo_epi8(s2, s3);
+ s3 = _mm_unpackhi_epi8(s2, s3);
+
+ s0 = _mm_unpacklo_epi8(t0, s1);
+ s2 = _mm_unpacklo_epi8(t1, s3);
+ s0 = _mm_unpacklo_epi32(s0, s2);
+ s0 = _mm_unpacklo_epi8(s0, zero);
+
+ p0 = _mm_unpacklo_epi8(p0, zero);
+ p0 = _mm_adds_epu16(s0, p0);
+ p0 = _mm_adds_epu16(p0, one);
+ p0 = _mm_srli_epi16(p0, 1);
+ p0 = _mm_packus_epi16(p0, zero);
+
+ *(int *)comp_pred = _mm_cvtsi128_si32(p0);
+ p0 = _mm_srli_si128(p0, 4);
+ *(int *)(comp_pred + 4) = _mm_cvtsi128_si32(p0);
+
+ comp_pred += 8;
+ pred += 8;
+ ref += 8 * 8;
+ }
+ ref += stride - (width << 3);
+ }
+ } else {
+ // read 4 points at one time
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j+= 4) {
+ __m128i s0 = _mm_loadu_si128((const __m128i *)ref);
+ __m128i s1 = _mm_loadu_si128((const __m128i *)(ref + 16));
+ __m128i p0 = _mm_cvtsi32_si128(*(const uint32_t *)pred);
+ __m128i t0;
+
+ t0 = _mm_unpacklo_epi8(s0, s1);
+ s1 = _mm_unpackhi_epi8(s0, s1);
+ s0 = _mm_unpacklo_epi8(t0, s1);
+ s0 = _mm_unpacklo_epi8(s0, zero);
+
+ p0 = _mm_unpacklo_epi8(p0, zero);
+ p0 = _mm_adds_epu16(s0, p0);
+ p0 = _mm_adds_epu16(p0, one);
+ p0 = _mm_srli_epi16(p0, 1);
+ p0 = _mm_packus_epi16(p0, zero);
+
+ *(int *)comp_pred = _mm_cvtsi128_si32(p0);
+
+ comp_pred += 4;
+ pred += 4;
+ ref += 4 * 8;
+ }
+ ref += stride - (width << 3);
+ }
+ }
+}
+#endif
diff --git a/vpx_scale/generic/yv12extend.c b/vpx_scale/generic/yv12extend.c
index 670144b..5212075 100644
--- a/vpx_scale/generic/yv12extend.c
+++ b/vpx_scale/generic/yv12extend.c
@@ -210,6 +210,30 @@
extend_frame(ybf, inner_bw);
}
+void vpx_extend_frame_borders_y_c(YV12_BUFFER_CONFIG *ybf) {
+ int ext_size = ybf->border;
+ assert(ybf->y_height - ybf->y_crop_height < 16);
+ assert(ybf->y_width - ybf->y_crop_width < 16);
+ assert(ybf->y_height - ybf->y_crop_height >= 0);
+ assert(ybf->y_width - ybf->y_crop_width >= 0);
+
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
+ extend_plane_high(ybf->y_buffer, ybf->y_stride,
+ ybf->y_crop_width, ybf->y_crop_height,
+ ext_size, ext_size,
+ ext_size + ybf->y_height - ybf->y_crop_height,
+ ext_size + ybf->y_width - ybf->y_crop_width);
+ return;
+ }
+#endif
+ extend_plane(ybf->y_buffer, ybf->y_stride,
+ ybf->y_crop_width, ybf->y_crop_height,
+ ext_size, ext_size,
+ ext_size + ybf->y_height - ybf->y_crop_height,
+ ext_size + ybf->y_width - ybf->y_crop_width);
+}
+
#if CONFIG_VP9_HIGHBITDEPTH
void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
diff --git a/vpx_scale/vpx_scale_rtcd.pl b/vpx_scale/vpx_scale_rtcd.pl
index 56b952b..68a1a3e 100644
--- a/vpx_scale/vpx_scale_rtcd.pl
+++ b/vpx_scale/vpx_scale_rtcd.pl
@@ -28,5 +28,8 @@
add_proto qw/void vpx_extend_frame_inner_borders/, "struct yv12_buffer_config *ybf";
specialize qw/vpx_extend_frame_inner_borders dspr2/;
+
+ add_proto qw/void vpx_extend_frame_borders_y/, "struct yv12_buffer_config *ybf";
+ specialize qw/vpx_extend_frame_borders_y/;
}
1;