Merge "Fix source frame border extension"
diff --git a/libs.mk b/libs.mk
index 4aee94e..e48d55c 100644
--- a/libs.mk
+++ b/libs.mk
@@ -179,7 +179,7 @@
# based build systems.
libvpx_srcs.txt:
@echo " [CREATE] $@"
- @echo $(CODEC_SRCS) | xargs -n1 echo | sort -u > $@
+ @echo $(CODEC_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
CLEAN-OBJS += libvpx_srcs.txt
@@ -356,7 +356,7 @@
libvpx_test_srcs.txt:
@echo " [CREATE] $@"
- @echo $(LIBVPX_TEST_SRCS) | xargs -n1 echo | sort -u > $@
+ @echo $(LIBVPX_TEST_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
CLEAN-OBJS += libvpx_test_srcs.txt
$(LIBVPX_TEST_DATA): $(SRC_PATH_BARE)/test/test-data.sha1
diff --git a/test/test-data.mk b/test/test-data.mk
index 5889ed9..1055e12 100644
--- a/test/test-data.mk
+++ b/test/test-data.mk
@@ -17,7 +17,7 @@
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_444.y4m
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_440.yuv
-LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m
@@ -727,10 +727,8 @@
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-3.webm
ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
-# NewEncode Test
-ifneq ($(CONFIG_VP9_ENCODER),yes)
-LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += niklas_1280_720_30.yuv
-endif
+# Encode / Decode test
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
# BBB VP9 streams
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_426x240_tile_1x1_180kbps.webm
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_640x360_tile_1x2_337kbps.webm
@@ -760,8 +758,12 @@
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += kirland_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcomoving_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcostationary_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomanarrows_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomasmallcameramovement_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += thaloundeskmtg_640_480_30.yuv
endif # CONFIG_ENCODE_PERF_TESTS
+
+# sort and remove duplicates
+LIBVPX_TEST_DATA-yes := $(sort $(LIBVPX_TEST_DATA-yes))
diff --git a/test/test-data.sha1 b/test/test-data.sha1
index cc5fe23..1212941 100644
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -741,3 +741,4 @@
d06285d109ecbaef63b0cbcc44d70a129186f51c invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res
e60d859b0ef2b331b21740cf6cb83fabe469b079 invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf
0ae808dca4d3c1152a9576e14830b6faa39f1b4a invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res
+9cfc855459e7549fd015c79e8eca512b2f2cb7e3 niklas_1280_720_30.y4m
diff --git a/test/tools_common.sh b/test/tools_common.sh
index 8e8d785..27785c3 100755
--- a/test/tools_common.sh
+++ b/test/tools_common.sh
@@ -106,22 +106,24 @@
fi
}
+# $1 is the name of an environment variable containing a directory name to
+# test.
+test_env_var_dir() {
+ local dir=$(eval echo "\${$1}")
+ if [ ! -d "${dir}" ]; then
+ elog "'${dir}': No such directory"
+ elog "The $1 environment variable must be set to a valid directory."
+ return 1
+ fi
+}
+
# This script requires that the LIBVPX_BIN_PATH, LIBVPX_CONFIG_PATH, and
# LIBVPX_TEST_DATA_PATH variables are in the environment: Confirm that
# the variables are set and that they all evaluate to directory paths.
verify_vpx_test_environment() {
- if [ ! -d "${LIBVPX_BIN_PATH}" ]; then
- echo "The LIBVPX_BIN_PATH environment variable must be set."
- return 1
- fi
- if [ ! -d "${LIBVPX_CONFIG_PATH}" ]; then
- echo "The LIBVPX_CONFIG_PATH environment variable must be set."
- return 1
- fi
- if [ ! -d "${LIBVPX_TEST_DATA_PATH}" ]; then
- echo "The LIBVPX_TEST_DATA_PATH environment variable must be set."
- return 1
- fi
+ test_env_var_dir "LIBVPX_BIN_PATH" \
+ && test_env_var_dir "LIBVPX_CONFIG_PATH" \
+ && test_env_var_dir "LIBVPX_TEST_DATA_PATH"
}
# Greps vpx_config.h in LIBVPX_CONFIG_PATH for positional parameter one, which
@@ -381,8 +383,7 @@
VPX_TEST_TEMP_ROOT=/tmp
fi
-VPX_TEST_RAND=$(awk 'BEGIN { srand(); printf "%d\n",(rand() * 32768)}')
-VPX_TEST_OUTPUT_DIR="${VPX_TEST_TEMP_ROOT}/vpx_test_${VPX_TEST_RAND}"
+VPX_TEST_OUTPUT_DIR="${VPX_TEST_TEMP_ROOT}/vpx_test_$$"
if ! mkdir -p "${VPX_TEST_OUTPUT_DIR}" || \
[ ! -d "${VPX_TEST_OUTPUT_DIR}" ]; then
@@ -420,7 +421,6 @@
VPX_TEST_LIST_TESTS=${VPX_TEST_LIST_TESTS}
VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR}
VPX_TEST_PREFIX=${VPX_TEST_PREFIX}
- VPX_TEST_RAND=${VPX_TEST_RAND}
VPX_TEST_RUN_DISABLED_TESTS=${VPX_TEST_RUN_DISABLED_TESTS}
VPX_TEST_SHOW_PROGRAM_OUTPUT=${VPX_TEST_SHOW_PROGRAM_OUTPUT}
VPX_TEST_TEMP_ROOT=${VPX_TEST_TEMP_ROOT}
diff --git a/test/vp9_encoder_parms_get_to_decoder.cc b/test/vp9_encoder_parms_get_to_decoder.cc
index cdc308d..c477af9 100644
--- a/test/vp9_encoder_parms_get_to_decoder.cc
+++ b/test/vp9_encoder_parms_get_to_decoder.cc
@@ -56,7 +56,7 @@
};
const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
- {"niklas_1280_720_30.yuv", 1280, 720, 600, 10},
+ {"niklas_1280_720_30.y4m", 1280, 720, 600, 10},
};
struct EncodeParameters {
diff --git a/test/vp9_ethread_test.cc b/test/vp9_ethread_test.cc
index d309483..ea1e0d7 100644
--- a/test/vp9_ethread_test.cc
+++ b/test/vp9_ethread_test.cc
@@ -13,9 +13,9 @@
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
-#include "test/i420_video_source.h"
-#include "test/util.h"
#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
namespace {
class VP9EncoderThreadTest
@@ -100,8 +100,7 @@
TEST_P(VP9EncoderThreadTest, EncoderResultTest) {
std::vector<std::string> single_thr_md5, multi_thr_md5;
- ::libvpx_test::I420VideoSource video("niklas_1280_720_30.yuv", 1280, 720,
- 50, 1, 15, 20);
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 15, 20);
cfg_.rc_target_bitrate = 1000;
diff --git a/vp9/common/x86/vp9_high_loopfilter_intrin_sse2.c b/vp9/common/x86/vp9_high_loopfilter_intrin_sse2.c
index 7e63f38..4bd8ac4 100644
--- a/vp9/common/x86/vp9_high_loopfilter_intrin_sse2.c
+++ b/vp9/common/x86/vp9_high_loopfilter_intrin_sse2.c
@@ -15,24 +15,38 @@
#include "vpx_ports/emmintrin_compat.h"
static INLINE __m128i signed_char_clamp_bd_sse2(__m128i value, int bd) {
- __m128i ubounded;
- __m128i lbounded;
- __m128i retval;
+ __m128i ubounded;
+ __m128i lbounded;
+ __m128i retval;
- const __m128i zero = _mm_set1_epi16(0);
- const __m128i one = _mm_set1_epi16(1);
- const __m128i t80 = _mm_slli_epi16(_mm_set1_epi16(0x80), bd - 8);
- const __m128i max = _mm_subs_epi16(
- _mm_subs_epi16(_mm_slli_epi16(one, bd), one), t80);
- const __m128i min = _mm_subs_epi16(zero, t80);
- ubounded = _mm_cmpgt_epi16(value, max);
- lbounded = _mm_cmplt_epi16(value, min);
- retval = _mm_andnot_si128(_mm_or_si128(ubounded, lbounded), value);
- ubounded = _mm_and_si128(ubounded, max);
- lbounded = _mm_and_si128(lbounded, min);
- retval = _mm_or_si128(retval, ubounded);
- retval = _mm_or_si128(retval, lbounded);
- return retval;
+ const __m128i zero = _mm_set1_epi16(0);
+ const __m128i one = _mm_set1_epi16(1);
+ __m128i t80, max, min;
+
+ if (bd == 8) {
+ t80 = _mm_set1_epi16(0x80);
+ max = _mm_subs_epi16(
+ _mm_subs_epi16(_mm_slli_epi16(one, 8), one), t80);
+ } else if (bd == 10) {
+ t80 = _mm_set1_epi16(0x200);
+ max = _mm_subs_epi16(
+ _mm_subs_epi16(_mm_slli_epi16(one, 10), one), t80);
+ } else { // bd == 12
+ t80 = _mm_set1_epi16(0x800);
+ max = _mm_subs_epi16(
+ _mm_subs_epi16(_mm_slli_epi16(one, 12), one), t80);
+ }
+
+ min = _mm_subs_epi16(zero, t80);
+
+ ubounded = _mm_cmpgt_epi16(value, max);
+ lbounded = _mm_cmplt_epi16(value, min);
+ retval = _mm_andnot_si128(_mm_or_si128(ubounded, lbounded), value);
+ ubounded = _mm_and_si128(ubounded, max);
+ lbounded = _mm_and_si128(lbounded, min);
+ retval = _mm_or_si128(retval, ubounded);
+ retval = _mm_or_si128(retval, lbounded);
+ return retval;
}
// TODO(debargha, peter): Break up large functions into smaller ones
@@ -45,14 +59,7 @@
int bd) {
const __m128i zero = _mm_set1_epi16(0);
const __m128i one = _mm_set1_epi16(1);
- const __m128i blimit = _mm_slli_epi16(
- _mm_unpacklo_epi8(
- _mm_load_si128((const __m128i *)_blimit), zero), bd - 8);
- const __m128i limit = _mm_slli_epi16(
- _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), bd - 8);
- const __m128i thresh = _mm_slli_epi16(
- _mm_unpacklo_epi8(
- _mm_load_si128((const __m128i *)_thresh), zero), bd - 8);
+ __m128i blimit, limit, thresh;
__m128i q7, p7, q6, p6, q5, p5, q4, p4, q3, p3, q2, p2, q1, p1, q0, p0;
__m128i mask, hev, flat, flat2, abs_p1p0, abs_q1q0;
__m128i ps1, qs1, ps0, qs0;
@@ -68,6 +75,26 @@
__m128i t4, t3, t80, t1;
__m128i eight, four;
+ if (bd == 8) {
+ blimit = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero);
+ limit = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero);
+ thresh = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero);
+ } else if (bd == 10) {
+ blimit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero), 2);
+ limit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), 2);
+ thresh = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero), 2);
+ } else { // bd == 12
+ blimit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero), 4);
+ limit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), 4);
+ thresh = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero), 4);
+ }
+
q4 = _mm_load_si128((__m128i *)(s + 4 * p));
p4 = _mm_load_si128((__m128i *)(s - 5 * p));
q3 = _mm_load_si128((__m128i *)(s + 3 * p));
@@ -121,7 +148,13 @@
// highbd_filter4
t4 = _mm_set1_epi16(4);
t3 = _mm_set1_epi16(3);
- t80 = _mm_slli_epi16(_mm_set1_epi16(0x80), bd - 8);
+ if (bd == 8)
+ t80 = _mm_set1_epi16(0x80);
+ else if (bd == 10)
+ t80 = _mm_set1_epi16(0x200);
+ else // bd == 12
+ t80 = _mm_set1_epi16(0x800);
+
t1 = _mm_set1_epi16(0x1);
ps1 = _mm_subs_epi16(p1, t80);
@@ -136,7 +169,6 @@
filt = _mm_adds_epi16(filt, work_a);
filt = signed_char_clamp_bd_sse2(_mm_adds_epi16(filt, work_a), bd);
filt = _mm_and_si128(filt, mask);
-
filter1 = signed_char_clamp_bd_sse2(_mm_adds_epi16(filt, t4), bd);
filter2 = signed_char_clamp_bd_sse2(_mm_adds_epi16(filt, t3), bd);
@@ -153,13 +185,13 @@
filt = _mm_adds_epi16(filter1, t1);
filt = _mm_srai_epi16(filt, 1);
filt = _mm_andnot_si128(hev, filt);
-
qs1 = _mm_adds_epi16(
signed_char_clamp_bd_sse2(_mm_subs_epi16(qs1, filt), bd),
t80);
ps1 = _mm_adds_epi16(
signed_char_clamp_bd_sse2(_mm_adds_epi16(ps1, filt), bd),
t80);
+
// end highbd_filter4
// loopfilter done
@@ -175,7 +207,14 @@
flat = _mm_max_epi16(work, flat);
work = _mm_max_epi16(abs_p1p0, abs_q1q0);
flat = _mm_max_epi16(work, flat);
- flat = _mm_subs_epu16(flat, _mm_slli_epi16(one, bd - 8));
+
+ if (bd == 8)
+ flat = _mm_subs_epu16(flat, one);
+ else if (bd == 10)
+ flat = _mm_subs_epu16(flat, _mm_slli_epi16(one, 2));
+ else // bd == 12
+ flat = _mm_subs_epu16(flat, _mm_slli_epi16(one, 4));
+
flat = _mm_cmpeq_epi16(flat, zero);
// end flat_mask4
@@ -215,7 +254,13 @@
_mm_subs_epu16(q0, q7)));
flat2 = _mm_max_epi16(work, flat2);
- flat2 = _mm_subs_epu16(flat2, _mm_slli_epi16(one, bd - 8));
+ if (bd == 8)
+ flat2 = _mm_subs_epu16(flat2, one);
+ else if (bd == 10)
+ flat2 = _mm_subs_epu16(flat2, _mm_slli_epi16(one, 2));
+ else // bd == 12
+ flat2 = _mm_subs_epu16(flat2, _mm_slli_epi16(one, 4));
+
flat2 = _mm_cmpeq_epi16(flat2, zero);
flat2 = _mm_and_si128(flat2, flat); // flat2 & flat & mask
// end highbd_flat_mask5
@@ -486,15 +531,7 @@
DECLARE_ALIGNED_ARRAY(16, uint16_t, flat_oq1, 16);
DECLARE_ALIGNED_ARRAY(16, uint16_t, flat_oq0, 16);
const __m128i zero = _mm_set1_epi16(0);
- const __m128i blimit = _mm_slli_epi16(
- _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero),
- bd - 8);
- const __m128i limit = _mm_slli_epi16(
- _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero),
- bd - 8);
- const __m128i thresh = _mm_slli_epi16(
- _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero),
- bd - 8);
+ __m128i blimit, limit, thresh;
__m128i mask, hev, flat;
__m128i p3 = _mm_load_si128((__m128i *)(s - 4 * p));
__m128i q3 = _mm_load_si128((__m128i *)(s + 3 * p));
@@ -512,18 +549,43 @@
const __m128i t4 = _mm_set1_epi16(4);
const __m128i t3 = _mm_set1_epi16(3);
- const __m128i t80 = _mm_slli_epi16(_mm_set1_epi16(0x80), bd - 8);
+ __m128i t80;
const __m128i t1 = _mm_set1_epi16(0x1);
- const __m128i ps1 = _mm_subs_epi16(p1, t80);
- const __m128i ps0 = _mm_subs_epi16(p0, t80);
- const __m128i qs0 = _mm_subs_epi16(q0, t80);
- const __m128i qs1 = _mm_subs_epi16(q1, t80);
+ __m128i ps1, ps0, qs0, qs1;
__m128i filt;
__m128i work_a;
__m128i filter1, filter2;
(void)count;
+ if (bd == 8) {
+ blimit = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero);
+ limit = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero);
+ thresh = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero);
+ t80 = _mm_set1_epi16(0x80);
+ } else if (bd == 10) {
+ blimit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero), 2);
+ limit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), 2);
+ thresh = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero), 2);
+ t80 = _mm_set1_epi16(0x200);
+ } else { // bd == 12
+ blimit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero), 4);
+ limit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), 4);
+ thresh = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero), 4);
+ t80 = _mm_set1_epi16(0x800);
+ }
+
+ ps1 = _mm_subs_epi16(p1, t80);
+ ps0 = _mm_subs_epi16(p0, t80);
+ qs0 = _mm_subs_epi16(q0, t80);
+ qs1 = _mm_subs_epi16(q1, t80);
+
// filter_mask and hev_mask
abs_p1p0 = _mm_or_si128(_mm_subs_epu16(p1, p0),
_mm_subs_epu16(p0, p1));
@@ -575,7 +637,14 @@
flat = _mm_max_epi16(work, flat);
flat = _mm_max_epi16(abs_p1p0, flat);
flat = _mm_max_epi16(abs_q1q0, flat);
- flat = _mm_subs_epu16(flat, _mm_slli_epi16(one, bd - 8));
+
+ if (bd == 8)
+ flat = _mm_subs_epu16(flat, one);
+ else if (bd == 10)
+ flat = _mm_subs_epu16(flat, _mm_slli_epi16(one, 2));
+ else // bd == 12
+ flat = _mm_subs_epu16(flat, _mm_slli_epi16(one, 4));
+
flat = _mm_cmpeq_epi16(flat, zero);
flat = _mm_and_si128(flat, mask); // flat & mask
@@ -706,15 +775,7 @@
const uint8_t *_thresh,
int count, int bd) {
const __m128i zero = _mm_set1_epi16(0);
- const __m128i blimit = _mm_slli_epi16(
- _mm_unpacklo_epi8(
- _mm_load_si128((const __m128i *)_blimit), zero), bd - 8);
- const __m128i limit = _mm_slli_epi16(
- _mm_unpacklo_epi8(
- _mm_load_si128((const __m128i *)_limit), zero), bd - 8);
- const __m128i thresh = _mm_slli_epi16(
- _mm_unpacklo_epi8(
- _mm_load_si128((const __m128i *)_thresh), zero), bd - 8);
+ __m128i blimit, limit, thresh;
__m128i mask, hev, flat;
__m128i p3 = _mm_loadu_si128((__m128i *)(s - 4 * p));
__m128i p2 = _mm_loadu_si128((__m128i *)(s - 3 * p));
@@ -737,30 +798,63 @@
__m128i work;
const __m128i t4 = _mm_set1_epi16(4);
const __m128i t3 = _mm_set1_epi16(3);
- const __m128i t80 = _mm_slli_epi16(_mm_set1_epi16(0x80), bd - 8);
- const __m128i tff80 = _mm_slli_epi16(_mm_set1_epi16(0xff80), bd - 8);
- const __m128i tffe0 = _mm_slli_epi16(_mm_set1_epi16(0xffe0), bd - 8);
- const __m128i t1f = _mm_srli_epi16(_mm_set1_epi16(0x1fff), 16 - bd);
+ __m128i t80;
+ __m128i tff80;
+ __m128i tffe0;
+ __m128i t1f;
// equivalent to shifting 0x1f left by bitdepth - 8
// and setting new bits to 1
const __m128i t1 = _mm_set1_epi16(0x1);
- const __m128i t7f = _mm_srli_epi16(_mm_set1_epi16(0x7fff), 16 - bd);
+ __m128i t7f;
// equivalent to shifting 0x7f left by bitdepth - 8
// and setting new bits to 1
- const __m128i ps1 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s - 2 * p)),
- t80);
- const __m128i ps0 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s - 1 * p)),
- t80);
- const __m128i qs0 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s + 0 * p)),
- t80);
- const __m128i qs1 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s + 1 * p)),
- t80);
+ __m128i ps1, ps0, qs0, qs1;
__m128i filt;
__m128i work_a;
__m128i filter1, filter2;
(void)count;
+ if (bd == 8) {
+ blimit = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero);
+ limit = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero);
+ thresh = _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero);
+ t80 = _mm_set1_epi16(0x80);
+ tff80 = _mm_set1_epi16(0xff80);
+ tffe0 = _mm_set1_epi16(0xffe0);
+ t1f = _mm_srli_epi16(_mm_set1_epi16(0x1fff), 8);
+ t7f = _mm_srli_epi16(_mm_set1_epi16(0x7fff), 8);
+ } else if (bd == 10) {
+ blimit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero), 2);
+ limit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), 2);
+ thresh = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero), 2);
+ t80 = _mm_slli_epi16(_mm_set1_epi16(0x80), 2);
+ tff80 = _mm_slli_epi16(_mm_set1_epi16(0xff80), 2);
+ tffe0 = _mm_slli_epi16(_mm_set1_epi16(0xffe0), 2);
+ t1f = _mm_srli_epi16(_mm_set1_epi16(0x1fff), 6);
+ t7f = _mm_srli_epi16(_mm_set1_epi16(0x7fff), 6);
+ } else { // bd == 12
+ blimit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_blimit), zero), 4);
+ limit = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_limit), zero), 4);
+ thresh = _mm_slli_epi16(
+ _mm_unpacklo_epi8(_mm_load_si128((const __m128i *)_thresh), zero), 4);
+ t80 = _mm_slli_epi16(_mm_set1_epi16(0x80), 4);
+ tff80 = _mm_slli_epi16(_mm_set1_epi16(0xff80), 4);
+ tffe0 = _mm_slli_epi16(_mm_set1_epi16(0xffe0), 4);
+ t1f = _mm_srli_epi16(_mm_set1_epi16(0x1fff), 4);
+ t7f = _mm_srli_epi16(_mm_set1_epi16(0x7fff), 4);
+ }
+
+ ps1 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s - 2 * p)), t80);
+ ps0 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s - 1 * p)), t80);
+ qs0 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s + 0 * p)), t80);
+ qs1 = _mm_subs_epi16(_mm_loadu_si128((__m128i *)(s + 1 * p)), t80);
+
// filter_mask and hev_mask
flat = _mm_max_epi16(abs_p1p0, abs_q1q0);
hev = _mm_subs_epu16(flat, thresh);
@@ -796,6 +890,7 @@
filt = _mm_adds_epi16(filt, work_a);
filt = _mm_adds_epi16(filt, work_a);
filt = signed_char_clamp_bd_sse2(_mm_adds_epi16(filt, work_a), bd);
+
// (vp9_filter + 3 * (qs0 - ps0)) & mask
filt = _mm_and_si128(filt, mask);
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c
index ff08f04..1540680 100644
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -368,9 +368,11 @@
cr->time_for_refresh = 0;
// Set rate threshold to some multiple (set to 2 for now) of the target
// rate (target is given by sb64_target_rate and scaled by 256).
- cr->thresh_rate_sb = (rc->sb64_target_rate << 8) << 1;
+ cr->thresh_rate_sb = ((int64_t)(rc->sb64_target_rate) << 8) << 1;
// Distortion threshold, quadratic in Q, scale factor to be adjusted.
- cr->thresh_dist_sb = (int)(q * q) << 2;
+ // q will not exceed 457, so (q * q) is within 32bit; see:
+ // vp9_convert_qindex_to_q(), vp9_ac_quant(), ac_qlookup*[].
+ cr->thresh_dist_sb = ((int64_t)(q * q)) << 2;
cr->motion_thresh = 32;
// Set up segmentation.
// Clear down the segment map.
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index ff12bf8..a5e9ed6 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -519,13 +519,14 @@
#endif
#if GLOBAL_MOTION
-static int vector_match(int16_t *ref, int16_t *src) {
+static int vector_match(int16_t *ref, int16_t *src, int length) {
int best_sad = INT_MAX;
int this_sad;
int d;
int center, offset = 0;
- for (d = 0; d <= 64; d += 16) {
- this_sad = vp9_vector_sad(&ref[d], src, 64);
+ int bw = length; // redundant variable, to be changed in the experiments.
+ for (d = 0; d <= bw; d += 16) {
+ this_sad = vp9_vector_sad(&ref[d], src, length);
if (this_sad < best_sad) {
best_sad = this_sad;
offset = d;
@@ -536,9 +537,9 @@
for (d = -8; d <= 8; d += 16) {
int this_pos = offset + d;
// check limit
- if (this_pos < 0 || this_pos > 64)
+ if (this_pos < 0 || this_pos > bw)
continue;
- this_sad = vp9_vector_sad(&ref[this_pos], src, 64);
+ this_sad = vp9_vector_sad(&ref[this_pos], src, length);
if (this_sad < best_sad) {
best_sad = this_sad;
center = this_pos;
@@ -549,9 +550,9 @@
for (d = -4; d <= 4; d += 8) {
int this_pos = offset + d;
// check limit
- if (this_pos < 0 || this_pos > 64)
+ if (this_pos < 0 || this_pos > bw)
continue;
- this_sad = vp9_vector_sad(&ref[this_pos], src, 64);
+ this_sad = vp9_vector_sad(&ref[this_pos], src, length);
if (this_sad < best_sad) {
best_sad = this_sad;
center = this_pos;
@@ -562,9 +563,9 @@
for (d = -2; d <= 2; d += 4) {
int this_pos = offset + d;
// check limit
- if (this_pos < 0 || this_pos > 64)
+ if (this_pos < 0 || this_pos > bw)
continue;
- this_sad = vp9_vector_sad(&ref[this_pos], src, 64);
+ this_sad = vp9_vector_sad(&ref[this_pos], src, length);
if (this_sad < best_sad) {
best_sad = this_sad;
center = this_pos;
@@ -575,16 +576,16 @@
for (d = -1; d <= 1; d += 2) {
int this_pos = offset + d;
// check limit
- if (this_pos < 0 || this_pos > 64)
+ if (this_pos < 0 || this_pos > bw)
continue;
- this_sad = vp9_vector_sad(&ref[this_pos], src, 64);
+ this_sad = vp9_vector_sad(&ref[this_pos], src, length);
if (this_sad < best_sad) {
best_sad = this_sad;
center = this_pos;
}
}
- return (center - 32);
+ return (center - (bw >> 1));
}
static const MV search_pos[9] = {
@@ -592,16 +593,18 @@
{1, -1}, {1, 0}, {1, 1},
};
-static void motion_estimation(VP9_COMP *cpi, MACROBLOCK *x) {
+static void motion_estimation(VP9_COMP *cpi, MACROBLOCK *x,
+ BLOCK_SIZE bsize) {
MACROBLOCKD *xd = &x->e_mbd;
DECLARE_ALIGNED(16, int16_t, hbuf[128]);
DECLARE_ALIGNED(16, int16_t, vbuf[128]);
DECLARE_ALIGNED(16, int16_t, src_hbuf[64]);
DECLARE_ALIGNED(16, int16_t, src_vbuf[64]);
int idx;
- const int stride = 64;
- const int search_width = 128;
- const int search_height = 128;
+ const int bw = 4 << b_width_log2_lookup[bsize];
+ const int bh = 4 << b_height_log2_lookup[bsize];
+ const int search_width = bw << 1;
+ const int search_height = bh << 1;
const int src_stride = x->plane[0].src.stride;
const int ref_stride = xd->plane[0].pre[0].stride;
uint8_t const *ref_buf, *src_buf;
@@ -610,34 +613,33 @@
MV this_mv;
// Set up prediction 1-D reference set
- ref_buf = xd->plane[0].pre[0].buf + (-32);
+ ref_buf = xd->plane[0].pre[0].buf - (bw >> 1);
for (idx = 0; idx < search_width; idx += 16) {
- vp9_int_pro_row(&hbuf[idx], ref_buf, ref_stride, 64);
+ vp9_int_pro_row(&hbuf[idx], ref_buf, ref_stride, bh);
ref_buf += 16;
}
- ref_buf = xd->plane[0].pre[0].buf + (-32) * ref_stride;
+ ref_buf = xd->plane[0].pre[0].buf - (bh >> 1) * ref_stride;
for (idx = 0; idx < search_height; ++idx) {
- vbuf[idx] = vp9_int_pro_col(ref_buf, 64);
+ vbuf[idx] = vp9_int_pro_col(ref_buf, bw);
ref_buf += ref_stride;
}
// Set up src 1-D reference set
- for (idx = 0; idx < stride; idx += 16) {
+ for (idx = 0; idx < bw; idx += 16) {
src_buf = x->plane[0].src.buf + idx;
- vp9_int_pro_row(&src_hbuf[idx], src_buf, src_stride, 64);
+ vp9_int_pro_row(&src_hbuf[idx], src_buf, src_stride, bh);
}
src_buf = x->plane[0].src.buf;
- for (idx = 0; idx < stride; ++idx) {
- src_vbuf[idx] = vp9_int_pro_col(src_buf, 64);
+ for (idx = 0; idx < bh; ++idx) {
+ src_vbuf[idx] = vp9_int_pro_col(src_buf, bw);
src_buf += src_stride;
}
// Find the best match per 1-D search
-
- tmp_mv->col = vector_match(hbuf, src_hbuf);
- tmp_mv->row = vector_match(vbuf, src_vbuf);
+ tmp_mv->col = vector_match(hbuf, src_hbuf, bw);
+ tmp_mv->row = vector_match(vbuf, src_vbuf, bh);
best_sad = INT_MAX;
this_mv = *tmp_mv;
@@ -648,8 +650,8 @@
(search_pos[idx].row + this_mv.row) * ref_stride +
(search_pos[idx].col + this_mv.col);
- this_sad = cpi->fn_ptr[BLOCK_64X64].sdf(src_buf, src_stride,
- ref_buf, ref_stride);
+ this_sad = cpi->fn_ptr[bsize].sdf(src_buf, src_stride,
+ ref_buf, ref_stride);
if (this_sad < best_sad) {
best_sad = this_sad;
tmp_mv->row = search_pos[idx].row + this_mv.row;
@@ -717,7 +719,7 @@
mbmi->interp_filter = BILINEAR;
#if GLOBAL_MOTION
- motion_estimation(cpi, x);
+ motion_estimation(cpi, x, BLOCK_64X64);
#endif
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64);
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index e2ed95c..bd7e0b6 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1963,11 +1963,13 @@
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_width, a->uv_width, a->uv_width };
- const int heights[3] = {a->y_height, a->uv_height, a->uv_height};
- const uint8_t *a_planes[3] = {a->y_buffer, a->u_buffer, a->v_buffer };
+ const int 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 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;
@@ -2000,8 +2002,10 @@
PSNR_STATS *psnr,
unsigned int bit_depth,
unsigned int in_bit_depth) {
- const int widths[3] = {a->y_width, a->uv_width, a->uv_width };
- const int heights[3] = {a->y_height, a->uv_height, a->uv_height};
+ const 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 };
@@ -3451,7 +3455,12 @@
int subsampling_x, int subsampling_y) {
VP9_COMMON *const cm = &cpi->common;
- if (!cpi->initial_width) {
+ if (!cpi->initial_width ||
+#if CONFIG_VP9_HIGHBITDEPTH
+ cm->use_highbitdepth != use_highbitdepth ||
+#endif
+ cm->subsampling_x != subsampling_x ||
+ cm->subsampling_y != subsampling_y) {
cm->subsampling_x = subsampling_x;
cm->subsampling_y = subsampling_y;
#if CONFIG_VP9_HIGHBITDEPTH
@@ -4077,7 +4086,7 @@
unsigned int height) {
VP9_COMMON *cm = &cpi->common;
#if CONFIG_VP9_HIGHBITDEPTH
- check_initial_width(cpi, 1, 1, cm->use_highbitdepth);
+ check_initial_width(cpi, cm->use_highbitdepth, 1, 1);
#else
check_initial_width(cpi, 1, 1);
#endif // CONFIG_VP9_HIGHBITDEPTH
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 4c45a79..b813e7d 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -57,6 +57,8 @@
#define SVC_FACTOR_PT_LOW 0.45
#define DARK_THRESH 64
#define DEFAULT_GRP_WEIGHT 1.0
+#define RC_FACTOR_MIN 0.75
+#define RC_FACTOR_MAX 1.75
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
@@ -1960,16 +1962,21 @@
const int vbr_group_bits_per_frame =
(int)(gf_group_bits / rc->baseline_gf_interval);
const double group_av_err = gf_group_raw_error / rc->baseline_gf_interval;
- const int tmp_q =
- get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
- twopass->kfgroup_inter_fraction);
-
- if (tmp_q < twopass->baseline_active_worst_quality) {
- twopass->active_worst_quality =
- (tmp_q + twopass->baseline_active_worst_quality + 1) / 2;
+ int tmp_q;
+ // rc factor is a weight factor that corrects for local rate control drift.
+ double rc_factor = 1.0;
+ if (rc->rate_error_estimate > 0) {
+ rc_factor = MAX(RC_FACTOR_MIN,
+ (double)(100 - rc->rate_error_estimate) / 100.0);
} else {
- twopass->active_worst_quality = tmp_q;
+ rc_factor = MIN(RC_FACTOR_MAX,
+ (double)(100 - rc->rate_error_estimate) / 100.0);
}
+ tmp_q =
+ get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
+ twopass->kfgroup_inter_fraction * rc_factor);
+ twopass->active_worst_quality =
+ MAX(tmp_q, twopass->active_worst_quality >> 1);
}
#endif
@@ -2577,7 +2584,7 @@
subtract_stats(&twopass->total_left_stats, &this_frame);
}
-#define MINQ_ADJ_LIMIT 32
+#define MINQ_ADJ_LIMIT 48
void vp9_twopass_postencode_update(VP9_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass;
RATE_CONTROL *const rc = &cpi->rc;
@@ -2610,8 +2617,7 @@
// Increment the gf group index ready for the next frame.
++twopass->gf_group.index;
- // If the rate control is drifting consider adjustment ot min or maxq.
- // Only make adjustments on gf/arf
+ // If the rate control is drifting consider adjustment to min or maxq.
if ((cpi->oxcf.rc_mode == VPX_VBR) &&
(cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD) &&
!cpi->rc.is_src_frame_alt_ref) {
@@ -2640,6 +2646,7 @@
else if (rc->rolling_target_bits > rc->rolling_actual_bits)
--twopass->extend_maxq;
}
+
twopass->extend_minq = clamp(twopass->extend_minq, 0, MINQ_ADJ_LIMIT);
twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit);
}
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index 82bce37..161b5a2 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -380,13 +380,14 @@
}
}
- if (vp9_set_size_literal(cpi, width, height) != 0)
- return VPX_CODEC_INVALID_PARAM;
-
cpi->oxcf.worst_allowed_q = vp9_quantizer_to_qindex(lc->max_q);
cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q);
vp9_change_config(cpi, &cpi->oxcf);
+
+ if (vp9_set_size_literal(cpi, width, height) != 0)
+ return VPX_CODEC_INVALID_PARAM;
+
vp9_set_high_precision_mv(cpi, 1);
cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source;
diff --git a/vp9/encoder/x86/vp9_avg_intrin_sse2.c b/vp9/encoder/x86/vp9_avg_intrin_sse2.c
index 0a10562..123255a 100644
--- a/vp9/encoder/x86/vp9_avg_intrin_sse2.c
+++ b/vp9/encoder/x86/vp9_avg_intrin_sse2.c
@@ -100,22 +100,14 @@
__m128i src_line = _mm_load_si128((const __m128i *)ref);
__m128i s0 = _mm_sad_epu8(src_line, zero);
__m128i s1;
- (void) width; // width = 64
+ int i;
- ref += 16;
- src_line = _mm_load_si128((const __m128i *)ref);
- s1 = _mm_sad_epu8(src_line, zero);
- s0 = _mm_adds_epu16(s0, s1);
-
- ref += 16;
- src_line = _mm_load_si128((const __m128i *)ref);
- s1 = _mm_sad_epu8(src_line, zero);
- s0 = _mm_adds_epu16(s0, s1);
-
- ref += 16;
- src_line = _mm_load_si128((const __m128i *)ref);
- s1 = _mm_sad_epu8(src_line, zero);
- s0 = _mm_adds_epu16(s0, s1);
+ for (i = 16; i < width; i += 16) {
+ ref += 16;
+ src_line = _mm_load_si128((const __m128i *)ref);
+ s1 = _mm_sad_epu8(src_line, zero);
+ s0 = _mm_adds_epu16(s0, s1);
+ }
s1 = _mm_srli_si128(s0, 8);
s0 = _mm_adds_epu16(s0, s1);
@@ -136,8 +128,6 @@
diff = _mm_xor_si128(diff, sign);
sum = _mm_sub_epi16(diff, sign);
- (void) width; // width = 64;
-
ref += 8;
src += 8;
@@ -145,7 +135,7 @@
v1 = _mm_unpackhi_epi16(sum, zero);
sum = _mm_add_epi32(v0, v1);
- for (idx = 1; idx < 8; ++idx) {
+ for (idx = 8; idx < width; idx += 8) {
v0 = _mm_loadu_si128((const __m128i *)ref);
v1 = _mm_load_si128((const __m128i *)src);
diff = _mm_subs_epi16(v0, v1);
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 251d240..d0c4c67 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -158,8 +158,8 @@
RANGE_CHECK_HI(cfg, g_threads, 64);
RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
- RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
- RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
+ RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
+ RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
@@ -550,6 +550,8 @@
if (res == VPX_CODEC_OK) {
ctx->cfg = *cfg;
set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
+ // On profile change, request a key frame
+ force_key |= ctx->cpi->common.profile != ctx->oxcf.profile;
vp9_change_config(ctx->cpi, &ctx->oxcf);
}