Compare commits
13 Commits
sandbox/hk
...
playground
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6b0c636b96 | ||
![]() |
b0aa2db2e7 | ||
![]() |
95d0f87d6e | ||
![]() |
c741a4fe03 | ||
![]() |
430c389f16 | ||
![]() |
d8b0d40bf6 | ||
![]() |
a4dfcd9a2d | ||
![]() |
be17f1b338 | ||
![]() |
ffdad39324 | ||
![]() |
07ac101806 | ||
![]() |
a49d80bfc8 | ||
![]() |
77a29953c5 | ||
![]() |
1a4b017fad |
1
README
1
README
@@ -55,7 +55,6 @@ COMPILING THE APPLICATIONS/LIBRARIES:
|
||||
armv6-linux-rvct
|
||||
armv6-linux-gcc
|
||||
armv6-none-rvct
|
||||
arm64-darwin-gcc
|
||||
armv7-android-gcc
|
||||
armv7-darwin-gcc
|
||||
armv7-linux-rvct
|
||||
|
@@ -799,7 +799,7 @@ process_common_toolchain() {
|
||||
arm*)
|
||||
# on arm, isa versions are supersets
|
||||
case ${tgt_isa} in
|
||||
arm64|armv8)
|
||||
armv8)
|
||||
soft_enable neon
|
||||
;;
|
||||
armv7|armv7s)
|
||||
@@ -1048,6 +1048,14 @@ EOF
|
||||
esac
|
||||
;;
|
||||
x86*)
|
||||
bits=32
|
||||
enabled x86_64 && bits=64
|
||||
check_cpp <<EOF && bits=x32
|
||||
#ifndef __ILP32__
|
||||
#error "not x32"
|
||||
#endif
|
||||
EOF
|
||||
|
||||
case ${tgt_os} in
|
||||
win*)
|
||||
enabled gcc && add_cflags -fno-common
|
||||
@@ -1086,6 +1094,8 @@ EOF
|
||||
esac
|
||||
;;
|
||||
gcc*)
|
||||
add_cflags -m${bits}
|
||||
add_ldflags -m${bits}
|
||||
link_with_cc=gcc
|
||||
tune_cflags="-march="
|
||||
setup_gnu_toolchain
|
||||
@@ -1110,20 +1120,6 @@ EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
bits=32
|
||||
enabled x86_64 && bits=64
|
||||
check_cpp <<EOF && bits=x32
|
||||
#ifndef __ILP32__
|
||||
#error "not x32"
|
||||
#endif
|
||||
EOF
|
||||
case ${tgt_cc} in
|
||||
gcc*)
|
||||
add_cflags -m${bits}
|
||||
add_ldflags -m${bits}
|
||||
;;
|
||||
esac
|
||||
|
||||
soft_enable runtime_cpu_detect
|
||||
# We can't use 'check_cflags' until the compiler is configured and CC is
|
||||
# populated.
|
||||
@@ -1226,12 +1222,10 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
tgt_os_no_version=$(echo "${tgt_os}" | tr -d "[0-9]")
|
||||
# Default use_x86inc to yes when we are 64 bit, non-pic, or on any
|
||||
# non-Darwin target.
|
||||
if [ "${tgt_isa}" = "x86_64" ] || [ "${pic}" != "yes" ] || \
|
||||
[ "${tgt_os_no_version}" != "darwin" ]; then
|
||||
soft_enable use_x86inc
|
||||
# default use_x86inc to yes if pic is no or 64bit or we are not on darwin
|
||||
if [ ${tgt_isa} = x86_64 -o ! "$pic" = "yes" -o \
|
||||
"${tgt_os#darwin}" = "${tgt_os}" ]; then
|
||||
soft_enable use_x86inc
|
||||
fi
|
||||
|
||||
# Position Independent Code (PIC) support, for building relocatable
|
||||
|
@@ -25,8 +25,7 @@ MAKE_JOBS=1
|
||||
LIBVPX_SOURCE_DIR=$(dirname "$0" | sed -e s,/build/make,,)
|
||||
LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
||||
ORIG_PWD="$(pwd)"
|
||||
TARGETS="arm64-darwin-gcc
|
||||
armv6-darwin-gcc
|
||||
TARGETS="armv6-darwin-gcc
|
||||
armv7-darwin-gcc
|
||||
armv7s-darwin-gcc
|
||||
x86-iphonesimulator-gcc
|
||||
@@ -55,9 +54,6 @@ build_target() {
|
||||
target_to_preproc_symbol() {
|
||||
target="$1"
|
||||
case "${target}" in
|
||||
arm64-*)
|
||||
echo "__aarch64__"
|
||||
;;
|
||||
armv6-*)
|
||||
echo "__ARM_ARCH_6__"
|
||||
;;
|
||||
|
9
configure
vendored
9
configure
vendored
@@ -96,7 +96,6 @@ all_platforms="${all_platforms} armv6-darwin-gcc"
|
||||
all_platforms="${all_platforms} armv6-linux-rvct"
|
||||
all_platforms="${all_platforms} armv6-linux-gcc"
|
||||
all_platforms="${all_platforms} armv6-none-rvct"
|
||||
all_platforms="${all_platforms} arm64-darwin-gcc"
|
||||
all_platforms="${all_platforms} armv7-android-gcc" #neon Cortex-A8
|
||||
all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8
|
||||
all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8
|
||||
@@ -274,7 +273,13 @@ EXPERIMENT_LIST="
|
||||
multiple_arf
|
||||
spatial_svc
|
||||
denoising
|
||||
fp_mb_stats
|
||||
masked_interinter
|
||||
interintra
|
||||
masked_interintra
|
||||
filterintra
|
||||
ext_tx
|
||||
supertx
|
||||
copy_coding
|
||||
"
|
||||
CONFIG_LIST="
|
||||
external_build
|
||||
|
@@ -28,6 +28,16 @@
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "./vpxstats.h"
|
||||
|
||||
static const struct arg_enum_list encoding_mode_enum[] = {
|
||||
{"i", INTER_LAYER_PREDICTION_I},
|
||||
{"alt-ip", ALT_INTER_LAYER_PREDICTION_IP},
|
||||
{"ip", INTER_LAYER_PREDICTION_IP},
|
||||
{"gf", USE_GOLDEN_FRAME},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static const arg_def_t encoding_mode_arg = ARG_DEF_ENUM(
|
||||
"m", "encoding-mode", 1, "Encoding mode algorithm", encoding_mode_enum);
|
||||
static const arg_def_t skip_frames_arg =
|
||||
ARG_DEF("s", "skip-frames", 1, "input frames to skip");
|
||||
static const arg_def_t frames_arg =
|
||||
@@ -48,6 +58,9 @@ static const arg_def_t quantizers_arg =
|
||||
ARG_DEF("q", "quantizers", 1, "quantizers for non key frames, also will "
|
||||
"be applied to key frames if -qn is not specified (lowest to "
|
||||
"highest layer)");
|
||||
static const arg_def_t quantizers_keyframe_arg =
|
||||
ARG_DEF("qn", "quantizers-keyframe", 1, "quantizers for key frames (lowest "
|
||||
"to highest layer)");
|
||||
static const arg_def_t passes_arg =
|
||||
ARG_DEF("p", "passes", 1, "Number of passes (1/2)");
|
||||
static const arg_def_t pass_arg =
|
||||
@@ -64,13 +77,16 @@ static const arg_def_t max_bitrate_arg =
|
||||
ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate");
|
||||
|
||||
static const arg_def_t *svc_args[] = {
|
||||
&frames_arg, &width_arg, &height_arg,
|
||||
&encoding_mode_arg, &frames_arg, &width_arg, &height_arg,
|
||||
&timebase_arg, &bitrate_arg, &skip_frames_arg, &layers_arg,
|
||||
&kf_dist_arg, &scale_factors_arg, &quantizers_arg, &passes_arg,
|
||||
&pass_arg, &fpf_name_arg, &min_q_arg, &max_q_arg,
|
||||
&min_bitrate_arg, &max_bitrate_arg, NULL
|
||||
&kf_dist_arg, &scale_factors_arg, &quantizers_arg,
|
||||
&quantizers_keyframe_arg, &passes_arg, &pass_arg,
|
||||
&fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg,
|
||||
&max_bitrate_arg, NULL
|
||||
};
|
||||
|
||||
static const SVC_ENCODING_MODE default_encoding_mode =
|
||||
INTER_LAYER_PREDICTION_IP;
|
||||
static const uint32_t default_frames_to_skip = 0;
|
||||
static const uint32_t default_frames_to_code = 60 * 60;
|
||||
static const uint32_t default_width = 1920;
|
||||
@@ -119,6 +135,7 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
// initialize SvcContext with parameters that will be passed to vpx_svc_init
|
||||
svc_ctx->log_level = SVC_LOG_DEBUG;
|
||||
svc_ctx->spatial_layers = default_spatial_layers;
|
||||
svc_ctx->encoding_mode = default_encoding_mode;
|
||||
|
||||
// start with default encoder configuration
|
||||
res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
|
||||
@@ -144,7 +161,9 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
|
||||
arg.argv_step = 1;
|
||||
|
||||
if (arg_match(&arg, &frames_arg, argi)) {
|
||||
if (arg_match(&arg, &encoding_mode_arg, argi)) {
|
||||
svc_ctx->encoding_mode = arg_parse_enum_or_int(&arg);
|
||||
} else if (arg_match(&arg, &frames_arg, argi)) {
|
||||
app_input->frames_to_code = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &width_arg, argi)) {
|
||||
enc_cfg->g_w = arg_parse_uint(&arg);
|
||||
@@ -164,7 +183,9 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
} else if (arg_match(&arg, &scale_factors_arg, argi)) {
|
||||
vpx_svc_set_scale_factors(svc_ctx, arg.val);
|
||||
} else if (arg_match(&arg, &quantizers_arg, argi)) {
|
||||
vpx_svc_set_quantizers(svc_ctx, arg.val);
|
||||
vpx_svc_set_quantizers(svc_ctx, arg.val, 0);
|
||||
} else if (arg_match(&arg, &quantizers_keyframe_arg, argi)) {
|
||||
vpx_svc_set_quantizers(svc_ctx, arg.val, 1);
|
||||
} else if (arg_match(&arg, &passes_arg, argi)) {
|
||||
passes = arg_parse_uint(&arg);
|
||||
if (passes < 1 || passes > 2) {
|
||||
@@ -249,12 +270,12 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
|
||||
printf(
|
||||
"Codec %s\nframes: %d, skip: %d\n"
|
||||
"layers: %d\n"
|
||||
"mode: %d, layers: %d\n"
|
||||
"width %d, height: %d,\n"
|
||||
"num: %d, den: %d, bitrate: %d,\n"
|
||||
"gop size: %d\n",
|
||||
vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code,
|
||||
app_input->frames_to_skip,
|
||||
app_input->frames_to_skip, svc_ctx->encoding_mode,
|
||||
svc_ctx->spatial_layers, enc_cfg->g_w, enc_cfg->g_h,
|
||||
enc_cfg->g_timebase.num, enc_cfg->g_timebase.den,
|
||||
enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
|
||||
|
2
libs.mk
2
libs.mk
@@ -170,7 +170,7 @@ CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/vpx_once.h
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += $(BUILD_PFX)vpx_config.c
|
||||
INSTALL-SRCS-no += $(BUILD_PFX)vpx_config.c
|
||||
ifeq ($(ARCH_X86)$(ARCH_X86_64),yes)
|
||||
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += third_party/x86inc/x86inc.asm
|
||||
CODEC_SRCS-$(BUILD_LIBVPX) += third_party/x86inc/x86inc.asm
|
||||
endif
|
||||
CODEC_EXPORTS-$(BUILD_LIBVPX) += vpx/exports_com
|
||||
CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
|
||||
|
@@ -14,49 +14,30 @@
|
||||
#include "test/encode_test_driver.h"
|
||||
#include "test/i420_video_source.h"
|
||||
#include "test/util.h"
|
||||
#include "test/y4m_video_source.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const int kMaxPSNR = 100;
|
||||
|
||||
class CpuSpeedTest : public ::libvpx_test::EncoderTest,
|
||||
public ::libvpx_test::CodecTestWith2Params<
|
||||
libvpx_test::TestMode, int> {
|
||||
protected:
|
||||
CpuSpeedTest()
|
||||
: EncoderTest(GET_PARAM(0)),
|
||||
encoding_mode_(GET_PARAM(1)),
|
||||
set_cpu_used_(GET_PARAM(2)),
|
||||
min_psnr_(kMaxPSNR) {}
|
||||
CpuSpeedTest() : EncoderTest(GET_PARAM(0)) {}
|
||||
virtual ~CpuSpeedTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
InitializeConfig();
|
||||
SetMode(encoding_mode_);
|
||||
if (encoding_mode_ != ::libvpx_test::kRealTime) {
|
||||
cfg_.g_lag_in_frames = 25;
|
||||
cfg_.rc_end_usage = VPX_VBR;
|
||||
} else {
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
cfg_.rc_end_usage = VPX_CBR;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void BeginPassHook(unsigned int /*pass*/) {
|
||||
min_psnr_ = kMaxPSNR;
|
||||
SetMode(GET_PARAM(1));
|
||||
set_cpu_used_ = GET_PARAM(2);
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
if (video->frame() == 1) {
|
||||
encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
|
||||
if (encoding_mode_ != ::libvpx_test::kRealTime) {
|
||||
encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
|
||||
encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
|
||||
encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
|
||||
encoder->Control(VP8E_SET_ARNR_TYPE, 3);
|
||||
}
|
||||
encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
|
||||
encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
|
||||
encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
|
||||
encoder->Control(VP8E_SET_ARNR_TYPE, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,15 +45,7 @@ class CpuSpeedTest : public ::libvpx_test::EncoderTest,
|
||||
if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
if (pkt->data.psnr.psnr[0] < min_psnr_)
|
||||
min_psnr_ = pkt->data.psnr.psnr[0];
|
||||
}
|
||||
|
||||
::libvpx_test::TestMode encoding_mode_;
|
||||
int set_cpu_used_;
|
||||
double min_psnr_;
|
||||
};
|
||||
|
||||
TEST_P(CpuSpeedTest, TestQ0) {
|
||||
@@ -80,6 +53,7 @@ TEST_P(CpuSpeedTest, TestQ0) {
|
||||
// without a mismatch when passing in a very low max q. This pushes
|
||||
// the encoder to producing lots of big partitions which will likely
|
||||
// extend into the border and test the border condition.
|
||||
cfg_.g_lag_in_frames = 25;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 5;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 2000;
|
||||
cfg_.rc_target_bitrate = 400;
|
||||
@@ -89,32 +63,16 @@ TEST_P(CpuSpeedTest, TestQ0) {
|
||||
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
|
||||
20);
|
||||
|
||||
init_flags_ = VPX_CODEC_USE_PSNR;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
EXPECT_GE(min_psnr_, kMaxPSNR);
|
||||
}
|
||||
|
||||
TEST_P(CpuSpeedTest, TestScreencastQ0) {
|
||||
::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25);
|
||||
cfg_.g_timebase = video.timebase();
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 5;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 2000;
|
||||
cfg_.rc_target_bitrate = 400;
|
||||
cfg_.rc_max_quantizer = 0;
|
||||
cfg_.rc_min_quantizer = 0;
|
||||
|
||||
init_flags_ = VPX_CODEC_USE_PSNR;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
EXPECT_GE(min_psnr_, kMaxPSNR);
|
||||
}
|
||||
|
||||
TEST_P(CpuSpeedTest, TestEncodeHighBitrate) {
|
||||
// Validate that this non multiple of 64 wide clip encodes and decodes
|
||||
// without a mismatch when passing in a very low max q. This pushes
|
||||
// the encoder to producing lots of big partitions which will likely
|
||||
// extend into the border and test the border condition.
|
||||
cfg_.g_lag_in_frames = 25;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 5;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 2000;
|
||||
cfg_.rc_target_bitrate = 12000;
|
||||
@@ -131,6 +89,7 @@ TEST_P(CpuSpeedTest, TestLowBitrate) {
|
||||
// when passing in a very high min q. This pushes the encoder to producing
|
||||
// lots of small partitions which might will test the other condition.
|
||||
|
||||
cfg_.g_lag_in_frames = 25;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 5;
|
||||
cfg_.rc_2pass_vbr_minsection_pct = 2000;
|
||||
cfg_.rc_target_bitrate = 200;
|
||||
@@ -149,7 +108,6 @@ using std::tr1::make_tuple;
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(
|
||||
CpuSpeedTest,
|
||||
::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
|
||||
::libvpx_test::kRealTime),
|
||||
::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood),
|
||||
::testing::Range(0, 8));
|
||||
} // namespace
|
||||
|
@@ -576,7 +576,7 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
|
||||
// Expect some frame drops in this test: for this 200 frames test,
|
||||
// expect at least 10% and not more than 60% drops.
|
||||
ASSERT_GE(num_drops_, 20);
|
||||
ASSERT_LE(num_drops_, 130);
|
||||
ASSERT_LE(num_drops_, 120);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -97,9 +97,6 @@ const char *const kVP9InvalidFileTests[] = {
|
||||
"invalid-vp90-01.webm",
|
||||
"invalid-vp90-02.webm",
|
||||
"invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf",
|
||||
"invalid-vp90-03.webm",
|
||||
"invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf",
|
||||
"invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf",
|
||||
};
|
||||
|
||||
#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
|
||||
|
@@ -28,11 +28,10 @@ class MD5 {
|
||||
// plane, we never want to round down and thus skip a pixel so if
|
||||
// we are shifting by 1 (chroma_shift) we add 1 before doing the shift.
|
||||
// This works only for chroma_shift of 0 and 1.
|
||||
const int bytes_per_sample = (img->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
|
||||
const int h = plane ? (img->d_h + img->y_chroma_shift) >>
|
||||
img->y_chroma_shift : img->d_h;
|
||||
const int w = (plane ? (img->d_w + img->x_chroma_shift) >>
|
||||
img->x_chroma_shift : img->d_w) * bytes_per_sample;
|
||||
const int w = plane ? (img->d_w + img->x_chroma_shift) >>
|
||||
img->x_chroma_shift : img->d_w;
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
MD5Update(&md5_, buf, w);
|
||||
|
@@ -41,6 +41,7 @@ class SvcTest : public ::testing::Test {
|
||||
virtual ~SvcTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
svc_.encoding_mode = INTER_LAYER_PREDICTION_IP;
|
||||
svc_.log_level = SVC_LOG_DEBUG;
|
||||
svc_.log_print = 0;
|
||||
|
||||
@@ -130,13 +131,22 @@ TEST_F(SvcTest, SetLayersOption) {
|
||||
EXPECT_EQ(3, svc_.spatial_layers);
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, SetEncodingMode) {
|
||||
vpx_codec_err_t res = vpx_svc_set_options(&svc_, "encoding-mode=alt-ip");
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
codec_initialized_ = true;
|
||||
EXPECT_EQ(ALT_INTER_LAYER_PREDICTION_IP, svc_.encoding_mode);
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, SetMultipleOptions) {
|
||||
vpx_codec_err_t res =
|
||||
vpx_svc_set_options(&svc_, "layers=2 scale-factors=1/3,2/3");
|
||||
vpx_codec_err_t res = vpx_svc_set_options(&svc_, "layers=2 encoding-mode=ip");
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
codec_initialized_ = true;
|
||||
EXPECT_EQ(2, svc_.spatial_layers);
|
||||
EXPECT_EQ(INTER_LAYER_PREDICTION_IP, svc_.encoding_mode);
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, SetScaleFactorsOption) {
|
||||
@@ -167,20 +177,48 @@ TEST_F(SvcTest, SetQuantizersOption) {
|
||||
codec_initialized_ = true;
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, SetQuantizers) {
|
||||
vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,30");
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
res = vpx_svc_set_quantizers(&svc_, NULL);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
TEST_F(SvcTest, SetKeyFrameQuantizersOption) {
|
||||
svc_.spatial_layers = 2;
|
||||
res = vpx_svc_set_quantizers(&svc_, "40");
|
||||
vpx_codec_err_t res = vpx_svc_set_options(&svc_,
|
||||
"quantizers-keyframe=not-quantizers");
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
res = vpx_svc_set_quantizers(&svc_, "40,30");
|
||||
vpx_svc_set_options(&svc_, "quantizers-keyframe=40,45");
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
codec_initialized_ = true;
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, SetQuantizers) {
|
||||
vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,30", 0);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
res = vpx_svc_set_quantizers(&svc_, NULL, 0);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
svc_.spatial_layers = 2;
|
||||
res = vpx_svc_set_quantizers(&svc_, "40", 0);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
res = vpx_svc_set_quantizers(&svc_, "40,30", 0);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
codec_initialized_ = true;
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, SetKeyFrameQuantizers) {
|
||||
vpx_codec_err_t res = vpx_svc_set_quantizers(NULL, "40,31", 1);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
res = vpx_svc_set_quantizers(&svc_, NULL, 1);
|
||||
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
|
||||
|
||||
res = vpx_svc_set_quantizers(&svc_, "40,30", 1);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
EXPECT_EQ(VPX_CODEC_OK, res);
|
||||
@@ -211,7 +249,7 @@ TEST_F(SvcTest, SetScaleFactors) {
|
||||
TEST_F(SvcTest, FirstFrameHasLayers) {
|
||||
svc_.spatial_layers = 2;
|
||||
vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30", 0);
|
||||
|
||||
vpx_codec_err_t res =
|
||||
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
@@ -246,7 +284,7 @@ TEST_F(SvcTest, FirstFrameHasLayers) {
|
||||
TEST_F(SvcTest, EncodeThreeFrames) {
|
||||
svc_.spatial_layers = 2;
|
||||
vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30", 0);
|
||||
int decoded_frames = 0;
|
||||
vpx_codec_err_t res_dec;
|
||||
int frame_size;
|
||||
@@ -322,7 +360,7 @@ TEST_F(SvcTest, EncodeThreeFrames) {
|
||||
TEST_F(SvcTest, GetLayerResolution) {
|
||||
svc_.spatial_layers = 2;
|
||||
vpx_svc_set_scale_factors(&svc_, "4/16,8/16");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30", 0);
|
||||
|
||||
vpx_codec_err_t res =
|
||||
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
@@ -361,7 +399,7 @@ TEST_F(SvcTest, TwoPassEncode) {
|
||||
svc_.spatial_layers = 2;
|
||||
codec_enc_.g_pass = VPX_RC_FIRST_PASS;
|
||||
vpx_svc_set_scale_factors(&svc_, "4/16,16/16");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30");
|
||||
vpx_svc_set_quantizers(&svc_, "40,30", 0);
|
||||
|
||||
vpx_codec_err_t res =
|
||||
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||
|
@@ -4,17 +4,6 @@ fe346136b9b8c1e6f6084cc106485706915795e4 invalid-vp90-01.webm
|
||||
25751f5d3b05ff03f0719ad42cd625348eb8961e invalid-vp90-01.webm.res
|
||||
d78e2fceba5ac942246503ec8366f879c4775ca5 invalid-vp90-02.webm
|
||||
2dadee5306245fa5eeb0f99652d0e17afbcba96d invalid-vp90-02.webm.res
|
||||
df1a1453feb3c00d7d89746c7003b4163523bff3 invalid-vp90-03.webm
|
||||
8fe6fd82bf537340f586f97a7ae31fb37ccda302 invalid-vp90-03.webm.res
|
||||
a432f96ff0a787268e2f94a8092ab161a18d1b06 park_joy_90p_10_420.y4m
|
||||
0b194cc312c3a2e84d156a221b0a5eb615dfddc5 park_joy_90p_10_422.y4m
|
||||
ff0e0a21dc2adc95b8c1b37902713700655ced17 park_joy_90p_10_444.y4m
|
||||
614c32ae1eca391e867c70d19974f0d62664dd99 park_joy_90p_12_420.y4m
|
||||
c92825f1ea25c5c37855083a69faac6ac4641a9e park_joy_90p_12_422.y4m
|
||||
b592189b885b6cc85db55cc98512a197d73d3b34 park_joy_90p_12_444.y4m
|
||||
4e0eb61e76f0684188d9bc9f3ce61f6b6b77bb2c park_joy_90p_8_420.y4m
|
||||
7a193ff7dfeb96ba5f82b2afd7afa9e1fe83d947 park_joy_90p_8_422.y4m
|
||||
bdb7856e6bc93599bdda05c2e773a9f22b6c6d03 park_joy_90p_8_444.y4m
|
||||
b1f1c3ec79114b9a0651af24ce634afb44a9a419 rush_hour_444.y4m
|
||||
5184c46ddca8b1fadd16742e8500115bc8f749da vp80-00-comprehensive-001.ivf
|
||||
65bf1bbbced81b97bd030f376d1b7f61a224793f vp80-00-comprehensive-002.ivf
|
||||
@@ -544,6 +533,8 @@ b6524e4084d15b5d0caaa3d3d1368db30cbee69c vp90-2-03-deltaq.webm
|
||||
7f6d8879336239a43dbb6c9f13178cb11cf7ed09 vp90-2-05-resize.ivf.md5
|
||||
bf61ddc1f716eba58d4c9837d4e91031d9ce4ffe vp90-2-06-bilinear.webm
|
||||
f6235f937552e11d8eb331ec55da6b3aa596b9ac vp90-2-06-bilinear.webm.md5
|
||||
495256cfd123fe777b2c0406862ed8468a1f4677 vp91-2-04-yv444.webm
|
||||
65e3a7ffef61ab340d9140f335ecc49125970c2c vp91-2-04-yv444.webm.md5
|
||||
0c83a1e414fde3bccd6dc451bbaee68e59974c76 vp90-2-07-frame_parallel.webm
|
||||
e5c2c9fb383e5bf3b563480adaeba5b7e3475ecd vp90-2-07-frame_parallel.webm.md5
|
||||
086c7edcffd699ae7d99d710fd7e53b18910ca5b vp90-2-08-tile_1x2_frame_parallel.webm
|
||||
@@ -653,11 +644,5 @@ e615575ded499ea1d992f3b38e3baa434509cdcd vp90-2-15-segkey.webm
|
||||
e3ab35d4316c5e81325c50f5236ceca4bc0d35df vp90-2-15-segkey.webm.md5
|
||||
9b7ca2cac09d34c4a5d296c1900f93b1e2f69d0d vp90-2-15-segkey_adpq.webm
|
||||
8f46ba5f785d0c2170591a153e0d0d146a7c8090 vp90-2-15-segkey_adpq.webm.md5
|
||||
0321d507ce62dedc8a51b4e9011f7a19aed9c3dc vp91-2-04-yuv444.webm
|
||||
367e423dd41fdb49aa028574a2cfec5c2f325c5c vp91-2-04-yuv444.webm.md5
|
||||
76024eb753cdac6a5e5703aaea189d35c3c30ac7 invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf
|
||||
d3964f9dad9f60363c81b688324d95b4ec7c8038 invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf.res
|
||||
83f50908c8dc0ef8760595447a2ff7727489542e invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
|
||||
456d1493e52d32a5c30edf44a27debc1fa6b253a invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
|
||||
c123d1f9f02fb4143abb5e271916e3a3080de8f6 invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
|
||||
456d1493e52d32a5c30edf44a27debc1fa6b253a invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
|
||||
|
27
test/test.mk
27
test/test.mk
@@ -15,7 +15,7 @@ LIBVPX_TEST_SRCS-yes += video_source.h
|
||||
##
|
||||
## Black box tests only use the public API.
|
||||
##
|
||||
LIBVPX_TEST_SRCS-yes += ../md5_utils.h ../md5_utils.c
|
||||
LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../md5_utils.h ../md5_utils.c
|
||||
LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ivf_video_source.h
|
||||
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../y4minput.h ../y4minput.c
|
||||
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc
|
||||
@@ -42,9 +42,6 @@ LIBVPX_TEST_SRCS-yes += decode_test_driver.h
|
||||
LIBVPX_TEST_SRCS-yes += encode_test_driver.cc
|
||||
LIBVPX_TEST_SRCS-yes += encode_test_driver.h
|
||||
|
||||
## Y4m parsing.
|
||||
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += y4m_test.cc ../y4menc.c ../y4menc.h
|
||||
|
||||
## WebM Parsing
|
||||
ifeq ($(CONFIG_WEBM_IO), yes)
|
||||
LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser.cpp
|
||||
@@ -137,19 +134,7 @@ endif # CONFIG_SHARED
|
||||
##
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv
|
||||
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_420.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_422.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_444.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_420.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_422.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_444.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_422.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_444.y4m
|
||||
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m
|
||||
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf.md5
|
||||
@@ -723,6 +708,8 @@ LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf.md5
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm.md5
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yv444.webm.md5
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm.md5
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm
|
||||
@@ -771,22 +758,14 @@ LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm.md5
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm.md5
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm.md5
|
||||
|
||||
# Invalid files for testing libvpx error checking.
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01.webm.res
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02.webm.res
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03.webm
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03.webm.res
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf.res
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
|
||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
|
||||
|
||||
ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
|
||||
# BBB VP9 streams
|
||||
|
@@ -165,7 +165,7 @@ const char *const kVP9TestVectors[] = {
|
||||
"vp90-2-11-size-351x287.webm", "vp90-2-11-size-351x288.webm",
|
||||
"vp90-2-11-size-352x287.webm", "vp90-2-12-droppable_1.ivf",
|
||||
"vp90-2-12-droppable_2.ivf", "vp90-2-12-droppable_3.ivf",
|
||||
"vp90-2-13-largescaling.webm",
|
||||
"vp90-2-13-largescaling.webm", "vp91-2-04-yv444.webm",
|
||||
"vp90-2-14-resize-fp-tiles-1-16.webm",
|
||||
"vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm",
|
||||
"vp90-2-14-resize-fp-tiles-1-2.webm", "vp90-2-14-resize-fp-tiles-1-4.webm",
|
||||
@@ -180,7 +180,6 @@ const char *const kVP9TestVectors[] = {
|
||||
"vp90-2-14-resize-fp-tiles-8-16.webm", "vp90-2-14-resize-fp-tiles-8-1.webm",
|
||||
"vp90-2-14-resize-fp-tiles-8-2.webm", "vp90-2-14-resize-fp-tiles-8-4.webm",
|
||||
"vp90-2-15-segkey.webm", "vp90-2-15-segkey_adpq.webm",
|
||||
"vp91-2-04-yuv444.webm",
|
||||
};
|
||||
const int kNumVP9TestVectors = NELEMENTS(kVP9TestVectors);
|
||||
#endif // CONFIG_VP9_DECODER
|
||||
|
@@ -78,7 +78,7 @@ string DecodeFile(const string &filename) {
|
||||
ref.idx = rnd.Rand8() % 3;
|
||||
decoder.Control(VP9_GET_REFERENCE, &ref);
|
||||
|
||||
CheckUserPrivateData(ref.img.user_priv, NULL);
|
||||
CheckUserPrivateData(ref.img.user_priv, &frame_num);
|
||||
}
|
||||
md5.Add(img);
|
||||
}
|
||||
|
@@ -50,15 +50,6 @@ static FILE *OpenTestDataFile(const std::string& file_name) {
|
||||
return fopen(path_to_source.c_str(), "rb");
|
||||
}
|
||||
|
||||
static FILE *OpenTestOutFile(const std::string& file_name) {
|
||||
const std::string path_to_source = GetDataPath() + "/" + file_name;
|
||||
return fopen(path_to_source.c_str(), "wb");
|
||||
}
|
||||
|
||||
static FILE *OpenTempOutFile() {
|
||||
return tmpfile();
|
||||
}
|
||||
|
||||
// Abstract base class for test video sources, which provide a stream of
|
||||
// vpx_image_t images with associated timestamps and duration.
|
||||
class VideoSource {
|
||||
|
@@ -36,17 +36,6 @@ class LosslessTestLarge : public ::libvpx_test::EncoderTest,
|
||||
SetMode(encoding_mode_);
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
|
||||
::libvpx_test::Encoder *encoder) {
|
||||
if (video->frame() == 1) {
|
||||
// Only call Control if quantizer > 0 to verify that using quantizer
|
||||
// alone will activate lossless
|
||||
if (cfg_.rc_max_quantizer > 0 || cfg_.rc_min_quantizer > 0) {
|
||||
encoder->Control(VP9E_SET_LOSSLESS, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void BeginPassHook(unsigned int /*pass*/) {
|
||||
psnr_ = kMaxPsnr;
|
||||
nframes_ = 0;
|
||||
@@ -102,24 +91,5 @@ TEST_P(LosslessTestLarge, TestLossLessEncoding444) {
|
||||
EXPECT_GE(psnr_lossless, kMaxPsnr);
|
||||
}
|
||||
|
||||
TEST_P(LosslessTestLarge, TestLossLessEncodingCtrl) {
|
||||
const vpx_rational timebase = { 33333333, 1000000000 };
|
||||
cfg_.g_timebase = timebase;
|
||||
cfg_.rc_target_bitrate = 2000;
|
||||
cfg_.g_lag_in_frames = 25;
|
||||
// Intentionally set Q > 0, to make sure control can be used to activate
|
||||
// lossless
|
||||
cfg_.rc_min_quantizer = 10;
|
||||
cfg_.rc_max_quantizer = 20;
|
||||
|
||||
init_flags_ = VPX_CODEC_USE_PSNR;
|
||||
|
||||
libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
|
||||
timebase.den, timebase.num, 0, 10);
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
const double psnr_lossless = GetMinPsnr();
|
||||
EXPECT_GE(psnr_lossless, kMaxPsnr);
|
||||
}
|
||||
|
||||
VP9_INSTANTIATE_TEST_CASE(LosslessTestLarge, ALL_TEST_MODES);
|
||||
} // namespace
|
||||
|
@@ -28,11 +28,11 @@ class VP9WorkerThreadTest : public ::testing::TestWithParam<bool> {
|
||||
protected:
|
||||
virtual ~VP9WorkerThreadTest() {}
|
||||
virtual void SetUp() {
|
||||
vp9_get_worker_interface()->init(&worker_);
|
||||
vp9_worker_init(&worker_);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
vp9_get_worker_interface()->end(&worker_);
|
||||
vp9_worker_end(&worker_);
|
||||
}
|
||||
|
||||
VP9Worker worker_;
|
||||
@@ -45,11 +45,10 @@ int ThreadHook(void* data, void* return_value) {
|
||||
}
|
||||
|
||||
TEST_P(VP9WorkerThreadTest, HookSuccess) {
|
||||
// should be a no-op.
|
||||
EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
|
||||
EXPECT_NE(vp9_worker_sync(&worker_), 0); // should be a no-op.
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
EXPECT_NE(vp9_get_worker_interface()->reset(&worker_), 0);
|
||||
EXPECT_NE(vp9_worker_reset(&worker_), 0);
|
||||
|
||||
int hook_data = 0;
|
||||
int return_value = 1; // return successfully from the hook
|
||||
@@ -59,21 +58,20 @@ TEST_P(VP9WorkerThreadTest, HookSuccess) {
|
||||
|
||||
const bool synchronous = GetParam();
|
||||
if (synchronous) {
|
||||
vp9_get_worker_interface()->execute(&worker_);
|
||||
vp9_worker_execute(&worker_);
|
||||
} else {
|
||||
vp9_get_worker_interface()->launch(&worker_);
|
||||
vp9_worker_launch(&worker_);
|
||||
}
|
||||
EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
|
||||
EXPECT_NE(vp9_worker_sync(&worker_), 0);
|
||||
EXPECT_FALSE(worker_.had_error);
|
||||
EXPECT_EQ(5, hook_data);
|
||||
|
||||
// should be a no-op.
|
||||
EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
|
||||
EXPECT_NE(vp9_worker_sync(&worker_), 0); // should be a no-op.
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(VP9WorkerThreadTest, HookFailure) {
|
||||
EXPECT_NE(vp9_get_worker_interface()->reset(&worker_), 0);
|
||||
EXPECT_NE(vp9_worker_reset(&worker_), 0);
|
||||
|
||||
int hook_data = 0;
|
||||
int return_value = 0; // return failure from the hook
|
||||
@@ -83,49 +81,26 @@ TEST_P(VP9WorkerThreadTest, HookFailure) {
|
||||
|
||||
const bool synchronous = GetParam();
|
||||
if (synchronous) {
|
||||
vp9_get_worker_interface()->execute(&worker_);
|
||||
vp9_worker_execute(&worker_);
|
||||
} else {
|
||||
vp9_get_worker_interface()->launch(&worker_);
|
||||
vp9_worker_launch(&worker_);
|
||||
}
|
||||
EXPECT_FALSE(vp9_get_worker_interface()->sync(&worker_));
|
||||
EXPECT_FALSE(vp9_worker_sync(&worker_));
|
||||
EXPECT_EQ(1, worker_.had_error);
|
||||
|
||||
// Ensure _reset() clears the error and _launch() can be called again.
|
||||
return_value = 1;
|
||||
EXPECT_NE(vp9_get_worker_interface()->reset(&worker_), 0);
|
||||
EXPECT_NE(vp9_worker_reset(&worker_), 0);
|
||||
EXPECT_FALSE(worker_.had_error);
|
||||
vp9_get_worker_interface()->launch(&worker_);
|
||||
EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
|
||||
vp9_worker_launch(&worker_);
|
||||
EXPECT_NE(vp9_worker_sync(&worker_), 0);
|
||||
EXPECT_FALSE(worker_.had_error);
|
||||
}
|
||||
|
||||
TEST(VP9WorkerThreadTest, TestInterfaceAPI) {
|
||||
EXPECT_EQ(0, vp9_set_worker_interface(NULL));
|
||||
EXPECT_TRUE(vp9_get_worker_interface() != NULL);
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
VP9WorkerInterface winterface = *vp9_get_worker_interface();
|
||||
switch (i) {
|
||||
default:
|
||||
case 0: winterface.init = NULL; break;
|
||||
case 1: winterface.reset = NULL; break;
|
||||
case 2: winterface.sync = NULL; break;
|
||||
case 3: winterface.launch = NULL; break;
|
||||
case 4: winterface.execute = NULL; break;
|
||||
case 5: winterface.end = NULL; break;
|
||||
}
|
||||
EXPECT_EQ(0, vp9_set_worker_interface(&winterface));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Multi-threaded decode tests
|
||||
|
||||
#if CONFIG_WEBM_IO
|
||||
struct FileList {
|
||||
const char *name;
|
||||
const char *expected_md5;
|
||||
};
|
||||
|
||||
// Decodes |filename| with |num_threads|. Returns the md5 of the decoded frames.
|
||||
string DecodeFile(const string& filename, int num_threads) {
|
||||
libvpx_test::WebMVideoSource video(filename);
|
||||
@@ -155,77 +130,39 @@ string DecodeFile(const string& filename, int num_threads) {
|
||||
return string(md5.Get());
|
||||
}
|
||||
|
||||
void DecodeFiles(const FileList files[]) {
|
||||
for (const FileList *iter = files; iter->name != NULL; ++iter) {
|
||||
SCOPED_TRACE(iter->name);
|
||||
for (int t = 2; t <= 8; ++t) {
|
||||
EXPECT_EQ(iter->expected_md5, DecodeFile(iter->name, t))
|
||||
<< "threads = " << t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trivial serialized thread worker interface implementation.
|
||||
// Note any worker that requires synchronization between other workers will
|
||||
// hang.
|
||||
namespace impl {
|
||||
|
||||
void Init(VP9Worker *const worker) { memset(worker, 0, sizeof(*worker)); }
|
||||
int Reset(VP9Worker *const /*worker*/) { return 1; }
|
||||
int Sync(VP9Worker *const worker) { return !worker->had_error; }
|
||||
|
||||
void Execute(VP9Worker *const worker) {
|
||||
worker->had_error |= worker->hook(worker->data1, worker->data2);
|
||||
}
|
||||
|
||||
void Launch(VP9Worker *const worker) { Execute(worker); }
|
||||
void End(VP9Worker *const /*worker*/) {}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
TEST(VP9WorkerThreadTest, TestSerialInterface) {
|
||||
static const VP9WorkerInterface serial_interface = {
|
||||
impl::Init, impl::Reset, impl::Sync, impl::Launch, impl::Execute, impl::End
|
||||
};
|
||||
// TODO(jzern): Avoid using a file that will use the row-based thread
|
||||
// loopfilter, with the simple serialized implementation it will hang. This is
|
||||
// due to its expectation that rows will be run in parallel as they wait on
|
||||
// progress in the row above before proceeding.
|
||||
static const char expected_md5[] = "b35a1b707b28e82be025d960aba039bc";
|
||||
static const char filename[] = "vp90-2-03-size-226x226.webm";
|
||||
VP9WorkerInterface default_interface = *vp9_get_worker_interface();
|
||||
|
||||
EXPECT_NE(vp9_set_worker_interface(&serial_interface), 0);
|
||||
EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
|
||||
|
||||
// Reset the interface.
|
||||
EXPECT_NE(vp9_set_worker_interface(&default_interface), 0);
|
||||
EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
|
||||
}
|
||||
|
||||
TEST(VP9DecodeMultiThreadedTest, Decode) {
|
||||
TEST(VP9DecodeMTTest, MTDecode) {
|
||||
// no tiles or frame parallel; this exercises loop filter threading.
|
||||
EXPECT_EQ("b35a1b707b28e82be025d960aba039bc",
|
||||
DecodeFile("vp90-2-03-size-226x226.webm", 2));
|
||||
EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc",
|
||||
DecodeFile("vp90-2-03-size-226x226.webm", 2).c_str());
|
||||
}
|
||||
|
||||
TEST(VP9DecodeMultiThreadedTest, Decode2) {
|
||||
static const FileList files[] = {
|
||||
TEST(VP9DecodeMTTest, MTDecode2) {
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *expected_md5;
|
||||
} files[] = {
|
||||
{ "vp90-2-08-tile_1x2_frame_parallel.webm",
|
||||
"68ede6abd66bae0a2edf2eb9232241b6" },
|
||||
{ "vp90-2-08-tile_1x4_frame_parallel.webm",
|
||||
"368ebc6ebf3a5e478d85b2c3149b2848" },
|
||||
{ "vp90-2-08-tile_1x8_frame_parallel.webm",
|
||||
"17e439da2388aff3a0f69cb22579c6c1" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
DecodeFiles(files);
|
||||
for (int i = 0; i < static_cast<int>(sizeof(files) / sizeof(files[0])); ++i) {
|
||||
for (int t = 2; t <= 8; ++t) {
|
||||
EXPECT_STREQ(files[i].expected_md5, DecodeFile(files[i].name, t).c_str())
|
||||
<< "threads = " << t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test tile quantity changes within one file.
|
||||
TEST(VP9DecodeMultiThreadedTest, Decode3) {
|
||||
static const FileList files[] = {
|
||||
TEST(VP9DecodeMTTest, MTDecode3) {
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *expected_md5;
|
||||
} files[] = {
|
||||
{ "vp90-2-14-resize-fp-tiles-1-16.webm",
|
||||
"0cd5e632c326297e975f38949c31ea94" },
|
||||
{ "vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm",
|
||||
@@ -270,10 +207,14 @@ TEST(VP9DecodeMultiThreadedTest, Decode3) {
|
||||
"ae96f21f21b6370cc0125621b441fc52" },
|
||||
{ "vp90-2-14-resize-fp-tiles-8-4.webm",
|
||||
"3eb4f24f10640d42218f7fd7b9fd30d4" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
DecodeFiles(files);
|
||||
for (int i = 0; i < static_cast<int>(sizeof(files) / sizeof(files[0])); ++i) {
|
||||
for (int t = 2; t <= 8; ++t) {
|
||||
EXPECT_STREQ(files[i].expected_md5, DecodeFile(files[i].name, t).c_str())
|
||||
<< "threads = " << t;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_WEBM_IO
|
||||
|
||||
|
193
test/y4m_test.cc
193
test/y4m_test.cc
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "test/md5_helper.h"
|
||||
#include "test/util.h"
|
||||
#include "test/y4m_video_source.h"
|
||||
#include "third_party/googletest/src/include/gtest/gtest.h"
|
||||
#include "./vpx_config.h"
|
||||
#include "./y4menc.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using std::string;
|
||||
using std::tr1::make_tuple;
|
||||
|
||||
static const unsigned int kWidth = 160;
|
||||
static const unsigned int kHeight = 90;
|
||||
static const unsigned int kFrames = 10;
|
||||
|
||||
typedef std::tr1::tuple<const char *, const unsigned int,
|
||||
const vpx_img_fmt, const char *> test_entry_type;
|
||||
|
||||
static const test_entry_type kY4mTestVectors[] = {
|
||||
make_tuple("park_joy_90p_8_420.y4m", 8, VPX_IMG_FMT_I420,
|
||||
"e5406275b9fc6bb3436c31d4a05c1cab"),
|
||||
make_tuple("park_joy_90p_8_422.y4m", 8, VPX_IMG_FMT_I422,
|
||||
"284a47a47133b12884ec3a14e959a0b6"),
|
||||
make_tuple("park_joy_90p_8_444.y4m", 8, VPX_IMG_FMT_I444,
|
||||
"90517ff33843d85de712fd4fe60dbed0"),
|
||||
make_tuple("park_joy_90p_10_420.y4m", 10, VPX_IMG_FMT_I42016,
|
||||
"63f21f9f717d8b8631bd2288ee87137b"),
|
||||
make_tuple("park_joy_90p_10_422.y4m", 10, VPX_IMG_FMT_I42216,
|
||||
"48ab51fb540aed07f7ff5af130c9b605"),
|
||||
make_tuple("park_joy_90p_10_444.y4m", 10, VPX_IMG_FMT_I44416,
|
||||
"067bfd75aa85ff9bae91fa3e0edd1e3e"),
|
||||
make_tuple("park_joy_90p_12_420.y4m", 12, VPX_IMG_FMT_I42016,
|
||||
"9e6d8f6508c6e55625f6b697bc461cef"),
|
||||
make_tuple("park_joy_90p_12_422.y4m", 12, VPX_IMG_FMT_I42216,
|
||||
"b239c6b301c0b835485be349ca83a7e3"),
|
||||
make_tuple("park_joy_90p_12_444.y4m", 12, VPX_IMG_FMT_I44416,
|
||||
"5a6481a550821dab6d0192f5c63845e9")
|
||||
};
|
||||
|
||||
static void write_image_file(const vpx_image_t *img, FILE *file) {
|
||||
int plane, y;
|
||||
for (plane = 0; plane < 3; ++plane) {
|
||||
const unsigned char *buf = img->planes[plane];
|
||||
const int stride = img->stride[plane];
|
||||
const int bytes_per_sample = (img->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
|
||||
const int h = (plane ? (img->d_h + img->y_chroma_shift) >>
|
||||
img->y_chroma_shift : img->d_h);
|
||||
const int w = (plane ? (img->d_w + img->x_chroma_shift) >>
|
||||
img->x_chroma_shift : img->d_w);
|
||||
for (y = 0; y < h; ++y) {
|
||||
fwrite(buf, bytes_per_sample, w, file);
|
||||
buf += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Y4mVideoSourceTest
|
||||
: public ::testing::TestWithParam<test_entry_type>,
|
||||
public ::libvpx_test::Y4mVideoSource {
|
||||
protected:
|
||||
Y4mVideoSourceTest() : Y4mVideoSource("", 0, 0) {}
|
||||
|
||||
virtual ~Y4mVideoSourceTest() {
|
||||
CloseSource();
|
||||
}
|
||||
|
||||
virtual void Init(const std::string &file_name, int limit) {
|
||||
file_name_ = file_name;
|
||||
start_ = 0;
|
||||
limit_ = limit;
|
||||
frame_ = 0;
|
||||
Begin();
|
||||
}
|
||||
|
||||
// Checks y4m header information
|
||||
void HeaderChecks(unsigned int bit_depth, vpx_img_fmt_t fmt) {
|
||||
ASSERT_TRUE(input_file_ != NULL);
|
||||
ASSERT_EQ(y4m_.pic_w, (int)kWidth);
|
||||
ASSERT_EQ(y4m_.pic_h, (int)kHeight);
|
||||
ASSERT_EQ(img()->d_w, kWidth);
|
||||
ASSERT_EQ(img()->d_h, kHeight);
|
||||
ASSERT_EQ(y4m_.bit_depth, bit_depth);
|
||||
ASSERT_EQ(y4m_.vpx_fmt, fmt);
|
||||
if (fmt == VPX_IMG_FMT_I420 || fmt == VPX_IMG_FMT_I42016) {
|
||||
ASSERT_EQ(y4m_.bps, (int)y4m_.bit_depth * 3 / 2);
|
||||
ASSERT_EQ(img()->x_chroma_shift, 1U);
|
||||
ASSERT_EQ(img()->y_chroma_shift, 1U);
|
||||
}
|
||||
if (fmt == VPX_IMG_FMT_I422 || fmt == VPX_IMG_FMT_I42216) {
|
||||
ASSERT_EQ(y4m_.bps, (int)y4m_.bit_depth * 2);
|
||||
ASSERT_EQ(img()->x_chroma_shift, 1U);
|
||||
ASSERT_EQ(img()->y_chroma_shift, 0U);
|
||||
}
|
||||
if (fmt == VPX_IMG_FMT_I444 || fmt == VPX_IMG_FMT_I44416) {
|
||||
ASSERT_EQ(y4m_.bps, (int)y4m_.bit_depth * 3);
|
||||
ASSERT_EQ(img()->x_chroma_shift, 0U);
|
||||
ASSERT_EQ(img()->y_chroma_shift, 0U);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks MD5 of the raw frame data
|
||||
void Md5Check(const string &expected_md5) {
|
||||
ASSERT_TRUE(input_file_ != NULL);
|
||||
libvpx_test::MD5 md5;
|
||||
for (unsigned int i = start_; i < limit_; i++) {
|
||||
md5.Add(img());
|
||||
Next();
|
||||
}
|
||||
ASSERT_EQ(string(md5.Get()), expected_md5);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(Y4mVideoSourceTest, SourceTest) {
|
||||
const char *filename = GET_PARAM(0);
|
||||
const unsigned int bit_depth = GET_PARAM(1);
|
||||
const vpx_img_fmt format = GET_PARAM(2);
|
||||
const char *md5raw = GET_PARAM(3);
|
||||
|
||||
Init(filename, kFrames);
|
||||
HeaderChecks(bit_depth, format);
|
||||
Md5Check(md5raw);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, Y4mVideoSourceTest,
|
||||
::testing::ValuesIn(kY4mTestVectors));
|
||||
|
||||
class Y4mVideoWriteTest
|
||||
: public Y4mVideoSourceTest {
|
||||
protected:
|
||||
Y4mVideoWriteTest() : Y4mVideoSourceTest() {}
|
||||
|
||||
virtual void ReplaceInputFp(FILE *input_file) {
|
||||
CloseSource();
|
||||
frame_ = 0;
|
||||
input_file_ = input_file;
|
||||
rewind(input_file_);
|
||||
ReadSourceToStart();
|
||||
}
|
||||
|
||||
// Writes out a y4m file and then reads it back
|
||||
void WriteY4mAndReadBack() {
|
||||
ASSERT_TRUE(input_file_ != NULL);
|
||||
char buf[Y4M_BUFFER_SIZE] = {0};
|
||||
const struct VpxRational framerate = {y4m_.fps_n, y4m_.fps_d};
|
||||
FILE *out_file = libvpx_test::OpenTempOutFile();
|
||||
ASSERT_TRUE(out_file != NULL);
|
||||
y4m_write_file_header(buf, sizeof(buf),
|
||||
kWidth, kHeight,
|
||||
&framerate, y4m_.vpx_fmt,
|
||||
y4m_.bit_depth);
|
||||
fputs(buf, out_file);
|
||||
for (unsigned int i = start_; i < limit_; i++) {
|
||||
y4m_write_frame_header(buf, sizeof(buf));
|
||||
fputs(buf, out_file);
|
||||
write_image_file(img(), out_file);
|
||||
Next();
|
||||
}
|
||||
ReplaceInputFp(out_file);
|
||||
}
|
||||
|
||||
virtual void Init(const std::string &file_name, int limit) {
|
||||
Y4mVideoSourceTest::Init(file_name, limit);
|
||||
WriteY4mAndReadBack();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(Y4mVideoWriteTest, WriteTest) {
|
||||
const char *filename = GET_PARAM(0);
|
||||
const unsigned int bit_depth = GET_PARAM(1);
|
||||
const vpx_img_fmt format = GET_PARAM(2);
|
||||
const char *md5raw = GET_PARAM(3);
|
||||
|
||||
Init(filename, kFrames);
|
||||
HeaderChecks(bit_depth, format);
|
||||
Md5Check(md5raw);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(C, Y4mVideoWriteTest,
|
||||
::testing::ValuesIn(kY4mTestVectors));
|
||||
|
||||
} // namespace
|
@@ -38,28 +38,22 @@ class Y4mVideoSource : public VideoSource {
|
||||
CloseSource();
|
||||
}
|
||||
|
||||
virtual void OpenSource() {
|
||||
virtual void Begin() {
|
||||
CloseSource();
|
||||
input_file_ = OpenTestDataFile(file_name_);
|
||||
ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
|
||||
<< file_name_;
|
||||
}
|
||||
<< file_name_;
|
||||
|
||||
virtual void ReadSourceToStart() {
|
||||
ASSERT_TRUE(input_file_ != NULL);
|
||||
ASSERT_FALSE(y4m_input_open(&y4m_, input_file_, NULL, 0, 0));
|
||||
y4m_input_open(&y4m_, input_file_, NULL, 0, 0);
|
||||
framerate_numerator_ = y4m_.fps_n;
|
||||
framerate_denominator_ = y4m_.fps_d;
|
||||
|
||||
frame_ = 0;
|
||||
for (unsigned int i = 0; i < start_; i++) {
|
||||
Next();
|
||||
Next();
|
||||
}
|
||||
FillFrame();
|
||||
}
|
||||
|
||||
virtual void Begin() {
|
||||
OpenSource();
|
||||
ReadSourceToStart();
|
||||
FillFrame();
|
||||
}
|
||||
|
||||
virtual void Next() {
|
||||
|
@@ -90,7 +90,6 @@ struct VpxInputContext {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
vpx_img_fmt_t fmt;
|
||||
vpx_bit_depth_t bit_depth;
|
||||
int only_i420;
|
||||
uint32_t fourcc;
|
||||
struct VpxRational framerate;
|
||||
|
@@ -393,12 +393,12 @@ void vp8_de_noise(VP8_COMMON *cm,
|
||||
int low_var_thresh,
|
||||
int flag)
|
||||
{
|
||||
int mbr;
|
||||
double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
|
||||
int ppl = (int)(level + .5);
|
||||
int mb_rows = cm->mb_rows;
|
||||
int mb_cols = cm->mb_cols;
|
||||
int mb_rows = source->y_width >> 4;
|
||||
int mb_cols = source->y_height >> 4;
|
||||
unsigned char *limits = cm->pp_limits_buffer;;
|
||||
int mbr, mbc;
|
||||
(void) post;
|
||||
(void) low_var_thresh;
|
||||
(void) flag;
|
||||
|
@@ -552,9 +552,6 @@ $vp8_yv12_copy_partial_frame_neon_asm=vp8_yv12_copy_partial_frame_neon;
|
||||
if (vpx_config("CONFIG_TEMPORAL_DENOISING") eq "yes") {
|
||||
add_proto qw/int vp8_denoiser_filter/, "unsigned char *mc_running_avg_y, int mc_avg_y_stride, unsigned char *running_avg_y, int avg_y_stride, unsigned char *sig, int sig_stride, unsigned int motion_magnitude, int increase_denoising";
|
||||
specialize qw/vp8_denoiser_filter sse2 neon/;
|
||||
add_proto qw/int vp8_denoiser_filter_uv/, "unsigned char *mc_running_avg, int mc_avg_stride, unsigned char *running_avg, int avg_stride, unsigned char *sig, int sig_stride, unsigned int motion_magnitude, int increase_denoising";
|
||||
specialize qw/vp8_denoiser_filter_uv sse2/;
|
||||
|
||||
}
|
||||
|
||||
# End of encoder only functions
|
||||
|
@@ -18,18 +18,18 @@ extern "C" {
|
||||
|
||||
#if HAVE_EDSP
|
||||
void vp8cx_pack_tokens_armv5(vp8_writer *w, const TOKENEXTRA *p, int xcount,
|
||||
vp8_token *,
|
||||
const vp8_token *,
|
||||
const vp8_extra_bit_struct *,
|
||||
const vp8_tree_index *);
|
||||
void vp8cx_pack_tokens_into_partitions_armv5(VP8_COMP *,
|
||||
unsigned char * cx_data,
|
||||
const unsigned char *cx_data_end,
|
||||
int num_parts,
|
||||
vp8_token *,
|
||||
const vp8_token *,
|
||||
const vp8_extra_bit_struct *,
|
||||
const vp8_tree_index *);
|
||||
void vp8cx_pack_mb_row_tokens_armv5(VP8_COMP *cpi, vp8_writer *w,
|
||||
vp8_token *,
|
||||
const vp8_token *,
|
||||
const vp8_extra_bit_struct *,
|
||||
const vp8_tree_index *);
|
||||
# define pack_tokens(a,b,c) \
|
||||
|
@@ -191,148 +191,6 @@ int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride,
|
||||
return FILTER_BLOCK;
|
||||
}
|
||||
|
||||
int vp8_denoiser_filter_uv_c(unsigned char *mc_running_avg_uv,
|
||||
int mc_avg_uv_stride,
|
||||
unsigned char *running_avg_uv,
|
||||
int avg_uv_stride,
|
||||
unsigned char *sig,
|
||||
int sig_stride,
|
||||
unsigned int motion_magnitude,
|
||||
int increase_denoising) {
|
||||
unsigned char *running_avg_uv_start = running_avg_uv;
|
||||
unsigned char *sig_start = sig;
|
||||
int sum_diff_thresh;
|
||||
int r, c;
|
||||
int sum_diff = 0;
|
||||
int sum_block = 0;
|
||||
int adj_val[3] = {3, 4, 6};
|
||||
int shift_inc1 = 0;
|
||||
int shift_inc2 = 1;
|
||||
/* If motion_magnitude is small, making the denoiser more aggressive by
|
||||
* increasing the adjustment for each level. Add another increment for
|
||||
* blocks that are labeled for increase denoising. */
|
||||
if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) {
|
||||
if (increase_denoising) {
|
||||
shift_inc1 = 1;
|
||||
shift_inc2 = 2;
|
||||
}
|
||||
adj_val[0] += shift_inc2;
|
||||
adj_val[1] += shift_inc2;
|
||||
adj_val[2] += shift_inc2;
|
||||
}
|
||||
|
||||
// Avoid denoising color signal if its close to average level.
|
||||
for (r = 0; r < 8; ++r) {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
sum_block += sig[c];
|
||||
}
|
||||
sig += sig_stride;
|
||||
}
|
||||
if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
|
||||
sig -= sig_stride * 8;
|
||||
for (r = 0; r < 8; ++r) {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
int diff = 0;
|
||||
int adjustment = 0;
|
||||
int absdiff = 0;
|
||||
|
||||
diff = mc_running_avg_uv[c] - sig[c];
|
||||
absdiff = abs(diff);
|
||||
|
||||
// When |diff| <= |3 + shift_inc1|, use pixel value from
|
||||
// last denoised raw.
|
||||
if (absdiff <= 3 + shift_inc1) {
|
||||
running_avg_uv[c] = mc_running_avg_uv[c];
|
||||
sum_diff += diff;
|
||||
} else {
|
||||
if (absdiff >= 4 && absdiff <= 7)
|
||||
adjustment = adj_val[0];
|
||||
else if (absdiff >= 8 && absdiff <= 15)
|
||||
adjustment = adj_val[1];
|
||||
else
|
||||
adjustment = adj_val[2];
|
||||
if (diff > 0) {
|
||||
if ((sig[c] + adjustment) > 255)
|
||||
running_avg_uv[c] = 255;
|
||||
else
|
||||
running_avg_uv[c] = sig[c] + adjustment;
|
||||
sum_diff += adjustment;
|
||||
} else {
|
||||
if ((sig[c] - adjustment) < 0)
|
||||
running_avg_uv[c] = 0;
|
||||
else
|
||||
running_avg_uv[c] = sig[c] - adjustment;
|
||||
sum_diff -= adjustment;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Update pointers for next iteration. */
|
||||
sig += sig_stride;
|
||||
mc_running_avg_uv += mc_avg_uv_stride;
|
||||
running_avg_uv += avg_uv_stride;
|
||||
}
|
||||
|
||||
sum_diff_thresh= SUM_DIFF_THRESHOLD_UV;
|
||||
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
|
||||
if (abs(sum_diff) > sum_diff_thresh) {
|
||||
// Before returning to copy the block (i.e., apply no denoising), check
|
||||
// if we can still apply some (weaker) temporal filtering to this block,
|
||||
// that would otherwise not be denoised at all. Simplest is to apply
|
||||
// an additional adjustment to running_avg_y to bring it closer to sig.
|
||||
// The adjustment is capped by a maximum delta, and chosen such that
|
||||
// in most cases the resulting sum_diff will be within the
|
||||
// accceptable range given by sum_diff_thresh.
|
||||
|
||||
// The delta is set by the excess of absolute pixel diff over threshold.
|
||||
int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
|
||||
// Only apply the adjustment for max delta up to 3.
|
||||
if (delta < 4) {
|
||||
sig -= sig_stride * 8;
|
||||
mc_running_avg_uv -= mc_avg_uv_stride * 8;
|
||||
running_avg_uv -= avg_uv_stride * 8;
|
||||
for (r = 0; r < 8; ++r) {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
int diff = mc_running_avg_uv[c] - sig[c];
|
||||
int adjustment = abs(diff);
|
||||
if (adjustment > delta)
|
||||
adjustment = delta;
|
||||
if (diff > 0) {
|
||||
// Bring denoised signal down.
|
||||
if (running_avg_uv[c] - adjustment < 0)
|
||||
running_avg_uv[c] = 0;
|
||||
else
|
||||
running_avg_uv[c] = running_avg_uv[c] - adjustment;
|
||||
sum_diff -= adjustment;
|
||||
} else if (diff < 0) {
|
||||
// Bring denoised signal up.
|
||||
if (running_avg_uv[c] + adjustment > 255)
|
||||
running_avg_uv[c] = 255;
|
||||
else
|
||||
running_avg_uv[c] = running_avg_uv[c] + adjustment;
|
||||
sum_diff += adjustment;
|
||||
}
|
||||
}
|
||||
// TODO(marpan): Check here if abs(sum_diff) has gone below the
|
||||
// threshold sum_diff_thresh, and if so, we can exit the row loop.
|
||||
sig += sig_stride;
|
||||
mc_running_avg_uv += mc_avg_uv_stride;
|
||||
running_avg_uv += avg_uv_stride;
|
||||
}
|
||||
if (abs(sum_diff) > sum_diff_thresh)
|
||||
return COPY_BLOCK;
|
||||
} else {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
vp8_copy_mem8x8(running_avg_uv_start, avg_uv_stride, sig_start,
|
||||
sig_stride);
|
||||
return FILTER_BLOCK;
|
||||
}
|
||||
|
||||
int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
|
||||
int num_mb_rows, int num_mb_cols)
|
||||
{
|
||||
@@ -383,7 +241,6 @@ void vp8_denoiser_free(VP8_DENOISER *denoiser)
|
||||
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]);
|
||||
}
|
||||
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
|
||||
vpx_free(denoiser->denoise_state);
|
||||
}
|
||||
|
||||
|
||||
@@ -403,8 +260,6 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
|
||||
unsigned int motion_magnitude2;
|
||||
unsigned int sse_thresh;
|
||||
int sse_diff_thresh = 0;
|
||||
// Denoise the UV channel.
|
||||
int apply_color_denoise = 0;
|
||||
// Spatial loop filter: only applied selectively based on
|
||||
// temporal filter state of block relative to top/left neighbors.
|
||||
int apply_spatial_loop_filter = 1;
|
||||
@@ -412,8 +267,6 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
|
||||
MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame;
|
||||
|
||||
enum vp8_denoiser_decision decision = FILTER_BLOCK;
|
||||
enum vp8_denoiser_decision decision_u = FILTER_BLOCK;
|
||||
enum vp8_denoiser_decision decision_v = FILTER_BLOCK;
|
||||
|
||||
if (zero_frame)
|
||||
{
|
||||
@@ -523,37 +376,11 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
|
||||
|
||||
/* Filter. */
|
||||
decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride,
|
||||
running_avg_y, avg_y_stride,
|
||||
x->thismb, 16, motion_magnitude2,
|
||||
x->increase_denoising);
|
||||
running_avg_y, avg_y_stride,
|
||||
x->thismb, 16, motion_magnitude2,
|
||||
x->increase_denoising);
|
||||
denoiser->denoise_state[block_index] = motion_magnitude2 > 0 ?
|
||||
kFilterNonZeroMV : kFilterZeroMV;
|
||||
// Only denoise UV for zero motion, and if y channel was denoised.
|
||||
if (apply_color_denoise &&
|
||||
motion_magnitude2 == 0 &&
|
||||
decision == FILTER_BLOCK) {
|
||||
unsigned char *mc_running_avg_u =
|
||||
denoiser->yv12_mc_running_avg.u_buffer + recon_uvoffset;
|
||||
unsigned char *running_avg_u =
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset;
|
||||
unsigned char *mc_running_avg_v =
|
||||
denoiser->yv12_mc_running_avg.v_buffer + recon_uvoffset;
|
||||
unsigned char *running_avg_v =
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset;
|
||||
int mc_avg_uv_stride = denoiser->yv12_mc_running_avg.uv_stride;
|
||||
int avg_uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
|
||||
int signal_stride = x->block[16].src_stride;
|
||||
decision_u =
|
||||
vp8_denoiser_filter_uv(mc_running_avg_u, mc_avg_uv_stride,
|
||||
running_avg_u, avg_uv_stride,
|
||||
x->block[16].src + *x->block[16].base_src,
|
||||
signal_stride, motion_magnitude2, 0);
|
||||
decision_v =
|
||||
vp8_denoiser_filter_uv(mc_running_avg_v, mc_avg_uv_stride,
|
||||
running_avg_v, avg_uv_stride,
|
||||
x->block[20].src + *x->block[20].base_src,
|
||||
signal_stride, motion_magnitude2, 0);
|
||||
}
|
||||
}
|
||||
if (decision == COPY_BLOCK)
|
||||
{
|
||||
@@ -566,21 +393,7 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].y_stride);
|
||||
denoiser->denoise_state[block_index] = kNoFilter;
|
||||
}
|
||||
if (apply_color_denoise) {
|
||||
if (decision_u == COPY_BLOCK) {
|
||||
vp8_copy_mem8x8(
|
||||
x->block[16].src + *x->block[16].base_src, x->block[16].src_stride,
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset,
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
|
||||
}
|
||||
if (decision_v == COPY_BLOCK) {
|
||||
vp8_copy_mem8x8(
|
||||
x->block[20].src + *x->block[20].base_src, x->block[16].src_stride,
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset,
|
||||
denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
|
||||
}
|
||||
}
|
||||
// Option to selectively deblock the denoised signal, for y channel only.
|
||||
// Option to selectively deblock the denoised signal.
|
||||
if (apply_spatial_loop_filter) {
|
||||
loop_filter_info lfi;
|
||||
int apply_filter_col = 0;
|
||||
|
@@ -22,11 +22,6 @@ extern "C" {
|
||||
#define SUM_DIFF_THRESHOLD_HIGH (16 * 16 * 3)
|
||||
#define MOTION_MAGNITUDE_THRESHOLD (8*3)
|
||||
|
||||
#define SUM_DIFF_THRESHOLD_UV (96) // (8 * 8 * 1.5)
|
||||
#define SUM_DIFF_THRESHOLD_HIGH_UV (8 * 8 * 2)
|
||||
#define SUM_DIFF_FROM_AVG_THRESH_UV (8 * 8 * 4)
|
||||
#define MOTION_MAGNITUDE_THRESHOLD_UV (8*3)
|
||||
|
||||
enum vp8_denoiser_decision
|
||||
{
|
||||
COPY_BLOCK,
|
||||
|
@@ -17,23 +17,10 @@
|
||||
#include <emmintrin.h>
|
||||
#include "vpx_ports/emmintrin_compat.h"
|
||||
|
||||
/* Compute the sum of all pixel differences of this MB. */
|
||||
static INLINE unsigned int abs_sum_diff_16x1(__m128i acc_diff) {
|
||||
const __m128i k_1 = _mm_set1_epi16(1);
|
||||
const __m128i acc_diff_lo = _mm_srai_epi16(
|
||||
_mm_unpacklo_epi8(acc_diff, acc_diff), 8);
|
||||
const __m128i acc_diff_hi = _mm_srai_epi16(
|
||||
_mm_unpackhi_epi8(acc_diff, acc_diff), 8);
|
||||
const __m128i acc_diff_16 = _mm_add_epi16(acc_diff_lo, acc_diff_hi);
|
||||
const __m128i hg_fe_dc_ba = _mm_madd_epi16(acc_diff_16, k_1);
|
||||
const __m128i hgfe_dcba = _mm_add_epi32(hg_fe_dc_ba,
|
||||
_mm_srli_si128(hg_fe_dc_ba, 8));
|
||||
const __m128i hgfedcba = _mm_add_epi32(hgfe_dcba,
|
||||
_mm_srli_si128(hgfe_dcba, 4));
|
||||
unsigned int sum_diff = _mm_cvtsi128_si32(hgfedcba);
|
||||
|
||||
return abs(sum_diff);
|
||||
}
|
||||
union sum_union {
|
||||
__m128i v;
|
||||
signed char e[16];
|
||||
};
|
||||
|
||||
int vp8_denoiser_filter_sse2(unsigned char *mc_running_avg_y,
|
||||
int mc_avg_y_stride,
|
||||
@@ -44,7 +31,7 @@ int vp8_denoiser_filter_sse2(unsigned char *mc_running_avg_y,
|
||||
{
|
||||
unsigned char *running_avg_y_start = running_avg_y;
|
||||
unsigned char *sig_start = sig;
|
||||
unsigned int sum_diff_thresh;
|
||||
int sum_diff_thresh;
|
||||
int r;
|
||||
int shift_inc = (increase_denoising &&
|
||||
motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) ? 1 : 0;
|
||||
@@ -116,10 +103,16 @@ int vp8_denoiser_filter_sse2(unsigned char *mc_running_avg_y,
|
||||
|
||||
{
|
||||
/* Compute the sum of all pixel differences of this MB. */
|
||||
unsigned int abs_sum_diff = abs_sum_diff_16x1(acc_diff);
|
||||
union sum_union s;
|
||||
int sum_diff = 0;
|
||||
s.v = acc_diff;
|
||||
sum_diff = s.e[0] + s.e[1] + s.e[2] + s.e[3] + s.e[4] + s.e[5]
|
||||
+ s.e[6] + s.e[7] + s.e[8] + s.e[9] + s.e[10] + s.e[11]
|
||||
+ s.e[12] + s.e[13] + s.e[14] + s.e[15];
|
||||
|
||||
sum_diff_thresh = SUM_DIFF_THRESHOLD;
|
||||
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH;
|
||||
if (abs_sum_diff > sum_diff_thresh) {
|
||||
if (abs(sum_diff) > sum_diff_thresh) {
|
||||
// Before returning to copy the block (i.e., apply no denoising),
|
||||
// checK if we can still apply some (weaker) temporal filtering to
|
||||
// this block, that would otherwise not be denoised at all. Simplest
|
||||
@@ -130,7 +123,7 @@ int vp8_denoiser_filter_sse2(unsigned char *mc_running_avg_y,
|
||||
|
||||
// The delta is set by the excess of absolute pixel diff over the
|
||||
// threshold.
|
||||
int delta = ((abs_sum_diff - sum_diff_thresh) >> 8) + 1;
|
||||
int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
|
||||
// Only apply the adjustment for max delta up to 3.
|
||||
if (delta < 4) {
|
||||
const __m128i k_delta = _mm_set1_epi8(delta);
|
||||
@@ -169,9 +162,16 @@ int vp8_denoiser_filter_sse2(unsigned char *mc_running_avg_y,
|
||||
mc_running_avg_y += mc_avg_y_stride;
|
||||
running_avg_y += avg_y_stride;
|
||||
}
|
||||
abs_sum_diff = abs_sum_diff_16x1(acc_diff);
|
||||
if (abs_sum_diff > sum_diff_thresh) {
|
||||
return COPY_BLOCK;
|
||||
{
|
||||
// Update the sum of all pixel differences of this MB.
|
||||
union sum_union s;
|
||||
s.v = acc_diff;
|
||||
sum_diff = s.e[0] + s.e[1] + s.e[2] + s.e[3] + s.e[4] + s.e[5]
|
||||
+ s.e[6] + s.e[7] + s.e[8] + s.e[9] + s.e[10] + s.e[11]
|
||||
+ s.e[12] + s.e[13] + s.e[14] + s.e[15];
|
||||
if (abs(sum_diff) > sum_diff_thresh) {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return COPY_BLOCK;
|
||||
@@ -182,198 +182,3 @@ int vp8_denoiser_filter_sse2(unsigned char *mc_running_avg_y,
|
||||
vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride);
|
||||
return FILTER_BLOCK;
|
||||
}
|
||||
|
||||
int vp8_denoiser_filter_uv_sse2(unsigned char *mc_running_avg,
|
||||
int mc_avg_stride,
|
||||
unsigned char *running_avg, int avg_stride,
|
||||
unsigned char *sig, int sig_stride,
|
||||
unsigned int motion_magnitude,
|
||||
int increase_denoising) {
|
||||
unsigned char *running_avg_start = running_avg;
|
||||
unsigned char *sig_start = sig;
|
||||
unsigned int sum_diff_thresh;
|
||||
int r;
|
||||
int shift_inc = (increase_denoising &&
|
||||
motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) ? 1 : 0;
|
||||
__m128i acc_diff = _mm_setzero_si128();
|
||||
const __m128i k_0 = _mm_setzero_si128();
|
||||
const __m128i k_4 = _mm_set1_epi8(4 + shift_inc);
|
||||
const __m128i k_8 = _mm_set1_epi8(8);
|
||||
const __m128i k_16 = _mm_set1_epi8(16);
|
||||
/* Modify each level's adjustment according to motion_magnitude. */
|
||||
const __m128i l3 = _mm_set1_epi8(
|
||||
(motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) ?
|
||||
7 + shift_inc : 6);
|
||||
/* Difference between level 3 and level 2 is 2. */
|
||||
const __m128i l32 = _mm_set1_epi8(2);
|
||||
/* Difference between level 2 and level 1 is 1. */
|
||||
const __m128i l21 = _mm_set1_epi8(1);
|
||||
|
||||
{
|
||||
const __m128i k_1 = _mm_set1_epi16(1);
|
||||
__m128i vec_sum_block = _mm_setzero_si128();
|
||||
|
||||
// Avoid denoising color signal if its close to average level.
|
||||
for (r = 0; r < 8; ++r) {
|
||||
const __m128i v_sig = _mm_loadl_epi64((__m128i *)(&sig[0]));
|
||||
const __m128i v_sig_unpack = _mm_unpacklo_epi8(v_sig, k_0);
|
||||
vec_sum_block = _mm_add_epi16(vec_sum_block, v_sig_unpack);
|
||||
sig += sig_stride;
|
||||
}
|
||||
sig -= sig_stride * 8;
|
||||
{
|
||||
const __m128i hg_fe_dc_ba = _mm_madd_epi16(vec_sum_block, k_1);
|
||||
const __m128i hgfe_dcba = _mm_add_epi32(hg_fe_dc_ba,
|
||||
_mm_srli_si128(hg_fe_dc_ba, 8));
|
||||
const __m128i hgfedcba = _mm_add_epi32(hgfe_dcba,
|
||||
_mm_srli_si128(hgfe_dcba, 4));
|
||||
const int sum_block = _mm_cvtsi128_si32(hgfedcba);
|
||||
if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (r = 0; r < 4; ++r) {
|
||||
/* Calculate differences */
|
||||
const __m128i v_sig_low = _mm_castpd_si128(
|
||||
_mm_load_sd((double *)(&sig[0])));
|
||||
const __m128i v_sig = _mm_castpd_si128(
|
||||
_mm_loadh_pd(_mm_castsi128_pd(v_sig_low),
|
||||
(double *)(&sig[sig_stride])));
|
||||
const __m128i v_mc_running_avg_low = _mm_castpd_si128(
|
||||
_mm_load_sd((double *)(&mc_running_avg[0])));
|
||||
const __m128i v_mc_running_avg = _mm_castpd_si128(
|
||||
_mm_loadh_pd(_mm_castsi128_pd(v_mc_running_avg_low),
|
||||
(double *)(&mc_running_avg[mc_avg_stride])));
|
||||
const __m128i pdiff = _mm_subs_epu8(v_mc_running_avg, v_sig);
|
||||
const __m128i ndiff = _mm_subs_epu8(v_sig, v_mc_running_avg);
|
||||
/* Obtain the sign. FF if diff is negative. */
|
||||
const __m128i diff_sign = _mm_cmpeq_epi8(pdiff, k_0);
|
||||
/* Clamp absolute difference to 16 to be used to get mask. Doing this
|
||||
* allows us to use _mm_cmpgt_epi8, which operates on signed byte. */
|
||||
const __m128i clamped_absdiff = _mm_min_epu8(
|
||||
_mm_or_si128(pdiff, ndiff), k_16);
|
||||
/* Get masks for l2 l1 and l0 adjustments */
|
||||
const __m128i mask2 = _mm_cmpgt_epi8(k_16, clamped_absdiff);
|
||||
const __m128i mask1 = _mm_cmpgt_epi8(k_8, clamped_absdiff);
|
||||
const __m128i mask0 = _mm_cmpgt_epi8(k_4, clamped_absdiff);
|
||||
/* Get adjustments for l2, l1, and l0 */
|
||||
__m128i adj2 = _mm_and_si128(mask2, l32);
|
||||
const __m128i adj1 = _mm_and_si128(mask1, l21);
|
||||
const __m128i adj0 = _mm_and_si128(mask0, clamped_absdiff);
|
||||
__m128i adj, padj, nadj;
|
||||
__m128i v_running_avg;
|
||||
|
||||
/* Combine the adjustments and get absolute adjustments. */
|
||||
adj2 = _mm_add_epi8(adj2, adj1);
|
||||
adj = _mm_sub_epi8(l3, adj2);
|
||||
adj = _mm_andnot_si128(mask0, adj);
|
||||
adj = _mm_or_si128(adj, adj0);
|
||||
|
||||
/* Restore the sign and get positive and negative adjustments. */
|
||||
padj = _mm_andnot_si128(diff_sign, adj);
|
||||
nadj = _mm_and_si128(diff_sign, adj);
|
||||
|
||||
/* Calculate filtered value. */
|
||||
v_running_avg = _mm_adds_epu8(v_sig, padj);
|
||||
v_running_avg = _mm_subs_epu8(v_running_avg, nadj);
|
||||
|
||||
_mm_storel_pd((double *)&running_avg[0],
|
||||
_mm_castsi128_pd(v_running_avg));
|
||||
_mm_storeh_pd((double *)&running_avg[avg_stride],
|
||||
_mm_castsi128_pd(v_running_avg));
|
||||
|
||||
/* Adjustments <=7, and each element in acc_diff can fit in signed
|
||||
* char.
|
||||
*/
|
||||
acc_diff = _mm_adds_epi8(acc_diff, padj);
|
||||
acc_diff = _mm_subs_epi8(acc_diff, nadj);
|
||||
|
||||
/* Update pointers for next iteration. */
|
||||
sig += sig_stride * 2;
|
||||
mc_running_avg += mc_avg_stride * 2;
|
||||
running_avg += avg_stride * 2;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned int abs_sum_diff = abs_sum_diff_16x1(acc_diff);
|
||||
sum_diff_thresh = SUM_DIFF_THRESHOLD_UV;
|
||||
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
|
||||
if (abs_sum_diff > sum_diff_thresh) {
|
||||
// Before returning to copy the block (i.e., apply no denoising),
|
||||
// checK if we can still apply some (weaker) temporal filtering to
|
||||
// this block, that would otherwise not be denoised at all. Simplest
|
||||
// is to apply an additional adjustment to running_avg_y to bring it
|
||||
// closer to sig. The adjustment is capped by a maximum delta, and
|
||||
// chosen such that in most cases the resulting sum_diff will be
|
||||
// within the accceptable range given by sum_diff_thresh.
|
||||
|
||||
// The delta is set by the excess of absolute pixel diff over the
|
||||
// threshold.
|
||||
int delta = ((abs_sum_diff - sum_diff_thresh) >> 8) + 1;
|
||||
// Only apply the adjustment for max delta up to 3.
|
||||
if (delta < 4) {
|
||||
const __m128i k_delta = _mm_set1_epi8(delta);
|
||||
sig -= sig_stride * 8;
|
||||
mc_running_avg -= mc_avg_stride * 8;
|
||||
running_avg -= avg_stride * 8;
|
||||
for (r = 0; r < 4; ++r) {
|
||||
// Calculate differences.
|
||||
const __m128i v_sig_low = _mm_castpd_si128(
|
||||
_mm_load_sd((double *)(&sig[0])));
|
||||
const __m128i v_sig = _mm_castpd_si128(
|
||||
_mm_loadh_pd(_mm_castsi128_pd(v_sig_low),
|
||||
(double *)(&sig[sig_stride])));
|
||||
const __m128i v_mc_running_avg_low = _mm_castpd_si128(
|
||||
_mm_load_sd((double *)(&mc_running_avg[0])));
|
||||
const __m128i v_mc_running_avg = _mm_castpd_si128(
|
||||
_mm_loadh_pd(_mm_castsi128_pd(v_mc_running_avg_low),
|
||||
(double *)(&mc_running_avg[mc_avg_stride])));
|
||||
const __m128i pdiff = _mm_subs_epu8(v_mc_running_avg, v_sig);
|
||||
const __m128i ndiff = _mm_subs_epu8(v_sig, v_mc_running_avg);
|
||||
// Obtain the sign. FF if diff is negative.
|
||||
const __m128i diff_sign = _mm_cmpeq_epi8(pdiff, k_0);
|
||||
// Clamp absolute difference to delta to get the adjustment.
|
||||
const __m128i adj =
|
||||
_mm_min_epu8(_mm_or_si128(pdiff, ndiff), k_delta);
|
||||
// Restore the sign and get positive and negative adjustments.
|
||||
__m128i padj, nadj;
|
||||
const __m128i v_running_avg_low = _mm_castpd_si128(
|
||||
_mm_load_sd((double *)(&running_avg[0])));
|
||||
__m128i v_running_avg = _mm_castpd_si128(
|
||||
_mm_loadh_pd(_mm_castsi128_pd(v_running_avg_low),
|
||||
(double *)(&running_avg[avg_stride])));
|
||||
padj = _mm_andnot_si128(diff_sign, adj);
|
||||
nadj = _mm_and_si128(diff_sign, adj);
|
||||
// Calculate filtered value.
|
||||
v_running_avg = _mm_subs_epu8(v_running_avg, padj);
|
||||
v_running_avg = _mm_adds_epu8(v_running_avg, nadj);
|
||||
|
||||
_mm_storel_pd((double *)&running_avg[0],
|
||||
_mm_castsi128_pd(v_running_avg));
|
||||
_mm_storeh_pd((double *)&running_avg[avg_stride],
|
||||
_mm_castsi128_pd(v_running_avg));
|
||||
|
||||
// Accumulate the adjustments.
|
||||
acc_diff = _mm_subs_epi8(acc_diff, padj);
|
||||
acc_diff = _mm_adds_epi8(acc_diff, nadj);
|
||||
|
||||
// Update pointers for next iteration.
|
||||
sig += sig_stride * 2;
|
||||
mc_running_avg += mc_avg_stride * 2;
|
||||
running_avg += avg_stride * 2;
|
||||
}
|
||||
abs_sum_diff = abs_sum_diff_16x1(acc_diff);
|
||||
if (abs_sum_diff > sum_diff_thresh) {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
} else {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vp8_copy_mem8x8(running_avg_start, avg_stride, sig_start, sig_stride);
|
||||
return FILTER_BLOCK;
|
||||
}
|
||||
|
@@ -97,15 +97,14 @@ static void free_mi(VP9_COMMON *cm) {
|
||||
|
||||
void vp9_free_frame_buffers(VP9_COMMON *cm) {
|
||||
int i;
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
|
||||
for (i = 0; i < FRAME_BUFFERS; ++i) {
|
||||
vp9_free_frame_buffer(&pool->frame_bufs[i].buf);
|
||||
vp9_free_frame_buffer(&cm->frame_bufs[i].buf);
|
||||
|
||||
if (pool->frame_bufs[i].ref_count > 0 &&
|
||||
pool->frame_bufs[i].raw_frame_buffer.data != NULL) {
|
||||
pool->release_fb_cb(pool->cb_priv, &pool->frame_bufs[i].raw_frame_buffer);
|
||||
pool->frame_bufs[i].ref_count = 0;
|
||||
if (cm->frame_bufs[i].ref_count > 0 &&
|
||||
cm->frame_bufs[i].raw_frame_buffer.data != NULL) {
|
||||
cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[i].raw_frame_buffer);
|
||||
cm->frame_bufs[i].ref_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,15 +127,12 @@ void vp9_free_context_buffers(VP9_COMMON *cm) {
|
||||
int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) {
|
||||
const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
|
||||
const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
|
||||
#if CONFIG_INTERNAL_STATS || CONFIG_VP9_POSTPROC
|
||||
const int ss_x = cm->subsampling_x;
|
||||
const int ss_y = cm->subsampling_y;
|
||||
|
||||
// TODO(agrange): this should be conditionally allocated.
|
||||
if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
|
||||
VP9_DEC_BORDER_IN_PIXELS, NULL, NULL, NULL) < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
set_mb_mi(cm, aligned_width, aligned_height);
|
||||
|
||||
@@ -177,14 +173,13 @@ int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) {
|
||||
|
||||
static void init_frame_bufs(VP9_COMMON *cm) {
|
||||
int i;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
cm->new_fb_idx = FRAME_BUFFERS - 1;
|
||||
frame_bufs[cm->new_fb_idx].ref_count = 1;
|
||||
cm->frame_bufs[cm->new_fb_idx].ref_count = 1;
|
||||
|
||||
for (i = 0; i < REF_FRAMES; ++i) {
|
||||
cm->ref_frame_map[i] = i;
|
||||
frame_bufs[i].ref_count = 1;
|
||||
cm->frame_bufs[i].ref_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,24 +187,21 @@ int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) {
|
||||
int i;
|
||||
const int ss_x = cm->subsampling_x;
|
||||
const int ss_y = cm->subsampling_y;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
vp9_free_frame_buffers(cm);
|
||||
|
||||
for (i = 0; i < FRAME_BUFFERS; ++i) {
|
||||
frame_bufs[i].ref_count = 0;
|
||||
if (vp9_alloc_frame_buffer(&frame_bufs[i].buf, width, height,
|
||||
cm->frame_bufs[i].ref_count = 0;
|
||||
if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height,
|
||||
ss_x, ss_y, VP9_ENC_BORDER_IN_PIXELS) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
init_frame_bufs(cm);
|
||||
|
||||
#if CONFIG_INTERNAL_STATS || CONFIG_VP9_POSTPROC
|
||||
if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
|
||||
VP9_ENC_BORDER_IN_PIXELS) < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -259,7 +251,7 @@ int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
|
||||
void vp9_remove_common(VP9_COMMON *cm) {
|
||||
vp9_free_frame_buffers(cm);
|
||||
vp9_free_context_buffers(cm);
|
||||
vp9_free_internal_frame_buffers(&cm->buffer_pool->int_frame_buffers);
|
||||
vp9_free_internal_frame_buffers(&cm->int_frame_buffers);
|
||||
}
|
||||
|
||||
void vp9_update_frame_size(VP9_COMMON *cm) {
|
||||
|
@@ -44,7 +44,7 @@ void vp9_foreach_transformed_block_in_plane(
|
||||
// block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
|
||||
// 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
|
||||
// transform size varies per plane, look it up in a common way.
|
||||
const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd)
|
||||
const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi)
|
||||
: mbmi->tx_size;
|
||||
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
|
||||
|
@@ -32,6 +32,9 @@ extern "C" {
|
||||
#define BLOCK_SIZE_GROUPS 4
|
||||
#define SKIP_CONTEXTS 3
|
||||
#define INTER_MODE_CONTEXTS 7
|
||||
#if CONFIG_COPY_CODING
|
||||
#define COPY_MODE_CONTEXTS 5
|
||||
#endif
|
||||
|
||||
/* Segment Feature Masks */
|
||||
#define MAX_MV_REF_CANDIDATES 2
|
||||
@@ -79,6 +82,16 @@ typedef enum {
|
||||
MB_MODE_COUNT
|
||||
} PREDICTION_MODE;
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
typedef enum {
|
||||
NOREF,
|
||||
REF0,
|
||||
REF1,
|
||||
REF2,
|
||||
COPY_MODE_COUNT
|
||||
} COPY_MODE;
|
||||
#endif
|
||||
|
||||
static INLINE int is_inter_mode(PREDICTION_MODE mode) {
|
||||
return mode >= NEARESTMV && mode <= NEWMV;
|
||||
}
|
||||
@@ -118,11 +131,86 @@ static INLINE int mi_width_log2(BLOCK_SIZE sb_type) {
|
||||
return mi_width_log2_lookup[sb_type];
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static INLINE TX_SIZE bsize_to_tx_size(BLOCK_SIZE bsize) {
|
||||
const TX_SIZE tx_size_lookup[BLOCK_SIZES] = {
|
||||
TX_4X4, TX_4X4, TX_4X4,
|
||||
TX_8X8, TX_8X8, TX_8X8,
|
||||
TX_16X16, TX_16X16, TX_16X16,
|
||||
TX_32X32, TX_32X32, TX_32X32, TX_32X32};
|
||||
return tx_size_lookup[bsize];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
#define MASK_BITS_SML 3
|
||||
#define MASK_BITS_MED 4
|
||||
#define MASK_BITS_BIG 5
|
||||
#define MASK_NONE -1
|
||||
|
||||
static inline int get_mask_bits(BLOCK_SIZE sb_type) {
|
||||
if (sb_type < BLOCK_8X8)
|
||||
return 0;
|
||||
if (sb_type <= BLOCK_8X8)
|
||||
return MASK_BITS_SML;
|
||||
else if (sb_type <= BLOCK_32X32)
|
||||
return MASK_BITS_MED;
|
||||
else
|
||||
return MASK_BITS_BIG;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
static INLINE TX_SIZE intra_size_log2_for_interintra(int bs) {
|
||||
switch (bs) {
|
||||
case 4:
|
||||
return TX_4X4;
|
||||
break;
|
||||
case 8:
|
||||
return TX_8X8;
|
||||
break;
|
||||
case 16:
|
||||
return TX_16X16;
|
||||
break;
|
||||
case 32:
|
||||
return TX_32X32;
|
||||
break;
|
||||
default:
|
||||
return TX_32X32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE int is_interintra_allowed(BLOCK_SIZE sb_type) {
|
||||
return ((sb_type >= BLOCK_8X8) && (sb_type < BLOCK_64X64));
|
||||
}
|
||||
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
#define MASK_BITS_SML_INTERINTRA 3
|
||||
#define MASK_BITS_MED_INTERINTRA 4
|
||||
#define MASK_BITS_BIG_INTERINTRA 5
|
||||
#define MASK_NONE_INTERINTRA -1
|
||||
static INLINE int get_mask_bits_interintra(BLOCK_SIZE sb_type) {
|
||||
if (sb_type == BLOCK_4X4)
|
||||
return 0;
|
||||
if (sb_type <= BLOCK_8X8)
|
||||
return MASK_BITS_SML_INTERINTRA;
|
||||
else if (sb_type <= BLOCK_32X32)
|
||||
return MASK_BITS_MED_INTERINTRA;
|
||||
else
|
||||
return MASK_BITS_BIG_INTERINTRA;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This structure now relates to 8x8 block regions.
|
||||
typedef struct {
|
||||
// Common for both INTER and INTRA blocks
|
||||
BLOCK_SIZE sb_type;
|
||||
PREDICTION_MODE mode;
|
||||
#if CONFIG_FILTERINTRA
|
||||
int filterbit, uv_filterbit;
|
||||
#endif
|
||||
TX_SIZE tx_size;
|
||||
uint8_t skip;
|
||||
uint8_t segment_id;
|
||||
@@ -137,10 +225,34 @@ typedef struct {
|
||||
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
|
||||
uint8_t mode_context[MAX_REF_FRAMES];
|
||||
INTERP_FILTER interp_filter;
|
||||
|
||||
#if CONFIG_EXT_TX
|
||||
EXT_TX_TYPE ext_txfrm;
|
||||
#endif
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
int use_masked_interinter;
|
||||
int mask_index;
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
PREDICTION_MODE interintra_mode, interintra_uv_mode;
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
int interintra_mask_index;
|
||||
int interintra_uv_mask_index;
|
||||
int use_masked_interintra;
|
||||
#endif
|
||||
#endif
|
||||
#if CONFIG_COPY_CODING
|
||||
COPY_MODE copy_mode;
|
||||
int inter_ref_count;
|
||||
#endif
|
||||
} MB_MODE_INFO;
|
||||
|
||||
typedef struct {
|
||||
MB_MODE_INFO mbmi;
|
||||
#if CONFIG_FILTERINTRA
|
||||
int b_filter_info[4];
|
||||
#endif
|
||||
b_mode_info bmi[4];
|
||||
} MODE_INFO;
|
||||
|
||||
@@ -149,6 +261,16 @@ static INLINE PREDICTION_MODE get_y_mode(const MODE_INFO *mi, int block) {
|
||||
: mi->mbmi.mode;
|
||||
}
|
||||
|
||||
#if CONFIG_FILTERINTRA
|
||||
static INLINE int is_filter_allowed(PREDICTION_MODE mode) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static INLINE int is_filter_enabled(TX_SIZE txsize) {
|
||||
return (txsize <= TX_32X32);
|
||||
}
|
||||
#endif
|
||||
|
||||
static INLINE int is_inter_block(const MB_MODE_INFO *mbmi) {
|
||||
return mbmi->ref_frame[0] > INTRA_FRAME;
|
||||
}
|
||||
@@ -240,6 +362,13 @@ typedef struct macroblockd {
|
||||
PARTITION_CONTEXT left_seg_context[8];
|
||||
} MACROBLOCKD;
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static INLINE int supertx_enabled(const MB_MODE_INFO *mbmi) {
|
||||
return mbmi->tx_size >
|
||||
MIN(b_width_log2(mbmi->sb_type), b_height_log2(mbmi->sb_type));
|
||||
}
|
||||
#endif
|
||||
|
||||
static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
|
||||
PARTITION_TYPE partition) {
|
||||
const BLOCK_SIZE subsize = subsize_lookup[partition][bsize];
|
||||
@@ -253,8 +382,20 @@ static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type,
|
||||
const MACROBLOCKD *xd) {
|
||||
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||
|
||||
#if !CONFIG_EXT_TX
|
||||
if (plane_type != PLANE_TYPE_Y || is_inter_block(mbmi))
|
||||
return DCT_DCT;
|
||||
#else
|
||||
if (plane_type != PLANE_TYPE_Y)
|
||||
return DCT_DCT;
|
||||
|
||||
if (is_inter_block(mbmi)) {
|
||||
if (mbmi->ext_txfrm == NORM || mbmi->tx_size >= TX_32X32)
|
||||
return DCT_DCT;
|
||||
else
|
||||
return ADST_ADST;
|
||||
}
|
||||
#endif
|
||||
return intra_mode_to_tx_type_lookup[mbmi->mode];
|
||||
}
|
||||
|
||||
@@ -262,28 +403,46 @@ static INLINE TX_TYPE get_tx_type_4x4(PLANE_TYPE plane_type,
|
||||
const MACROBLOCKD *xd, int ib) {
|
||||
const MODE_INFO *const mi = xd->mi[0];
|
||||
|
||||
#if !CONFIG_EXT_TX
|
||||
if (plane_type != PLANE_TYPE_Y || xd->lossless || is_inter_block(&mi->mbmi))
|
||||
return DCT_DCT;
|
||||
#else
|
||||
if (plane_type != PLANE_TYPE_Y || xd->lossless)
|
||||
return DCT_DCT;
|
||||
|
||||
if (is_inter_block(&mi->mbmi)) {
|
||||
if (mi->mbmi.ext_txfrm == NORM)
|
||||
return DCT_DCT;
|
||||
else
|
||||
return ADST_ADST;
|
||||
}
|
||||
#endif
|
||||
|
||||
return intra_mode_to_tx_type_lookup[get_y_mode(mi, ib)];
|
||||
}
|
||||
|
||||
void vp9_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y);
|
||||
|
||||
static INLINE TX_SIZE get_uv_tx_size_impl(TX_SIZE y_tx_size, BLOCK_SIZE bsize,
|
||||
int xss, int yss) {
|
||||
static INLINE TX_SIZE get_uv_tx_size_impl(TX_SIZE y_tx_size, BLOCK_SIZE bsize) {
|
||||
if (bsize < BLOCK_8X8) {
|
||||
return TX_4X4;
|
||||
} else {
|
||||
const BLOCK_SIZE plane_bsize = ss_size_lookup[bsize][xss][yss];
|
||||
// TODO(dkovalev): Assuming YUV420 (ss_x == 1, ss_y == 1)
|
||||
const BLOCK_SIZE plane_bsize = ss_size_lookup[bsize][1][1];
|
||||
return MIN(y_tx_size, max_txsize_lookup[plane_bsize]);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE TX_SIZE get_uv_tx_size(const MB_MODE_INFO *mbmi,
|
||||
const struct macroblockd_plane *pd) {
|
||||
return get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type, pd->subsampling_x,
|
||||
pd->subsampling_y);
|
||||
static INLINE TX_SIZE get_uv_tx_size(const MB_MODE_INFO *mbmi) {
|
||||
#if CONFIG_SUPERTX
|
||||
if (!supertx_enabled(mbmi)) {
|
||||
#endif
|
||||
return get_uv_tx_size_impl(mbmi->tx_size, mbmi->sb_type);
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
return uvsupertx_size_lookup[mbmi->tx_size];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
|
||||
|
@@ -133,6 +133,15 @@ const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2] = {
|
||||
{{BLOCK_64X64, BLOCK_64X32}, {BLOCK_32X64, BLOCK_32X32}},
|
||||
};
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
const TX_SIZE uvsupertx_size_lookup[TX_SIZES] = {
|
||||
TX_4X4,
|
||||
TX_4X4,
|
||||
TX_8X8,
|
||||
TX_16X16
|
||||
};
|
||||
#endif
|
||||
|
||||
// Generates 4 bit field in which each bit set to 1 represents
|
||||
// a blocksize partition 1111 means we split 64x64, 32x32, 16x16
|
||||
// and 8x8. 1000 means we just split the 64x64 to 32x32
|
||||
|
@@ -31,6 +31,9 @@ extern const BLOCK_SIZE subsize_lookup[PARTITION_TYPES][BLOCK_SIZES];
|
||||
extern const TX_SIZE max_txsize_lookup[BLOCK_SIZES];
|
||||
extern const TX_SIZE tx_mode_to_biggest_tx_size[TX_MODES];
|
||||
extern const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2];
|
||||
#if CONFIG_SUPERTX
|
||||
extern const TX_SIZE uvsupertx_size_lookup[TX_SIZES];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
@@ -13,6 +13,84 @@
|
||||
#include "vp9/common/vp9_onyxc_int.h"
|
||||
#include "vp9/common/vp9_seg_common.h"
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
static const vp9_prob default_masked_interinter_prob[BLOCK_SIZES] = {
|
||||
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
static const vp9_prob default_interintra_prob[BLOCK_SIZES] = {
|
||||
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
|
||||
};
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
static const vp9_prob default_masked_interintra_prob[BLOCK_SIZES] = {
|
||||
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_FILTERINTRA
|
||||
static const vp9_prob default_filterintra_prob[TX_SIZES][INTRA_MODES] = {
|
||||
// DC V H D45 D135 D117 D153 D207 D63 TM
|
||||
{153, 171, 147, 150, 129, 101, 100, 153, 132, 111},
|
||||
{171, 173, 185, 131, 70, 53, 70, 148, 127, 114},
|
||||
{175, 203, 213, 86, 45, 71, 41, 150, 125, 154},
|
||||
{235, 230, 154, 202, 154, 205, 37, 128, 0, 202}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXT_TX
|
||||
static const vp9_prob default_ext_tx_prob = 178;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static const vp9_prob default_supertx_prob[TX_SIZES] = {
|
||||
255, 160, 160, 160
|
||||
};
|
||||
|
||||
static const vp9_prob default_supertxsplit_prob[TX_SIZES] = {
|
||||
255, 200, 200, 200
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
static const vp9_prob default_copy_noref_prob[COPY_MODE_CONTEXTS]
|
||||
[BLOCK_SIZES] = {
|
||||
{255, 255, 255, 82, 148, 182, 65, 193, 158, 70, 138, 101, 23},
|
||||
{255, 255, 255, 118, 153, 161, 123, 169, 157, 82, 101, 123, 88},
|
||||
{255, 255, 255, 130, 178, 226, 194, 196, 174, 173, 135, 144, 141},
|
||||
{255, 255, 255, 178, 218, 225, 197, 230, 222, 215, 220, 220, 220},
|
||||
{255, 255, 255, 243, 248, 241, 233, 249, 249, 249, 249, 249, 249}
|
||||
};
|
||||
|
||||
static const vp9_prob default_copy_mode_probs_l2[COPY_MODE_CONTEXTS][1] = {
|
||||
{207},
|
||||
{135},
|
||||
{141},
|
||||
{189},
|
||||
{209}
|
||||
};
|
||||
|
||||
const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)] = {
|
||||
-(REF0 - REF0), -(REF1 - REF0)
|
||||
};
|
||||
|
||||
static const vp9_prob default_copy_mode_probs[COPY_MODE_CONTEXTS]
|
||||
[COPY_MODE_COUNT - 2] = {
|
||||
{130, 159},
|
||||
{126, 176},
|
||||
{120, 150},
|
||||
{158, 183},
|
||||
{149, 125}
|
||||
};
|
||||
|
||||
const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)] = {
|
||||
-(REF0 - REF0), 2,
|
||||
-(REF1 - REF0), -(REF2 - REF0)
|
||||
};
|
||||
#endif
|
||||
|
||||
const vp9_prob vp9_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1] = {
|
||||
{ // above = dc
|
||||
{ 137, 30, 42, 148, 151, 207, 70, 52, 91 }, // left = dc
|
||||
@@ -245,7 +323,11 @@ const vp9_tree_index vp9_partition_tree[TREE_SIZE(PARTITION_TYPES)] = {
|
||||
};
|
||||
|
||||
static const vp9_prob default_intra_inter_p[INTRA_INTER_CONTEXTS] = {
|
||||
#if !CONFIG_COPY_CODING
|
||||
9, 102, 187, 225
|
||||
#else
|
||||
35, 112, 187, 225
|
||||
#endif
|
||||
};
|
||||
|
||||
static const vp9_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
|
||||
@@ -326,6 +408,30 @@ void vp9_init_mode_probs(FRAME_CONTEXT *fc) {
|
||||
fc->tx_probs = default_tx_probs;
|
||||
vp9_copy(fc->skip_probs, default_skip_probs);
|
||||
vp9_copy(fc->inter_mode_probs, default_inter_mode_probs);
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
vp9_copy(fc->masked_interinter_prob, default_masked_interinter_prob);
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
vp9_copy(fc->interintra_prob, default_interintra_prob);
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
vp9_copy(fc->masked_interintra_prob, default_masked_interintra_prob);
|
||||
#endif
|
||||
#endif
|
||||
#if CONFIG_FILTERINTRA
|
||||
vp9_copy(fc->filterintra_prob, default_filterintra_prob);
|
||||
#endif
|
||||
#if CONFIG_EXT_TX
|
||||
fc->ext_tx_prob = default_ext_tx_prob;
|
||||
#endif
|
||||
#if CONFIG_SUPERTX
|
||||
vp9_copy(fc->supertx_prob, default_supertx_prob);
|
||||
vp9_copy(fc->supertxsplit_prob, default_supertxsplit_prob);
|
||||
#endif
|
||||
#if CONFIG_COPY_CODING
|
||||
vp9_copy(fc->copy_noref_prob, default_copy_noref_prob);
|
||||
vp9_copy(fc->copy_mode_probs_l2, default_copy_mode_probs_l2);
|
||||
vp9_copy(fc->copy_mode_probs, default_copy_mode_probs);
|
||||
#endif
|
||||
}
|
||||
|
||||
const vp9_tree_index vp9_switchable_interp_tree
|
||||
@@ -416,6 +522,73 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) {
|
||||
|
||||
for (i = 0; i < SKIP_CONTEXTS; ++i)
|
||||
fc->skip_probs[i] = adapt_prob(pre_fc->skip_probs[i], counts->skip[i]);
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
if (cm->use_masked_interinter) {
|
||||
for (i = 0; i < BLOCK_SIZES; ++i) {
|
||||
if (get_mask_bits(i))
|
||||
fc->masked_interinter_prob[i] = adapt_prob
|
||||
(pre_fc->masked_interinter_prob[i],
|
||||
counts->masked_interinter[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
if (cm->use_interintra) {
|
||||
for (i = 0; i < BLOCK_SIZES; ++i) {
|
||||
if (is_interintra_allowed(i))
|
||||
fc->interintra_prob[i] = adapt_prob(pre_fc->interintra_prob[i],
|
||||
counts->interintra[i]);
|
||||
}
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (cm->use_masked_interintra) {
|
||||
for (i = 0; i < BLOCK_SIZES; ++i) {
|
||||
if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
|
||||
fc->masked_interintra_prob[i] = adapt_prob(
|
||||
pre_fc->masked_interintra_prob[i],
|
||||
counts->masked_interintra[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_FILTERINTRA
|
||||
for (i = 0; i < TX_SIZES; ++i)
|
||||
for (j = 0; j < INTRA_MODES; ++j)
|
||||
fc->filterintra_prob[i][j] = adapt_prob(pre_fc->filterintra_prob[i][j],
|
||||
counts->filterintra[i][j]);
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXT_TX
|
||||
fc->ext_tx_prob = adapt_prob(pre_fc->ext_tx_prob, counts->ext_tx);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
for (i = 1; i < TX_SIZES; ++i) {
|
||||
fc->supertx_prob[i] = adapt_prob(pre_fc->supertx_prob[i],
|
||||
counts->supertx[i]);
|
||||
}
|
||||
|
||||
for (i = 1; i < TX_SIZES; ++i) {
|
||||
fc->supertxsplit_prob[i] = adapt_prob(pre_fc->supertxsplit_prob[i],
|
||||
counts->supertxsplit[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
for (i = 0; i < COPY_MODE_CONTEXTS; i++) {
|
||||
for (j = BLOCK_8X8; j < BLOCK_SIZES; j++) {
|
||||
fc->copy_noref_prob[i][j] =
|
||||
adapt_prob(pre_fc->copy_noref_prob[i][j], counts->copy_noref[i][j]);
|
||||
}
|
||||
adapt_probs(vp9_copy_mode_tree_l2, pre_fc->copy_mode_probs_l2[i],
|
||||
counts->copy_mode_l2[i], fc->copy_mode_probs_l2[i]);
|
||||
adapt_probs(vp9_copy_mode_tree, pre_fc->copy_mode_probs[i],
|
||||
counts->copy_mode[i], fc->copy_mode_probs[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_default_lf_deltas(struct loopfilter *lf) {
|
||||
|
@@ -52,6 +52,30 @@ typedef struct frame_contexts {
|
||||
struct tx_probs tx_probs;
|
||||
vp9_prob skip_probs[SKIP_CONTEXTS];
|
||||
nmv_context nmvc;
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
vp9_prob masked_interinter_prob[BLOCK_SIZES];
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
vp9_prob interintra_prob[BLOCK_SIZES];
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
vp9_prob masked_interintra_prob[BLOCK_SIZES];
|
||||
#endif
|
||||
#endif
|
||||
#if CONFIG_FILTERINTRA
|
||||
vp9_prob filterintra_prob[TX_SIZES][INTRA_MODES];
|
||||
#endif
|
||||
#if CONFIG_EXT_TX
|
||||
vp9_prob ext_tx_prob;
|
||||
#endif
|
||||
#if CONFIG_SUPERTX
|
||||
vp9_prob supertx_prob[TX_SIZES];
|
||||
vp9_prob supertxsplit_prob[TX_SIZES];
|
||||
#endif
|
||||
#if CONFIG_COPY_CODING
|
||||
vp9_prob copy_noref_prob[COPY_MODE_CONTEXTS][BLOCK_SIZES];
|
||||
vp9_prob copy_mode_probs_l2[COPY_MODE_CONTEXTS][1];
|
||||
vp9_prob copy_mode_probs[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 2];
|
||||
#endif
|
||||
} FRAME_CONTEXT;
|
||||
|
||||
typedef struct {
|
||||
@@ -71,6 +95,31 @@ typedef struct {
|
||||
struct tx_counts tx;
|
||||
unsigned int skip[SKIP_CONTEXTS][2];
|
||||
nmv_context_counts mv;
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
unsigned int masked_interinter[BLOCK_SIZES][2];
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
unsigned int interintra[BLOCK_SIZES][2];
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
unsigned int masked_interintra[BLOCK_SIZES][2];
|
||||
#endif
|
||||
#endif
|
||||
#if CONFIG_FILTERINTRA
|
||||
unsigned int filterintra[TX_SIZES][INTRA_MODES][2];
|
||||
#endif
|
||||
#if CONFIG_EXT_TX
|
||||
unsigned int ext_tx[2];
|
||||
#endif
|
||||
#if CONFIG_SUPERTX
|
||||
unsigned int supertx[TX_SIZES][2];
|
||||
unsigned int supertxsplit[TX_SIZES][2];
|
||||
unsigned int supertx_size[BLOCK_SIZES];
|
||||
#endif
|
||||
#if CONFIG_COPY_CODING
|
||||
unsigned int copy_noref[COPY_MODE_CONTEXTS][BLOCK_SIZES][2];
|
||||
unsigned int copy_mode_l2[COPY_MODE_CONTEXTS][2];
|
||||
unsigned int copy_mode[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 1];
|
||||
#endif
|
||||
} FRAME_COUNTS;
|
||||
|
||||
extern const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
|
||||
@@ -83,6 +132,10 @@ extern const vp9_tree_index vp9_inter_mode_tree[TREE_SIZE(INTER_MODES)];
|
||||
extern const vp9_tree_index vp9_partition_tree[TREE_SIZE(PARTITION_TYPES)];
|
||||
extern const vp9_tree_index vp9_switchable_interp_tree
|
||||
[TREE_SIZE(SWITCHABLE_FILTERS)];
|
||||
#if CONFIG_COPY_CODING
|
||||
extern const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)];
|
||||
extern const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)];
|
||||
#endif
|
||||
|
||||
void vp9_setup_past_independence(struct VP9Common *cm);
|
||||
|
||||
|
@@ -100,6 +100,14 @@ typedef enum {
|
||||
TX_TYPES = 4
|
||||
} TX_TYPE;
|
||||
|
||||
#if CONFIG_EXT_TX
|
||||
typedef enum {
|
||||
NORM = 0,
|
||||
ALT = 1,
|
||||
EXT_TX_TYPES = 2
|
||||
} EXT_TX_TYPE;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN = 0,
|
||||
BT_601 = 1, // YUV
|
||||
|
@@ -76,7 +76,6 @@ int vp9_get_frame_buffer(void *cb_priv, size_t min_size,
|
||||
int vp9_release_frame_buffer(void *cb_priv, vpx_codec_frame_buffer_t *fb) {
|
||||
InternalFrameBuffer *const int_fb = (InternalFrameBuffer *)fb->priv;
|
||||
(void)cb_priv;
|
||||
if (int_fb)
|
||||
int_fb->in_use = 0;
|
||||
int_fb->in_use = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -206,6 +206,13 @@ static const int mode_lf_lut[MB_MODE_COUNT] = {
|
||||
1, 1, 0, 1 // INTER_MODES (ZEROMV == 0)
|
||||
};
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static int supertx_enabled_lpf(const MB_MODE_INFO *mbmi) {
|
||||
return mbmi->tx_size >
|
||||
MIN(b_width_log2(mbmi->sb_type), b_height_log2(mbmi->sb_type));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
|
||||
int lvl;
|
||||
|
||||
@@ -502,7 +509,7 @@ static void build_masks(const loop_filter_info_n *const lfi_n,
|
||||
const MB_MODE_INFO *mbmi = &mi->mbmi;
|
||||
const BLOCK_SIZE block_size = mbmi->sb_type;
|
||||
const TX_SIZE tx_size_y = mbmi->tx_size;
|
||||
const TX_SIZE tx_size_uv = get_uv_tx_size_impl(tx_size_y, block_size, 1, 1);
|
||||
const TX_SIZE tx_size_uv = get_uv_tx_size(mbmi);
|
||||
const int filter_level = get_filter_level(lfi_n, mbmi);
|
||||
uint64_t *const left_y = &lfm->left_y[tx_size_y];
|
||||
uint64_t *const above_y = &lfm->above_y[tx_size_y];
|
||||
@@ -572,6 +579,85 @@ static void build_masks(const loop_filter_info_n *const lfi_n,
|
||||
*int_4x4_uv |= (size_mask_uv[block_size] & 0xffff) << shift_uv;
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static void build_masks_supertx(const loop_filter_info_n *const lfi_n,
|
||||
const MODE_INFO *mi, const int shift_y,
|
||||
const int shift_uv,
|
||||
LOOP_FILTER_MASK *lfm) {
|
||||
const MB_MODE_INFO *mbmi = &mi->mbmi;
|
||||
const TX_SIZE tx_size_y = mbmi->tx_size;
|
||||
const TX_SIZE tx_size_uv = get_uv_tx_size(mbmi);
|
||||
const BLOCK_SIZE block_size = 3 * (int)tx_size_y;
|
||||
const int filter_level = get_filter_level(lfi_n, mbmi);
|
||||
uint64_t *const left_y = &lfm->left_y[tx_size_y];
|
||||
uint64_t *const above_y = &lfm->above_y[tx_size_y];
|
||||
uint64_t *const int_4x4_y = &lfm->int_4x4_y;
|
||||
uint16_t *const left_uv = &lfm->left_uv[tx_size_uv];
|
||||
uint16_t *const above_uv = &lfm->above_uv[tx_size_uv];
|
||||
uint16_t *const int_4x4_uv = &lfm->int_4x4_uv;
|
||||
int i;
|
||||
|
||||
// If filter level is 0 we don't loop filter.
|
||||
if (!filter_level) {
|
||||
return;
|
||||
} else {
|
||||
const int w = num_8x8_blocks_wide_lookup[block_size];
|
||||
const int h = num_8x8_blocks_high_lookup[block_size];
|
||||
int index = shift_y;
|
||||
for (i = 0; i < h; i++) {
|
||||
vpx_memset(&lfm->lfl_y[index], filter_level, w);
|
||||
index += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// These set 1 in the current block size for the block size edges.
|
||||
// For instance if the block size is 32x16, we'll set :
|
||||
// above = 1111
|
||||
// 0000
|
||||
// and
|
||||
// left = 1000
|
||||
// = 1000
|
||||
// NOTE : In this example the low bit is left most ( 1000 ) is stored as
|
||||
// 1, not 8...
|
||||
//
|
||||
// U and v set things on a 16 bit scale.
|
||||
//
|
||||
*above_y |= above_prediction_mask[block_size] << shift_y;
|
||||
*above_uv |= above_prediction_mask_uv[block_size] << shift_uv;
|
||||
*left_y |= left_prediction_mask[block_size] << shift_y;
|
||||
*left_uv |= left_prediction_mask_uv[block_size] << shift_uv;
|
||||
|
||||
// If the block has no coefficients and is not intra we skip applying
|
||||
// the loop filter on block edges.
|
||||
if (mbmi->skip && is_inter_block(mbmi))
|
||||
return;
|
||||
|
||||
// Here we are adding a mask for the transform size. The transform
|
||||
// size mask is set to be correct for a 64x64 prediction block size. We
|
||||
// mask to match the size of the block we are working on and then shift it
|
||||
// into place..
|
||||
*above_y |= (size_mask[block_size] &
|
||||
above_64x64_txform_mask[tx_size_y]) << shift_y;
|
||||
*above_uv |= (size_mask_uv[block_size] &
|
||||
above_64x64_txform_mask_uv[tx_size_uv]) << shift_uv;
|
||||
|
||||
*left_y |= (size_mask[block_size] &
|
||||
left_64x64_txform_mask[tx_size_y]) << shift_y;
|
||||
*left_uv |= (size_mask_uv[block_size] &
|
||||
left_64x64_txform_mask_uv[tx_size_uv]) << shift_uv;
|
||||
|
||||
// Here we are trying to determine what to do with the internal 4x4 block
|
||||
// boundaries. These differ from the 4x4 boundaries on the outside edge of
|
||||
// an 8x8 in that the internal ones can be skipped and don't depend on
|
||||
// the prediction block size.
|
||||
if (tx_size_y == TX_4X4)
|
||||
*int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffff) << shift_y;
|
||||
|
||||
if (tx_size_uv == TX_4X4)
|
||||
*int_4x4_uv |= (size_mask_uv[block_size] & 0xffff) << shift_uv;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function does the same thing as the one above with the exception that
|
||||
// it only affects the y masks. It exists because for blocks < 16x16 in size,
|
||||
// we only update u and v masks on the first block.
|
||||
@@ -615,6 +701,48 @@ static void build_y_mask(const loop_filter_info_n *const lfi_n,
|
||||
*int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffff) << shift_y;
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static void build_y_mask_supertx(const loop_filter_info_n *const lfi_n,
|
||||
const MODE_INFO *mi, const int shift_y,
|
||||
LOOP_FILTER_MASK *lfm) {
|
||||
const MB_MODE_INFO *mbmi = &mi->mbmi;
|
||||
const TX_SIZE tx_size_y = mbmi->tx_size;
|
||||
const BLOCK_SIZE block_size = 3 * (int)tx_size_y;
|
||||
const int filter_level = get_filter_level(lfi_n, mbmi);
|
||||
uint64_t *const left_y = &lfm->left_y[tx_size_y];
|
||||
uint64_t *const above_y = &lfm->above_y[tx_size_y];
|
||||
uint64_t *const int_4x4_y = &lfm->int_4x4_y;
|
||||
int i;
|
||||
|
||||
if (!filter_level) {
|
||||
return;
|
||||
} else {
|
||||
const int w = num_8x8_blocks_wide_lookup[block_size];
|
||||
const int h = num_8x8_blocks_high_lookup[block_size];
|
||||
int index = shift_y;
|
||||
for (i = 0; i < h; i++) {
|
||||
vpx_memset(&lfm->lfl_y[index], filter_level, w);
|
||||
index += 8;
|
||||
}
|
||||
}
|
||||
|
||||
*above_y |= above_prediction_mask[block_size] << shift_y;
|
||||
*left_y |= left_prediction_mask[block_size] << shift_y;
|
||||
|
||||
if (mbmi->skip && is_inter_block(mbmi))
|
||||
return;
|
||||
|
||||
*above_y |= (size_mask[block_size] &
|
||||
above_64x64_txform_mask[tx_size_y]) << shift_y;
|
||||
|
||||
*left_y |= (size_mask[block_size] &
|
||||
left_64x64_txform_mask[tx_size_y]) << shift_y;
|
||||
|
||||
if (tx_size_y == TX_4X4)
|
||||
*int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffff) << shift_y;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function sets up the bit masks for the entire 64x64 region represented
|
||||
// by mi_row, mi_col.
|
||||
// TODO(JBB): This function only works for yv12.
|
||||
@@ -650,6 +778,9 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
|
||||
cm->mi_rows - mi_row : MI_BLOCK_SIZE);
|
||||
const int max_cols = (mi_col + MI_BLOCK_SIZE > cm->mi_cols ?
|
||||
cm->mi_cols - mi_col : MI_BLOCK_SIZE);
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx;
|
||||
#endif
|
||||
|
||||
vp9_zero(*lfm);
|
||||
|
||||
@@ -687,20 +818,43 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
break;
|
||||
case BLOCK_32X16:
|
||||
#if CONFIG_SUPERTX
|
||||
supertx = supertx_enabled_lpf(&mip[0]->mbmi);
|
||||
if (!supertx) {
|
||||
#endif
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
if (mi_32_row_offset + 2 >= max_rows)
|
||||
continue;
|
||||
mip2 = mip + mode_info_stride * 2;
|
||||
build_masks(lfi_n, mip2[0], shift_y + 16, shift_uv + 4, lfm);
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case BLOCK_16X32:
|
||||
#if CONFIG_SUPERTX
|
||||
supertx = supertx_enabled_lpf(&mip[0]->mbmi);
|
||||
if (!supertx) {
|
||||
#endif
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
if (mi_32_col_offset + 2 >= max_cols)
|
||||
continue;
|
||||
mip2 = mip + 2;
|
||||
build_masks(lfi_n, mip2[0], shift_y + 2, shift_uv + 1, lfm);
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
#if CONFIG_SUPERTX
|
||||
if (mip[0]->mbmi.tx_size == TX_32X32) {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
} else {
|
||||
#endif
|
||||
for (idx_16 = 0; idx_16 < 4; mip += offset_16[idx_16], ++idx_16) {
|
||||
const int shift_y = shift_32_y[idx_32] + shift_16_y[idx_16];
|
||||
const int shift_uv = shift_32_uv[idx_32] + shift_16_uv[idx_16];
|
||||
@@ -717,24 +871,56 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
break;
|
||||
case BLOCK_16X8:
|
||||
#if CONFIG_SUPERTX
|
||||
supertx = supertx_enabled_lpf(&mip[0]->mbmi);
|
||||
if (!supertx) {
|
||||
#endif
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
if (mi_16_row_offset + 1 >= max_rows)
|
||||
continue;
|
||||
mip2 = mip + mode_info_stride;
|
||||
build_y_mask(lfi_n, mip2[0], shift_y+8, lfm);
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case BLOCK_8X16:
|
||||
#if CONFIG_SUPERTX
|
||||
supertx = supertx_enabled_lpf(&mip[0]->mbmi);
|
||||
if (!supertx) {
|
||||
#endif
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
if (mi_16_col_offset +1 >= max_cols)
|
||||
continue;
|
||||
mip2 = mip + 1;
|
||||
build_y_mask(lfi_n, mip2[0], shift_y+1, lfm);
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default: {
|
||||
#if CONFIG_SUPERTX
|
||||
if (mip[0]->mbmi.tx_size == TX_16X16) {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
} else {
|
||||
#endif
|
||||
const int shift_y = shift_32_y[idx_32] +
|
||||
shift_16_y[idx_16] +
|
||||
shift_8_y[0];
|
||||
#if CONFIG_SUPERTX
|
||||
supertx = supertx_enabled_lpf(&mip[0]->mbmi);
|
||||
if (!supertx) {
|
||||
#endif
|
||||
build_masks(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
build_masks_supertx(lfi_n, mip[0], shift_y, shift_uv, lfm);
|
||||
}
|
||||
#endif
|
||||
mip += offset[0];
|
||||
for (idx_8 = 1; idx_8 < 4; mip += offset[idx_8], ++idx_8) {
|
||||
const int shift_y = shift_32_y[idx_32] +
|
||||
@@ -748,12 +934,26 @@ void vp9_setup_mask(VP9_COMMON *const cm, const int mi_row, const int mi_col,
|
||||
if (mi_8_col_offset >= max_cols ||
|
||||
mi_8_row_offset >= max_rows)
|
||||
continue;
|
||||
#if CONFIG_SUPERTX
|
||||
supertx = supertx_enabled_lpf(&mip[0]->mbmi);
|
||||
if (!supertx)
|
||||
#endif
|
||||
build_y_mask(lfi_n, mip[0], shift_y, lfm);
|
||||
#if CONFIG_SUPERTX
|
||||
else
|
||||
build_y_mask_supertx(lfi_n, mip[0], shift_y, lfm);
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_SUPERTX
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if CONFIG_SUPERTX
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -939,7 +1139,7 @@ static void filter_block_plane_non420(VP9_COMMON *cm,
|
||||
!(r & (num_8x8_blocks_high_lookup[sb_type] - 1)) : 1;
|
||||
const int skip_this_r = skip_this && !block_edge_above;
|
||||
const TX_SIZE tx_size = (plane->plane_type == PLANE_TYPE_UV)
|
||||
? get_uv_tx_size(&mi[0].mbmi, plane)
|
||||
? get_uv_tx_size(&mi[0].mbmi)
|
||||
: mi[0].mbmi.tx_size;
|
||||
const int skip_border_4x4_c = ss_x && mi_col + c == cm->mi_cols - 1;
|
||||
const int skip_border_4x4_r = ss_y && mi_row + r == cm->mi_rows - 1;
|
||||
|
@@ -188,3 +188,176 @@ void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
assert("Invalid block index.");
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
static int compare_interinfo(MB_MODE_INFO *mbmi, MB_MODE_INFO *ref_mbmi) {
|
||||
if (mbmi == ref_mbmi) {
|
||||
return 1;
|
||||
} else {
|
||||
int is_same;
|
||||
#if CONFIG_INTERINTRA
|
||||
MV_REFERENCE_FRAME mbmi_ref1_backup = mbmi->ref_frame[1];
|
||||
MV_REFERENCE_FRAME refmbmi_ref1_backup = ref_mbmi->ref_frame[1];
|
||||
|
||||
if (mbmi->ref_frame[1] == INTRA_FRAME)
|
||||
mbmi->ref_frame[1] = NONE;
|
||||
if (ref_mbmi->ref_frame[1] == INTRA_FRAME)
|
||||
ref_mbmi->ref_frame[1] = NONE;
|
||||
#endif
|
||||
if (mbmi->ref_frame[0] == ref_mbmi->ref_frame[0] &&
|
||||
mbmi->ref_frame[1] == ref_mbmi->ref_frame[1]) {
|
||||
if (mbmi->ref_frame[1] > INTRA_FRAME)
|
||||
is_same = mbmi->mv[0].as_int == ref_mbmi->mv[0].as_int &&
|
||||
mbmi->mv[1].as_int == ref_mbmi->mv[1].as_int &&
|
||||
mbmi->interp_filter == ref_mbmi->interp_filter;
|
||||
else
|
||||
is_same = mbmi->mv[0].as_int == ref_mbmi->mv[0].as_int &&
|
||||
mbmi->interp_filter == ref_mbmi->interp_filter;
|
||||
} else {
|
||||
is_same = 0;
|
||||
}
|
||||
#if CONFIG_INTERINTRA
|
||||
mbmi->ref_frame[1] = mbmi_ref1_backup;
|
||||
ref_mbmi->ref_frame[1] = refmbmi_ref1_backup;
|
||||
#endif
|
||||
|
||||
return is_same;
|
||||
}
|
||||
}
|
||||
|
||||
static int check_inside(VP9_COMMON *cm, int mi_row, int mi_col) {
|
||||
return mi_row >= 0 && mi_col >= 0 &&
|
||||
mi_row < cm->mi_rows && mi_col < cm->mi_cols;
|
||||
}
|
||||
|
||||
static int is_right_available(BLOCK_SIZE bsize, int mi_row, int mi_col) {
|
||||
int depth, max_depth = 4 - MIN(b_width_log2(bsize), b_height_log2(bsize));
|
||||
int block[4] = {0};
|
||||
|
||||
if (bsize == BLOCK_64X64)
|
||||
return 1;
|
||||
mi_row = mi_row % 8;
|
||||
mi_col = mi_col % 8;
|
||||
for (depth = 1; depth <= max_depth; depth++) {
|
||||
block[depth] = (mi_row >> (3 - depth)) * 2 + (mi_col >> (3 - depth));
|
||||
mi_row = mi_row % (8 >> depth);
|
||||
mi_col = mi_col % (8 >> depth);
|
||||
}
|
||||
|
||||
if (b_width_log2(bsize) < b_height_log2(bsize)) {
|
||||
if (block[max_depth] == 0)
|
||||
return 1;
|
||||
} else if (b_width_log2(bsize) > b_height_log2(bsize)) {
|
||||
if (block[max_depth] > 0)
|
||||
return 0;
|
||||
} else {
|
||||
if (block[max_depth] == 0 || block[max_depth] == 2)
|
||||
return 1;
|
||||
else if (block[max_depth] == 3)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (depth = max_depth - 1; depth > 0; depth--) {
|
||||
if (block[depth] == 0 || block[depth] == 2)
|
||||
return 1;
|
||||
else if (block[depth] == 3)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int is_second_rec(int mi_row, int mi_col, BLOCK_SIZE bsize) {
|
||||
int bw = 4 << b_width_log2(bsize);
|
||||
int bh = 4 << b_height_log2(bsize);
|
||||
|
||||
if (bw < bh)
|
||||
return (mi_col << 3) % (bw << 1) == 0 ? 0 : 1;
|
||||
else if (bh < bw)
|
||||
return (mi_row << 3) % (bh << 1) == 0 ? 0 : 2;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vp9_construct_ref_inter_list(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
BLOCK_SIZE bsize, int mi_row, int mi_col,
|
||||
MB_MODE_INFO *ref_list[18]) {
|
||||
int bw = 4 << b_width_log2(bsize);
|
||||
int bh = 4 << b_height_log2(bsize);
|
||||
int row_offset, col_offset;
|
||||
int mi_offset;
|
||||
MB_MODE_INFO *ref_mbmi;
|
||||
int ref_index, ref_num = 0;
|
||||
int row_offset_cand[18], col_offset_cand[18];
|
||||
int offset_num = 0, i, switchflag;
|
||||
int is_sec_rec = is_second_rec(mi_row, mi_col, bsize);
|
||||
|
||||
if (is_sec_rec != 2) {
|
||||
row_offset_cand[offset_num] = -1; col_offset_cand[offset_num] = 0;
|
||||
offset_num++;
|
||||
}
|
||||
if (is_sec_rec != 1) {
|
||||
row_offset_cand[offset_num] = bh / 16; col_offset_cand[offset_num] = -1;
|
||||
offset_num++;
|
||||
}
|
||||
|
||||
row_offset = bh / 8 - 1;
|
||||
col_offset = 1;
|
||||
if (is_sec_rec < 2)
|
||||
switchflag = 1;
|
||||
else
|
||||
switchflag = 0;
|
||||
while ((is_sec_rec == 0 && ((row_offset >=0) || col_offset < (bw / 8 + 1))) ||
|
||||
(is_sec_rec == 1 && col_offset < (bw / 8 + 1)) ||
|
||||
(is_sec_rec == 2 && row_offset >=0)) {
|
||||
switch (switchflag) {
|
||||
case 0:
|
||||
if (row_offset >= 0) {
|
||||
if (row_offset != bh / 16) {
|
||||
row_offset_cand[offset_num] = row_offset;
|
||||
col_offset_cand[offset_num] = -1;
|
||||
offset_num++;
|
||||
}
|
||||
row_offset--;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (col_offset < (bw / 8 + 1)) {
|
||||
row_offset_cand[offset_num] = -1;
|
||||
col_offset_cand[offset_num] = col_offset;
|
||||
offset_num++;
|
||||
col_offset++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
if (is_sec_rec == 0)
|
||||
switchflag = 1 - switchflag;
|
||||
}
|
||||
row_offset_cand[offset_num] = -1;
|
||||
col_offset_cand[offset_num] = -1;
|
||||
offset_num++;
|
||||
|
||||
for (i = 0; i < offset_num; i++) {
|
||||
row_offset = row_offset_cand[i];
|
||||
col_offset = col_offset_cand[i];
|
||||
if ((col_offset < (bw / 8) ||
|
||||
(col_offset == (bw / 8) && is_right_available(bsize, mi_row, mi_col)))
|
||||
&& check_inside(cm, mi_row + row_offset, mi_col + col_offset)) {
|
||||
mi_offset = row_offset * cm->mi_stride + col_offset;
|
||||
ref_mbmi = &xd->mi[mi_offset]->mbmi;
|
||||
if (is_inter_block(ref_mbmi)) {
|
||||
for (ref_index = 0; ref_index < ref_num; ref_index++) {
|
||||
if (compare_interinfo(ref_mbmi, ref_list[ref_index]))
|
||||
break;
|
||||
}
|
||||
if (ref_index == ref_num) {
|
||||
ref_list[ref_num] = ref_mbmi;
|
||||
ref_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ref_num;
|
||||
}
|
||||
#endif
|
||||
|
@@ -220,6 +220,12 @@ void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
int block, int ref, int mi_row, int mi_col,
|
||||
int_mv *nearest, int_mv *near);
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
int vp9_construct_ref_inter_list(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
BLOCK_SIZE bsize, int mi_row, int mi_col,
|
||||
MB_MODE_INFO *ref_list[18]);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#ifndef VP9_COMMON_VP9_ONYXC_INT_H_
|
||||
#define VP9_COMMON_VP9_ONYXC_INT_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx/internal/vpx_codec_internal.h"
|
||||
#include "./vp9_rtcd.h"
|
||||
@@ -62,40 +61,8 @@ typedef struct {
|
||||
int ref_count;
|
||||
vpx_codec_frame_buffer_t raw_frame_buffer;
|
||||
YV12_BUFFER_CONFIG buf;
|
||||
|
||||
// The Following variables will only be used in frame parallel decode.
|
||||
|
||||
// owner_thread_id indicates which FrameWorker owns this buffer. -1 means
|
||||
// that no FrameWorker owns, or is decoding, this buffer.
|
||||
int owner_worker_id;
|
||||
|
||||
// Buffer has been decoded to (row, col) position. When first start decoding,
|
||||
// they are reset to -1. If a frame has been fully decoded, row and col will
|
||||
// be set to INT_MAX.
|
||||
int row;
|
||||
int col;
|
||||
} RefCntBuffer;
|
||||
|
||||
typedef struct {
|
||||
// Protect BufferPool from being accessed by several FrameWorkers at
|
||||
// the same time during frame parallel decode.
|
||||
// TODO(hkuang): Try to use atomic variable instead of locking the whole pool.
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_t pool_mutex;
|
||||
#endif
|
||||
|
||||
// Private data associated with the frame buffer callbacks.
|
||||
void *cb_priv;
|
||||
|
||||
vpx_get_frame_buffer_cb_fn_t get_fb_cb;
|
||||
vpx_release_frame_buffer_cb_fn_t release_fb_cb;
|
||||
|
||||
RefCntBuffer frame_bufs[FRAME_BUFFERS];
|
||||
|
||||
// Handles memory for the codec.
|
||||
InternalFrameBufferList int_frame_buffers;
|
||||
} BufferPool;
|
||||
|
||||
typedef struct VP9Common {
|
||||
struct vpx_internal_error_info error;
|
||||
|
||||
@@ -122,10 +89,9 @@ typedef struct VP9Common {
|
||||
|
||||
YV12_BUFFER_CONFIG *frame_to_show;
|
||||
|
||||
int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
|
||||
RefCntBuffer frame_bufs[FRAME_BUFFERS];
|
||||
|
||||
// Prepare ref_frame_map for next frame. Only used in frame parallel decode.
|
||||
int next_ref_frame_map[REF_FRAMES];
|
||||
int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
|
||||
|
||||
// TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
|
||||
// roll new_fb_idx into it.
|
||||
@@ -236,33 +202,40 @@ typedef struct VP9Common {
|
||||
|
||||
int log2_tile_cols, log2_tile_rows;
|
||||
|
||||
// External BufferPool passed from outside.
|
||||
BufferPool *buffer_pool;
|
||||
// Private data associated with the frame buffer callbacks.
|
||||
void *cb_priv;
|
||||
vpx_get_frame_buffer_cb_fn_t get_fb_cb;
|
||||
vpx_release_frame_buffer_cb_fn_t release_fb_cb;
|
||||
|
||||
// Handles memory for the codec.
|
||||
InternalFrameBufferList int_frame_buffers;
|
||||
|
||||
PARTITION_CONTEXT *above_seg_context;
|
||||
ENTROPY_CONTEXT *above_context;
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
int use_masked_interinter;
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
int use_interintra;
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
int use_masked_interintra;
|
||||
#endif
|
||||
#endif
|
||||
} VP9_COMMON;
|
||||
|
||||
static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
|
||||
return &cm->buffer_pool->frame_bufs[cm->new_fb_idx].buf;
|
||||
return &cm->frame_bufs[cm->new_fb_idx].buf;
|
||||
}
|
||||
|
||||
static INLINE int get_free_fb(VP9_COMMON *cm) {
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
int i;
|
||||
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_lock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
for (i = 0; i < FRAME_BUFFERS; i++)
|
||||
if (frame_bufs[i].ref_count == 0)
|
||||
if (cm->frame_bufs[i].ref_count == 0)
|
||||
break;
|
||||
|
||||
assert(i < FRAME_BUFFERS);
|
||||
frame_bufs[i].ref_count = 1;
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_unlock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
cm->frame_bufs[i].ref_count = 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@@ -383,3 +383,47 @@ int vp9_get_segment_id(VP9_COMMON *cm, const uint8_t *segment_ids,
|
||||
assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
|
||||
return segment_id;
|
||||
}
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
int vp9_get_copy_mode_context(const MACROBLOCKD *xd) {
|
||||
const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
|
||||
const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
|
||||
const int has_above = above_mbmi != NULL;
|
||||
const int has_left = left_mbmi != NULL;
|
||||
|
||||
if (has_above && has_left) {
|
||||
const int above_intra = !is_inter_block(above_mbmi);
|
||||
const int left_intra = !is_inter_block(left_mbmi);
|
||||
|
||||
if (above_intra && left_intra) {
|
||||
return 4;
|
||||
} else if (above_intra || left_intra) {
|
||||
return 3;
|
||||
} else {
|
||||
const int above_predict = above_mbmi->copy_mode != NOREF;
|
||||
const int left_predict = left_mbmi->copy_mode != NOREF;
|
||||
if (above_predict && left_predict)
|
||||
return 0;
|
||||
else if (above_predict || left_predict)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
} else if (has_above || has_left) {
|
||||
const MB_MODE_INFO *const ref_mbmi = has_above ? above_mbmi : left_mbmi;
|
||||
const int ref_intra = !is_inter_block(ref_mbmi);
|
||||
|
||||
if (ref_intra) {
|
||||
return 3;
|
||||
} else {
|
||||
const int ref_predict = ref_mbmi != NOREF;
|
||||
if (ref_predict)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -134,6 +134,10 @@ static INLINE unsigned int *get_tx_counts(TX_SIZE max_tx_size, int ctx,
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
int vp9_get_copy_mode_context(const MACROBLOCKD *xd);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,60 @@ void vp9_setup_pre_planes(MACROBLOCKD *xd, int idx,
|
||||
const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
|
||||
const struct scale_factors *sf);
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
void vp9_generate_masked_weight(int mask_index, BLOCK_SIZE sb_type,
|
||||
int h, int w, uint8_t *mask, int stride);
|
||||
void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
|
||||
int h, int w, uint8_t *mask, int stride);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
void vp9_build_inter_predictors_sby_sub8x8_extend(MACROBLOCKD *xd,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori,
|
||||
int mi_col_ori,
|
||||
BLOCK_SIZE top_bsize,
|
||||
PARTITION_TYPE partition);
|
||||
void vp9_build_inter_predictors_sbuv_sub8x8_extend(MACROBLOCKD *xd,
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
int mi_row, int mi_col,
|
||||
#endif
|
||||
int mi_row_ori,
|
||||
int mi_col_ori,
|
||||
BLOCK_SIZE top_bsize);
|
||||
void vp9_build_masked_inter_predictor_complex(uint8_t *dst, int dst_stride,
|
||||
uint8_t *dst2, int dst2_stride,
|
||||
int plane,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori,
|
||||
BLOCK_SIZE bsize,
|
||||
BLOCK_SIZE top_bsize,
|
||||
PARTITION_TYPE partition);
|
||||
void vp9_dec_build_inter_predictors_sby_sub8x8_extend(MACROBLOCKD *xd,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori,
|
||||
int mi_col_ori,
|
||||
BLOCK_SIZE top_bsize,
|
||||
PARTITION_TYPE p);
|
||||
void vp9_dec_build_inter_predictors_sbuv_sub8x8_extend(MACROBLOCKD *xd,
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
int mi_row, int mi_col,
|
||||
#endif
|
||||
int mi_row_ori,
|
||||
int mi_col_ori,
|
||||
BLOCK_SIZE top_bsize);
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
void vp9_build_inter_predictors_sb_extend(MACROBLOCKD *xd,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori,
|
||||
BLOCK_SIZE bsize);
|
||||
void vp9_dec_build_inter_predictors_sb_extend(MACROBLOCKD *xd,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori,
|
||||
BLOCK_SIZE bsize);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -444,8 +444,227 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_FILTERINTRA
|
||||
static void filter_intra_predictors_4tap(uint8_t *ypred_ptr, int y_stride,
|
||||
int bs,
|
||||
const uint8_t *yabove_row,
|
||||
const uint8_t *yleft_col,
|
||||
int mode) {
|
||||
static const int prec_bits = 10;
|
||||
static const int round_val = 511;
|
||||
|
||||
int k, r, c;
|
||||
int pred[33][33];
|
||||
int mean, ipred;
|
||||
|
||||
int taps4_4[10][4] = {
|
||||
{735, 881, -537, -54},
|
||||
{1005, 519, -488, -11},
|
||||
{383, 990, -343, -6},
|
||||
{442, 805, -542, 319},
|
||||
{658, 616, -133, -116},
|
||||
{875, 442, -141, -151},
|
||||
{386, 741, -23, -80},
|
||||
{390, 1027, -446, 51},
|
||||
{679, 606, -523, 262},
|
||||
{903, 922, -778, -23}
|
||||
};
|
||||
int taps4_8[10][4] = {
|
||||
{648, 803, -444, 16},
|
||||
{972, 620, -576, 7},
|
||||
{561, 967, -499, -5},
|
||||
{585, 762, -468, 144},
|
||||
{596, 619, -182, -9},
|
||||
{895, 459, -176, -153},
|
||||
{557, 722, -126, -129},
|
||||
{601, 839, -523, 105},
|
||||
{562, 709, -499, 251},
|
||||
{803, 872, -695, 43}
|
||||
};
|
||||
int taps4_16[10][4] = {
|
||||
{423, 728, -347, 111},
|
||||
{963, 685, -665, 23},
|
||||
{281, 1024, -480, 216},
|
||||
{640, 596, -437, 78},
|
||||
{429, 669, -259, 99},
|
||||
{740, 646, -415, 23},
|
||||
{568, 771, -346, 40},
|
||||
{404, 833, -486, 209},
|
||||
{398, 712, -423, 307},
|
||||
{939, 935, -887, 17}
|
||||
};
|
||||
int taps4_32[10][4] = {
|
||||
{477, 737, -393, 150},
|
||||
{881, 630, -546, 67},
|
||||
{506, 984, -443, -20},
|
||||
{114, 459, -270, 528},
|
||||
{433, 528, 14, 3},
|
||||
{837, 470, -301, -30},
|
||||
{181, 777, 89, -107},
|
||||
{-29, 716, -232, 259},
|
||||
{589, 646, -495, 255},
|
||||
{740, 884, -728, 77}
|
||||
};
|
||||
|
||||
const int c1 = (bs >= 32) ? taps4_32[mode][0] : ((bs >= 16) ?
|
||||
taps4_16[mode][0] : ((bs >= 8) ? taps4_8[mode][0] : taps4_4[mode][0]));
|
||||
const int c2 = (bs >= 32) ? taps4_32[mode][1] : ((bs >= 16) ?
|
||||
taps4_16[mode][1] : ((bs >= 8) ? taps4_8[mode][1] : taps4_4[mode][1]));
|
||||
const int c3 = (bs >= 32) ? taps4_32[mode][2] : ((bs >= 16) ?
|
||||
taps4_16[mode][2] : ((bs >= 8) ? taps4_8[mode][2] : taps4_4[mode][2]));
|
||||
const int c4 = (bs >= 32) ? taps4_32[mode][3] : ((bs >= 16) ?
|
||||
taps4_16[mode][3] : ((bs >= 8) ? taps4_8[mode][3] : taps4_4[mode][3]));
|
||||
|
||||
k = 0;
|
||||
mean = 0;
|
||||
while (k < bs) {
|
||||
mean = mean + (int)yleft_col[k];
|
||||
mean = mean + (int)yabove_row[k];
|
||||
k++;
|
||||
}
|
||||
mean = (mean + bs) / (2 * bs);
|
||||
|
||||
for (r = 0; r < bs; r++)
|
||||
pred[r + 1][0] = (int)yleft_col[r] - mean;
|
||||
|
||||
for (c = 0; c < 2 * bs + 1; c++)
|
||||
pred[0][c] = (int)yabove_row[c - 1] - mean;
|
||||
|
||||
for (r = 1; r < bs + 1; r++)
|
||||
for (c = 1; c < 2 * bs + 1 - r; c++) {
|
||||
ipred = c1 * pred[r - 1][c] + c2 * pred[r][c - 1]
|
||||
+ c3 * pred[r - 1][c - 1] + c4 * pred[r - 1][c + 1];
|
||||
pred[r][c] = ipred < 0 ? -((-ipred + round_val) >> prec_bits) :
|
||||
((ipred + round_val) >> prec_bits);
|
||||
}
|
||||
|
||||
for (r = 0; r < bs; r++) {
|
||||
for (c = 0; c < bs; c++) {
|
||||
ipred = pred[r + 1][c + 1] + mean;
|
||||
ypred_ptr[c] = clip_pixel(ipred);
|
||||
}
|
||||
ypred_ptr += y_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void build_filter_intra_predictors(const MACROBLOCKD *xd,
|
||||
const uint8_t *ref, int ref_stride,
|
||||
uint8_t *dst, int dst_stride,
|
||||
PREDICTION_MODE mode, TX_SIZE tx_size,
|
||||
int up_available, int left_available,
|
||||
int right_available, int x, int y,
|
||||
int plane) {
|
||||
int i;
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
|
||||
uint8_t *above_row = above_data + 16;
|
||||
const uint8_t *const_above_row = above_row;
|
||||
const int bs = 4 << tx_size;
|
||||
int frame_width, frame_height;
|
||||
int x0, y0;
|
||||
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||
|
||||
// Get current frame pointer, width and height.
|
||||
if (plane == 0) {
|
||||
frame_width = xd->cur_buf->y_width;
|
||||
frame_height = xd->cur_buf->y_height;
|
||||
} else {
|
||||
frame_width = xd->cur_buf->uv_width;
|
||||
frame_height = xd->cur_buf->uv_height;
|
||||
}
|
||||
|
||||
// Get block position in current frame.
|
||||
x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
|
||||
y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
|
||||
|
||||
vpx_memset(left_col, 129, 64);
|
||||
|
||||
// left
|
||||
if (left_available) {
|
||||
if (xd->mb_to_bottom_edge < 0) {
|
||||
/* slower path if the block needs border extension */
|
||||
if (y0 + bs <= frame_height) {
|
||||
for (i = 0; i < bs; ++i)
|
||||
left_col[i] = ref[i * ref_stride - 1];
|
||||
} else {
|
||||
const int extend_bottom = frame_height - y0;
|
||||
for (i = 0; i < extend_bottom; ++i)
|
||||
left_col[i] = ref[i * ref_stride - 1];
|
||||
for (; i < bs; ++i)
|
||||
left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
|
||||
}
|
||||
} else {
|
||||
/* faster path if the block does not need extension */
|
||||
for (i = 0; i < bs; ++i)
|
||||
left_col[i] = ref[i * ref_stride - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(hkuang) do not extend 2*bs pixels for all modes.
|
||||
// above
|
||||
if (up_available) {
|
||||
const uint8_t *above_ref = ref - ref_stride;
|
||||
if (xd->mb_to_right_edge < 0) {
|
||||
/* slower path if the block needs border extension */
|
||||
if (x0 + 2 * bs <= frame_width) {
|
||||
if (right_available && bs == 4) {
|
||||
vpx_memcpy(above_row, above_ref, 2 * bs);
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, bs);
|
||||
vpx_memset(above_row + bs, above_row[bs - 1], bs);
|
||||
}
|
||||
} else if (x0 + bs <= frame_width) {
|
||||
const int r = frame_width - x0;
|
||||
if (right_available && bs == 4) {
|
||||
vpx_memcpy(above_row, above_ref, r);
|
||||
vpx_memset(above_row + r, above_row[r - 1],
|
||||
x0 + 2 * bs - frame_width);
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, bs);
|
||||
vpx_memset(above_row + bs, above_row[bs - 1], bs);
|
||||
}
|
||||
} else if (x0 <= frame_width) {
|
||||
const int r = frame_width - x0;
|
||||
if (right_available && bs == 4) {
|
||||
vpx_memcpy(above_row, above_ref, r);
|
||||
vpx_memset(above_row + r, above_row[r - 1],
|
||||
x0 + 2 * bs - frame_width);
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, r);
|
||||
vpx_memset(above_row + r, above_row[r - 1],
|
||||
x0 + 2 * bs - frame_width);
|
||||
}
|
||||
}
|
||||
above_row[-1] = left_available ? above_ref[-1] : 129;
|
||||
} else {
|
||||
/* faster path if the block does not need extension */
|
||||
if (bs == 4 && right_available && left_available) {
|
||||
const_above_row = above_ref;
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, bs);
|
||||
if (bs == 4 && right_available)
|
||||
vpx_memcpy(above_row + bs, above_ref + bs, bs);
|
||||
else
|
||||
vpx_memset(above_row + bs, above_row[bs - 1], bs);
|
||||
above_row[-1] = left_available ? above_ref[-1] : 129;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vpx_memset(above_row, 127, bs * 2);
|
||||
above_row[-1] = 127;
|
||||
}
|
||||
|
||||
// predict
|
||||
filter_intra_predictors_4tap(dst, dst_stride, bs, const_above_row, left_col,
|
||||
mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
|
||||
TX_SIZE tx_size, PREDICTION_MODE mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
int filterbit,
|
||||
#endif
|
||||
const uint8_t *ref, int ref_stride,
|
||||
uint8_t *dst, int dst_stride,
|
||||
int aoff, int loff, int plane) {
|
||||
@@ -456,8 +675,708 @@ void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
|
||||
const int have_right = ((block_idx & wmask) != wmask);
|
||||
const int x = aoff * 4;
|
||||
const int y = loff * 4;
|
||||
#if CONFIG_FILTERINTRA
|
||||
const int filterflag = is_filter_allowed(mode) && is_filter_enabled(tx_size)
|
||||
&& filterbit;
|
||||
#endif
|
||||
|
||||
assert(bwl >= 0);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (!filterflag) {
|
||||
#endif
|
||||
build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
|
||||
have_top, have_left, have_right, x, y, plane);
|
||||
#if CONFIG_FILTERINTRA
|
||||
} else {
|
||||
build_filter_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode,
|
||||
tx_size, have_top, have_left, have_right, x, y, plane);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
#define MASK_WEIGHT_BITS_INTERINTRA 6
|
||||
|
||||
static int get_masked_weight_interintra(int m) {
|
||||
#define SMOOTHER_LEN_INTERINTRA 32
|
||||
static const uint8_t smoothfn[2 * SMOOTHER_LEN_INTERINTRA + 1] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1,
|
||||
1, 1, 2, 2, 3, 4, 5, 6,
|
||||
8, 9, 12, 14, 17, 21, 24, 28,
|
||||
32,
|
||||
36, 40, 43, 47, 50, 52, 55, 56,
|
||||
58, 59, 60, 61, 62, 62, 63, 63,
|
||||
63, 63, 63, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64,
|
||||
};
|
||||
if (m < -SMOOTHER_LEN_INTERINTRA)
|
||||
return 0;
|
||||
else if (m > SMOOTHER_LEN_INTERINTRA)
|
||||
return (1 << MASK_WEIGHT_BITS_INTERINTRA);
|
||||
else
|
||||
return smoothfn[m + SMOOTHER_LEN_INTERINTRA];
|
||||
}
|
||||
|
||||
static int get_hard_mask_interintra(int m) {
|
||||
return m > 0;
|
||||
}
|
||||
|
||||
// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
|
||||
// The soft mask is obtained by computing f(x, y) and then calling
|
||||
// get_masked_weight(f(x, y)).
|
||||
static const int mask_params_sml_interintra[1 << MASK_BITS_SML_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
};
|
||||
|
||||
static const int mask_params_med_hgtw_interintra[1 << MASK_BITS_MED_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
|
||||
{-1, 2, 2, 1},
|
||||
{ 1, -2, 2, 1},
|
||||
{-1, 2, 2, 3},
|
||||
{ 1, -2, 2, 3},
|
||||
{ 1, 2, 2, 1},
|
||||
{-1, -2, 2, 1},
|
||||
{ 1, 2, 2, 3},
|
||||
{-1, -2, 2, 3},
|
||||
};
|
||||
|
||||
static const int mask_params_med_hltw_interintra[1 << MASK_BITS_MED_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
|
||||
{-2, 1, 1, 2},
|
||||
{ 2, -1, 1, 2},
|
||||
{-2, 1, 3, 2},
|
||||
{ 2, -1, 3, 2},
|
||||
{ 2, 1, 1, 2},
|
||||
{-2, -1, 1, 2},
|
||||
{ 2, 1, 3, 2},
|
||||
{-2, -1, 3, 2},
|
||||
};
|
||||
|
||||
static const int mask_params_med_heqw_interintra[1 << MASK_BITS_MED_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
|
||||
{ 0, 2, 0, 1},
|
||||
{ 0, -2, 0, 1},
|
||||
{ 0, 2, 0, 3},
|
||||
{ 0, -2, 0, 3},
|
||||
{ 2, 0, 1, 0},
|
||||
{-2, 0, 1, 0},
|
||||
{ 2, 0, 3, 0},
|
||||
{-2, 0, 3, 0},
|
||||
};
|
||||
|
||||
static const int mask_params_big_hgtw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
|
||||
{-1, 2, 2, 1},
|
||||
{ 1, -2, 2, 1},
|
||||
{-1, 2, 2, 3},
|
||||
{ 1, -2, 2, 3},
|
||||
{ 1, 2, 2, 1},
|
||||
{-1, -2, 2, 1},
|
||||
{ 1, 2, 2, 3},
|
||||
{-1, -2, 2, 3},
|
||||
|
||||
{-2, 1, 1, 2},
|
||||
{ 2, -1, 1, 2},
|
||||
{-2, 1, 3, 2},
|
||||
{ 2, -1, 3, 2},
|
||||
{ 2, 1, 1, 2},
|
||||
{-2, -1, 1, 2},
|
||||
{ 2, 1, 3, 2},
|
||||
{-2, -1, 3, 2},
|
||||
|
||||
{ 0, 2, 0, 1},
|
||||
{ 0, -2, 0, 1},
|
||||
{ 0, 2, 0, 2},
|
||||
{ 0, -2, 0, 2},
|
||||
{ 0, 2, 0, 3},
|
||||
{ 0, -2, 0, 3},
|
||||
{ 2, 0, 2, 0},
|
||||
{-2, 0, 2, 0},
|
||||
};
|
||||
|
||||
static const int mask_params_big_hltw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
|
||||
{-1, 2, 2, 1},
|
||||
{ 1, -2, 2, 1},
|
||||
{-1, 2, 2, 3},
|
||||
{ 1, -2, 2, 3},
|
||||
{ 1, 2, 2, 1},
|
||||
{-1, -2, 2, 1},
|
||||
{ 1, 2, 2, 3},
|
||||
{-1, -2, 2, 3},
|
||||
|
||||
{-2, 1, 1, 2},
|
||||
{ 2, -1, 1, 2},
|
||||
{-2, 1, 3, 2},
|
||||
{ 2, -1, 3, 2},
|
||||
{ 2, 1, 1, 2},
|
||||
{-2, -1, 1, 2},
|
||||
{ 2, 1, 3, 2},
|
||||
{-2, -1, 3, 2},
|
||||
|
||||
{ 0, 2, 0, 2},
|
||||
{ 0, -2, 0, 2},
|
||||
{ 2, 0, 1, 0},
|
||||
{-2, 0, 1, 0},
|
||||
{ 2, 0, 2, 0},
|
||||
{-2, 0, 2, 0},
|
||||
{ 2, 0, 3, 0},
|
||||
{-2, 0, 3, 0},
|
||||
};
|
||||
|
||||
static const int mask_params_big_heqw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
|
||||
[4] = {
|
||||
{-1, 2, 2, 2},
|
||||
{ 1, -2, 2, 2},
|
||||
{-2, 1, 2, 2},
|
||||
{ 2, -1, 2, 2},
|
||||
{ 2, 1, 2, 2},
|
||||
{-2, -1, 2, 2},
|
||||
{ 1, 2, 2, 2},
|
||||
{-1, -2, 2, 2},
|
||||
|
||||
{-1, 2, 2, 1},
|
||||
{ 1, -2, 2, 1},
|
||||
{-1, 2, 2, 3},
|
||||
{ 1, -2, 2, 3},
|
||||
{ 1, 2, 2, 1},
|
||||
{-1, -2, 2, 1},
|
||||
{ 1, 2, 2, 3},
|
||||
{-1, -2, 2, 3},
|
||||
|
||||
{-2, 1, 1, 2},
|
||||
{ 2, -1, 1, 2},
|
||||
{-2, 1, 3, 2},
|
||||
{ 2, -1, 3, 2},
|
||||
{ 2, 1, 1, 2},
|
||||
{-2, -1, 1, 2},
|
||||
{ 2, 1, 3, 2},
|
||||
{-2, -1, 3, 2},
|
||||
|
||||
{ 0, 2, 0, 1},
|
||||
{ 0, -2, 0, 1},
|
||||
{ 0, 2, 0, 3},
|
||||
{ 0, -2, 0, 3},
|
||||
{ 2, 0, 1, 0},
|
||||
{-2, 0, 1, 0},
|
||||
{ 2, 0, 3, 0},
|
||||
{-2, 0, 3, 0},
|
||||
};
|
||||
|
||||
static const int *get_mask_params_interintra(int mask_index,
|
||||
BLOCK_SIZE sb_type,
|
||||
int h, int w) {
|
||||
const int *a;
|
||||
const int mask_bits = get_mask_bits_interintra(sb_type);
|
||||
|
||||
if (mask_index == MASK_NONE_INTERINTRA)
|
||||
return NULL;
|
||||
|
||||
if (mask_bits == MASK_BITS_SML_INTERINTRA) {
|
||||
a = mask_params_sml_interintra[mask_index];
|
||||
} else if (mask_bits == MASK_BITS_MED_INTERINTRA) {
|
||||
if (h > w)
|
||||
a = mask_params_med_hgtw_interintra[mask_index];
|
||||
else if (h < w)
|
||||
a = mask_params_med_hltw_interintra[mask_index];
|
||||
else
|
||||
a = mask_params_med_heqw_interintra[mask_index];
|
||||
} else if (mask_bits == MASK_BITS_BIG_INTERINTRA) {
|
||||
if (h > w)
|
||||
a = mask_params_big_hgtw_interintra[mask_index];
|
||||
else if (h < w)
|
||||
a = mask_params_big_hltw_interintra[mask_index];
|
||||
else
|
||||
a = mask_params_big_heqw_interintra[mask_index];
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void vp9_generate_masked_weight_interintra(int mask_index,
|
||||
BLOCK_SIZE sb_type,
|
||||
int h, int w,
|
||||
uint8_t *mask, int stride) {
|
||||
int i, j;
|
||||
const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
|
||||
if (!a) return;
|
||||
for (i = 0; i < h; ++i)
|
||||
for (j = 0; j < w; ++j) {
|
||||
int x = (j - (a[2] * w) / 4);
|
||||
int y = (i - (a[3] * h) / 4);
|
||||
int m = a[0] * x + a[1] * y;
|
||||
mask[i * stride + j] = get_masked_weight_interintra(m);
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_generate_hard_mask_interintra(int mask_index, BLOCK_SIZE sb_type,
|
||||
int h, int w, uint8_t *mask, int stride) {
|
||||
int i, j;
|
||||
const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
|
||||
if (!a) return;
|
||||
for (i = 0; i < h; ++i)
|
||||
for (j = 0; j < w; ++j) {
|
||||
int x = (j - (a[2] * w) / 4);
|
||||
int y = (i - (a[3] * h) / 4);
|
||||
int m = a[0] * x + a[1] * y;
|
||||
mask[i * stride + j] = get_hard_mask_interintra(m);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void combine_interintra(PREDICTION_MODE mode,
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
int use_masked_interintra,
|
||||
int mask_index,
|
||||
BLOCK_SIZE bsize,
|
||||
#endif
|
||||
uint8_t *comppred,
|
||||
int compstride,
|
||||
uint8_t *interpred,
|
||||
int interstride,
|
||||
uint8_t *intrapred,
|
||||
int intrastride,
|
||||
int bw, int bh) {
|
||||
static const int scale_bits = 8;
|
||||
static const int scale_max = 256;
|
||||
static const int scale_round = 127;
|
||||
static const int weights1d[64] = {
|
||||
128, 125, 122, 119, 116, 114, 111, 109,
|
||||
107, 105, 103, 101, 99, 97, 96, 94,
|
||||
93, 91, 90, 89, 88, 86, 85, 84,
|
||||
83, 82, 81, 81, 80, 79, 78, 78,
|
||||
77, 76, 76, 75, 75, 74, 74, 73,
|
||||
73, 72, 72, 71, 71, 71, 70, 70,
|
||||
70, 70, 69, 69, 69, 69, 68, 68,
|
||||
68, 68, 68, 67, 67, 67, 67, 67,
|
||||
};
|
||||
|
||||
int size = MAX(bw, bh);
|
||||
int size_scale = (size >= 64 ? 1 :
|
||||
size == 32 ? 2 :
|
||||
size == 16 ? 4 :
|
||||
size == 8 ? 8 : 16);
|
||||
int i, j;
|
||||
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (use_masked_interintra && get_mask_bits_interintra(bsize)) {
|
||||
uint8_t mask[4096];
|
||||
vp9_generate_masked_weight_interintra(mask_index, bsize, bh, bw, mask, bw);
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int m = mask[i * bw + j];
|
||||
comppred[i * compstride + j] =
|
||||
(intrapred[i * intrastride + j] * m +
|
||||
interpred[i * interstride + j] *
|
||||
((1 << MASK_WEIGHT_BITS_INTERINTRA) - m) +
|
||||
(1 << (MASK_WEIGHT_BITS_INTERINTRA - 1))) >>
|
||||
MASK_WEIGHT_BITS_INTERINTRA;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (mode) {
|
||||
case V_PRED:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int scale = weights1d[i * size_scale];
|
||||
comppred[i * compstride + j] =
|
||||
((scale_max - scale) * interpred[i * interstride + j] +
|
||||
scale * intrapred[i * intrastride + j] + scale_round)
|
||||
>> scale_bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case H_PRED:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int scale = weights1d[j * size_scale];
|
||||
comppred[i * compstride + j] =
|
||||
((scale_max - scale) * interpred[i * interstride + j] +
|
||||
scale * intrapred[i * intrastride + j] + scale_round)
|
||||
>> scale_bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D63_PRED:
|
||||
case D117_PRED:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int scale = (weights1d[i * size_scale] * 3 +
|
||||
weights1d[j * size_scale]) >> 2;
|
||||
comppred[i * compstride + j] =
|
||||
((scale_max - scale) * interpred[i * interstride + j] +
|
||||
scale * intrapred[i * intrastride + j] + scale_round)
|
||||
>> scale_bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D207_PRED:
|
||||
case D153_PRED:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int scale = (weights1d[j * size_scale] * 3 +
|
||||
weights1d[i * size_scale]) >> 2;
|
||||
comppred[i * compstride + j] =
|
||||
((scale_max - scale) * interpred[i * interstride + j] +
|
||||
scale * intrapred[i * intrastride + j] + scale_round)
|
||||
>> scale_bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D135_PRED:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int scale = weights1d[(i < j ? i : j) * size_scale];
|
||||
comppred[i * compstride + j] =
|
||||
((scale_max - scale) * interpred[i * interstride + j] +
|
||||
scale * intrapred[i * intrastride + j] + scale_round)
|
||||
>> scale_bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D45_PRED:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
int scale = (weights1d[i * size_scale] +
|
||||
weights1d[j * size_scale]) >> 1;
|
||||
comppred[i * compstride + j] =
|
||||
((scale_max - scale) * interpred[i * interstride + j] +
|
||||
scale * intrapred[i * intrastride + j] + scale_round)
|
||||
>> scale_bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TM_PRED:
|
||||
case DC_PRED:
|
||||
default:
|
||||
for (i = 0; i < bh; ++i) {
|
||||
for (j = 0; j < bw; ++j) {
|
||||
comppred[i * compstride + j] = (interpred[i * interstride + j] +
|
||||
intrapred[i * intrastride + j]) >> 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void build_intra_predictors_for_2nd_block_interintra
|
||||
(const MACROBLOCKD *xd, const uint8_t *ref,
|
||||
int ref_stride, uint8_t *dst, int dst_stride,
|
||||
PREDICTION_MODE mode, TX_SIZE tx_size,
|
||||
int up_available, int left_available,
|
||||
int right_available, int bwltbh,
|
||||
int x, int y, int plane) {
|
||||
int i;
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
|
||||
uint8_t *above_row = above_data + 16;
|
||||
const uint8_t *const_above_row = above_row;
|
||||
const int bs = 4 << tx_size;
|
||||
int frame_width, frame_height;
|
||||
int x0, y0;
|
||||
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||
const uint8_t *ref_fi;
|
||||
int ref_stride_fi;
|
||||
|
||||
// 127 127 127 .. 127 127 127 127 127 127
|
||||
// 129 A B .. Y Z
|
||||
// 129 C D .. W X
|
||||
// 129 E F .. U V
|
||||
// 129 G H .. S T T T T T
|
||||
// ..
|
||||
|
||||
once(init_intra_pred_fn_ptrs);
|
||||
|
||||
// Get current frame pointer, width and height.
|
||||
if (plane == 0) {
|
||||
frame_width = xd->cur_buf->y_width;
|
||||
frame_height = xd->cur_buf->y_height;
|
||||
} else {
|
||||
frame_width = xd->cur_buf->uv_width;
|
||||
frame_height = xd->cur_buf->uv_height;
|
||||
}
|
||||
|
||||
// Get block position in current frame.
|
||||
x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
|
||||
y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
|
||||
|
||||
vpx_memset(left_col, 129, 64);
|
||||
|
||||
// left
|
||||
if (left_available) {
|
||||
if (bwltbh) {
|
||||
ref_fi = ref;
|
||||
ref_stride_fi = ref_stride;
|
||||
} else {
|
||||
ref_fi = dst;
|
||||
ref_stride_fi = dst_stride;
|
||||
}
|
||||
if (xd->mb_to_bottom_edge < 0) {
|
||||
/* slower path if the block needs border extension */
|
||||
if (y0 + bs <= frame_height) {
|
||||
for (i = 0; i < bs; ++i)
|
||||
left_col[i] = ref_fi[i * ref_stride_fi - 1];
|
||||
} else {
|
||||
const int extend_bottom = frame_height - y0;
|
||||
assert(extend_bottom >= 0);
|
||||
for (i = 0; i < extend_bottom; ++i)
|
||||
left_col[i] = ref_fi[i * ref_stride_fi - 1];
|
||||
for (; i < bs; ++i)
|
||||
left_col[i] = ref_fi[(extend_bottom - 1) * ref_stride_fi - 1];
|
||||
}
|
||||
} else {
|
||||
/* faster path if the block does not need extension */
|
||||
for (i = 0; i < bs; ++i)
|
||||
left_col[i] = ref_fi[i * ref_stride_fi - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(hkuang) do not extend 2*bs pixels for all modes.
|
||||
// above
|
||||
if (up_available) {
|
||||
const uint8_t *above_ref;
|
||||
if (bwltbh) {
|
||||
ref_fi = dst;
|
||||
ref_stride_fi = dst_stride;
|
||||
above_row[-1] = left_available ? ref[-ref_stride-1] : 129;
|
||||
} else {
|
||||
ref_fi = ref;
|
||||
ref_stride_fi = ref_stride;
|
||||
above_row[-1] = ref[-ref_stride-1];
|
||||
}
|
||||
above_ref = ref_fi - ref_stride_fi;
|
||||
if (xd->mb_to_right_edge < 0) {
|
||||
/* slower path if the block needs border extension */
|
||||
if (x0 + 2 * bs <= frame_width) {
|
||||
if (right_available && bs == 4) {
|
||||
vpx_memcpy(above_row, above_ref, 2 * bs);
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, bs);
|
||||
vpx_memset(above_row + bs, above_row[bs - 1], bs);
|
||||
}
|
||||
} else if (x0 + bs <= frame_width) {
|
||||
const int r = frame_width - x0;
|
||||
if (right_available && bs == 4) {
|
||||
vpx_memcpy(above_row, above_ref, r);
|
||||
vpx_memset(above_row + r, above_row[r - 1],
|
||||
x0 + 2 * bs - frame_width);
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, bs);
|
||||
vpx_memset(above_row + bs, above_row[bs - 1], bs);
|
||||
}
|
||||
} else if (x0 <= frame_width) {
|
||||
const int r = frame_width - x0;
|
||||
assert(r >= 0);
|
||||
if (right_available && bs == 4) {
|
||||
vpx_memcpy(above_row, above_ref, r);
|
||||
vpx_memset(above_row + r, above_row[r - 1],
|
||||
x0 + 2 * bs - frame_width);
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, r);
|
||||
vpx_memset(above_row + r, above_row[r - 1],
|
||||
x0 + 2 * bs - frame_width);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* faster path if the block does not need extension */
|
||||
if (bs == 4 && right_available && left_available) {
|
||||
const_above_row = above_ref;
|
||||
} else {
|
||||
vpx_memcpy(above_row, above_ref, bs);
|
||||
if (bs == 4 && right_available)
|
||||
vpx_memcpy(above_row + bs, above_ref + bs, bs);
|
||||
else
|
||||
vpx_memset(above_row + bs, above_row[bs - 1], bs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vpx_memset(above_row, 127, bs * 2);
|
||||
above_row[-1] = 127;
|
||||
}
|
||||
|
||||
// predict
|
||||
if (mode == DC_PRED) {
|
||||
dc_pred[left_available][up_available][tx_size](dst, dst_stride,
|
||||
const_above_row, left_col);
|
||||
} else {
|
||||
pred[mode][tx_size](dst, dst_stride, const_above_row, left_col);
|
||||
}
|
||||
}
|
||||
|
||||
// Break down rectangular intra prediction for joint spatio-temporal prediction
|
||||
// into two square intra predictions.
|
||||
static void build_intra_predictors_for_interintra(MACROBLOCKD *xd,
|
||||
uint8_t *src, int src_stride,
|
||||
uint8_t *pred_ptr, int stride,
|
||||
PREDICTION_MODE mode,
|
||||
int bw, int bh,
|
||||
int up_available, int left_available,
|
||||
int right_available, int plane) {
|
||||
if (bw == bh) {
|
||||
build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
|
||||
mode, intra_size_log2_for_interintra(bw),
|
||||
up_available, left_available, right_available,
|
||||
0, 0, plane);
|
||||
} else if (bw < bh) {
|
||||
uint8_t *src_bottom = src + bw * src_stride;
|
||||
uint8_t *pred_ptr_bottom = pred_ptr + bw * stride;
|
||||
build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
|
||||
mode, intra_size_log2_for_interintra(bw),
|
||||
up_available, left_available, right_available,
|
||||
0, 0, plane);
|
||||
build_intra_predictors_for_2nd_block_interintra(xd, src_bottom, src_stride,
|
||||
pred_ptr_bottom, stride,
|
||||
mode, intra_size_log2_for_interintra(bw),
|
||||
up_available, left_available, 0, 1,
|
||||
0, bw, plane);
|
||||
} else {
|
||||
uint8_t *src_right = src + bh;
|
||||
uint8_t *pred_ptr_right = pred_ptr + bh;
|
||||
build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
|
||||
mode, intra_size_log2_for_interintra(bh),
|
||||
up_available, left_available, 1,
|
||||
0, 0, plane);
|
||||
build_intra_predictors_for_2nd_block_interintra(xd, src_right, src_stride,
|
||||
pred_ptr_right, stride,
|
||||
mode, intra_size_log2_for_interintra(bh),
|
||||
up_available, left_available, right_available, 0,
|
||||
bh, 0, plane);
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
|
||||
uint8_t *ypred,
|
||||
int ystride,
|
||||
BLOCK_SIZE bsize) {
|
||||
int bw = 4 << b_width_log2(bsize);
|
||||
int bh = 4 << b_height_log2(bsize);
|
||||
uint8_t intrapredictor[4096];
|
||||
build_intra_predictors_for_interintra(
|
||||
xd, xd->plane[0].dst.buf, xd->plane[0].dst.stride,
|
||||
intrapredictor, bw,
|
||||
xd->mi[0]->mbmi.interintra_mode, bw, bh,
|
||||
xd->up_available, xd->left_available, 0, 0);
|
||||
combine_interintra(xd->mi[0]->mbmi.interintra_mode,
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
xd->mi[0]->mbmi.use_masked_interintra,
|
||||
xd->mi[0]->mbmi.interintra_mask_index,
|
||||
bsize,
|
||||
#endif
|
||||
xd->plane[0].dst.buf, xd->plane[0].dst.stride,
|
||||
ypred, ystride, intrapredictor, bw, bw, bh);
|
||||
}
|
||||
|
||||
void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
|
||||
uint8_t *upred,
|
||||
uint8_t *vpred,
|
||||
int ustride, int vstride,
|
||||
BLOCK_SIZE bsize) {
|
||||
int bwl = b_width_log2(bsize), bw = 2 << bwl;
|
||||
int bhl = b_height_log2(bsize), bh = 2 << bhl;
|
||||
uint8_t uintrapredictor[1024];
|
||||
uint8_t vintrapredictor[1024];
|
||||
build_intra_predictors_for_interintra(
|
||||
xd, xd->plane[1].dst.buf, xd->plane[1].dst.stride,
|
||||
uintrapredictor, bw,
|
||||
xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
|
||||
xd->up_available, xd->left_available, 0, 1);
|
||||
build_intra_predictors_for_interintra(
|
||||
xd, xd->plane[2].dst.buf, xd->plane[1].dst.stride,
|
||||
vintrapredictor, bw,
|
||||
xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
|
||||
xd->up_available, xd->left_available, 0, 2);
|
||||
combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
xd->mi[0]->mbmi.use_masked_interintra,
|
||||
xd->mi[0]->mbmi.interintra_uv_mask_index,
|
||||
bsize,
|
||||
#endif
|
||||
xd->plane[1].dst.buf, xd->plane[1].dst.stride,
|
||||
upred, ustride, uintrapredictor, bw, bw, bh);
|
||||
combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
xd->mi[0]->mbmi.use_masked_interintra,
|
||||
xd->mi[0]->mbmi.interintra_uv_mask_index,
|
||||
bsize,
|
||||
#endif
|
||||
xd->plane[2].dst.buf, xd->plane[2].dst.stride,
|
||||
vpred, vstride, vintrapredictor, bw, bw, bh);
|
||||
}
|
||||
|
||||
void vp9_build_interintra_predictors(MACROBLOCKD *xd,
|
||||
uint8_t *ypred,
|
||||
uint8_t *upred,
|
||||
uint8_t *vpred,
|
||||
int ystride, int ustride, int vstride,
|
||||
BLOCK_SIZE bsize) {
|
||||
vp9_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
|
||||
vp9_build_interintra_predictors_sbuv(xd, upred, vpred,
|
||||
ustride, vstride, bsize);
|
||||
}
|
||||
#endif
|
||||
|
@@ -20,9 +20,37 @@ extern "C" {
|
||||
|
||||
void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
|
||||
TX_SIZE tx_size, PREDICTION_MODE mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
int filterbit,
|
||||
#endif
|
||||
const uint8_t *ref, int ref_stride,
|
||||
uint8_t *dst, int dst_stride,
|
||||
int aoff, int loff, int plane);
|
||||
#if CONFIG_INTERINTRA
|
||||
void vp9_build_interintra_predictors(MACROBLOCKD *xd,
|
||||
uint8_t *ypred,
|
||||
uint8_t *upred,
|
||||
uint8_t *vpred,
|
||||
int ystride,
|
||||
int ustride,
|
||||
int vstride,
|
||||
BLOCK_SIZE bsize);
|
||||
void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
|
||||
uint8_t *ypred,
|
||||
int ystride,
|
||||
BLOCK_SIZE bsize);
|
||||
void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
|
||||
uint8_t *upred,
|
||||
uint8_t *vpred,
|
||||
int ustride, int vstride,
|
||||
BLOCK_SIZE bsize);
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
void vp9_generate_masked_weight_interintra(int mask_index,
|
||||
BLOCK_SIZE sb_type,
|
||||
int h, int w,
|
||||
uint8_t *mask, int stride);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -506,6 +506,125 @@ specialize qw/vp9_sub_pixel_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
|
||||
add_proto qw/unsigned int vp9_sub_pixel_avg_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, const uint8_t *second_pred";
|
||||
specialize qw/vp9_sub_pixel_avg_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
|
||||
|
||||
if ((vpx_config("CONFIG_MASKED_INTERINTER") eq "yes") || ((vpx_config("CONFIG_INTERINTRA") eq "yes") && (vpx_config("CONFIG_MASKED_INTERINTRA") eq "yes"))) {
|
||||
add_proto qw/unsigned int vp9_masked_variance32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance32x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masdctked_variance16x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance64x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance32x64/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance32x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance64x64/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance16x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance16x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance8x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance8x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance8x4/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance4x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_variance4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_variance4x4/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance64x64/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance32x64/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance64x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance32x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance16x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance32x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance16x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance8x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance16x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance8x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance8x4/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance4x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
|
||||
specialize qw/vp9_masked_sub_pixel_variance4x4/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad64x64/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad32x64/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad64x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad32x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad16x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad32x32/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad16x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad16x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad8x16/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad8x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad8x4/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad4x8/;
|
||||
|
||||
add_proto qw/unsigned int vp9_masked_sad4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
|
||||
specialize qw/vp9_masked_sad4x4/;
|
||||
}
|
||||
|
||||
# TODO(jingning): need to convert 8x4/4x8 functions into mmx/sse form
|
||||
add_proto qw/unsigned int vp9_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse";
|
||||
specialize qw/vp9_sub_pixel_variance8x4/, "$sse2_x86inc", "$ssse3_x86inc";
|
||||
@@ -714,9 +833,6 @@ specialize qw/vp9_block_error avx2/, "$sse2_x86inc";
|
||||
add_proto qw/void vp9_subtract_block/, "int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride";
|
||||
specialize qw/vp9_subtract_block/, "$sse2_x86inc";
|
||||
|
||||
add_proto qw/void vp9_quantize_fp/, "const int16_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr, const int16_t *dequant_ptr, int zbin_oq_value, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
|
||||
specialize qw/vp9_quantize_fp/, "$ssse3_x86_64";
|
||||
|
||||
add_proto qw/void vp9_quantize_b/, "const int16_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr, const int16_t *dequant_ptr, int zbin_oq_value, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
|
||||
specialize qw/vp9_quantize_b/, "$ssse3_x86_64";
|
||||
|
||||
|
@@ -33,6 +33,14 @@ static int get_fixed_point_scale_factor(int other_size, int this_size) {
|
||||
return (other_size << REF_SCALE_SHIFT) / this_size;
|
||||
}
|
||||
|
||||
static int check_scale_factors(int other_w, int other_h,
|
||||
int this_w, int this_h) {
|
||||
return 2 * this_w >= other_w &&
|
||||
2 * this_h >= other_h &&
|
||||
this_w <= 16 * other_w &&
|
||||
this_h <= 16 * other_h;
|
||||
}
|
||||
|
||||
MV32 vp9_scale_mv(const MV *mv, int x, int y, const struct scale_factors *sf) {
|
||||
const int x_off_q4 = scaled_x(x << SUBPEL_BITS, sf) & SUBPEL_MASK;
|
||||
const int y_off_q4 = scaled_y(y << SUBPEL_BITS, sf) & SUBPEL_MASK;
|
||||
@@ -46,7 +54,7 @@ MV32 vp9_scale_mv(const MV *mv, int x, int y, const struct scale_factors *sf) {
|
||||
void vp9_setup_scale_factors_for_frame(struct scale_factors *sf,
|
||||
int other_w, int other_h,
|
||||
int this_w, int this_h) {
|
||||
if (!valid_ref_frame_size(other_w, other_h, this_w, this_h)) {
|
||||
if (!check_scale_factors(other_w, other_h, this_w, this_h)) {
|
||||
sf->x_scale_fp = REF_INVALID_SCALE;
|
||||
sf->y_scale_fp = REF_INVALID_SCALE;
|
||||
return;
|
||||
|
@@ -50,14 +50,6 @@ static INLINE int vp9_is_scaled(const struct scale_factors *sf) {
|
||||
(sf->x_scale_fp != REF_NO_SCALE || sf->y_scale_fp != REF_NO_SCALE);
|
||||
}
|
||||
|
||||
static INLINE int valid_ref_frame_size(int ref_width, int ref_height,
|
||||
int this_width, int this_height) {
|
||||
return 2 * this_width >= ref_width &&
|
||||
2 * this_height >= ref_height &&
|
||||
this_width <= 16 * ref_width &&
|
||||
this_height <= 16 * ref_height;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -254,11 +254,24 @@ static void predict_and_reconstruct_intra_block(int plane, int block,
|
||||
: mi->mbmi.uv_mode;
|
||||
int x, y;
|
||||
uint8_t *dst;
|
||||
#if CONFIG_FILTERINTRA
|
||||
int fbit;
|
||||
if (plane == 0)
|
||||
if (mi->mbmi.sb_type < BLOCK_8X8)
|
||||
fbit = mi->b_filter_info[block];
|
||||
else
|
||||
fbit = is_filter_enabled(tx_size) ? mi->mbmi.filterbit : 0;
|
||||
else
|
||||
fbit = is_filter_enabled(tx_size) ? mi->mbmi.uv_filterbit : 0;
|
||||
#endif
|
||||
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
|
||||
dst = &pd->dst.buf[4 * y * pd->dst.stride + 4 * x];
|
||||
|
||||
vp9_predict_intra_block(xd, block >> (tx_size << 1),
|
||||
b_width_log2(plane_bsize), tx_size, mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
fbit,
|
||||
#endif
|
||||
dst, pd->dst.stride, dst, pd->dst.stride,
|
||||
x, y, plane);
|
||||
|
||||
@@ -322,6 +335,84 @@ static MB_MODE_INFO *set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
return &xd->mi[0]->mbmi;
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static void set_offsets_extend(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
BLOCK_SIZE top_bsize,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori) {
|
||||
const int bw = num_8x8_blocks_wide_lookup[top_bsize];
|
||||
const int bh = num_8x8_blocks_high_lookup[top_bsize];
|
||||
const int offset = mi_row * cm->mi_stride + mi_col;
|
||||
|
||||
xd->mi = cm->mi_grid_visible + offset;
|
||||
xd->mi[0] = &cm->mi[offset];
|
||||
|
||||
set_mi_row_col(xd, tile, mi_row_ori, bh, mi_col_ori, bw,
|
||||
cm->mi_rows, cm->mi_cols);
|
||||
}
|
||||
|
||||
static void set_mb_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
BLOCK_SIZE bsize, int mi_row, int mi_col) {
|
||||
const int bw = num_8x8_blocks_wide_lookup[bsize];
|
||||
const int bh = num_8x8_blocks_high_lookup[bsize];
|
||||
const int x_mis = MIN(bw, cm->mi_cols - mi_col);
|
||||
const int y_mis = MIN(bh, cm->mi_rows - mi_row);
|
||||
const int offset = mi_row * cm->mi_stride + mi_col;
|
||||
int x, y;
|
||||
|
||||
xd->mi = cm->mi_grid_visible + offset;
|
||||
xd->mi[0] = &cm->mi[offset];
|
||||
xd->mi[0]->mbmi.sb_type = bsize;
|
||||
for (y = 0; y < y_mis; ++y)
|
||||
for (x = !y; x < x_mis; ++x)
|
||||
xd->mi[y * cm->mi_stride + x] = xd->mi[0];
|
||||
|
||||
set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);
|
||||
}
|
||||
|
||||
static void set_offsets_topblock(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
BLOCK_SIZE bsize, int mi_row, int mi_col) {
|
||||
const int bw = num_8x8_blocks_wide_lookup[bsize];
|
||||
const int bh = num_8x8_blocks_high_lookup[bsize];
|
||||
const int offset = mi_row * cm->mi_stride + mi_col;
|
||||
|
||||
xd->mi = cm->mi_grid_visible + offset;
|
||||
xd->mi[0] = &cm->mi[offset];
|
||||
|
||||
set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);
|
||||
|
||||
vp9_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
|
||||
}
|
||||
|
||||
static void set_param_topblock(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
BLOCK_SIZE bsize, int mi_row, int mi_col,
|
||||
#if CONFIG_EXT_TX
|
||||
int txfm,
|
||||
#endif
|
||||
int skip) {
|
||||
const int bw = num_8x8_blocks_wide_lookup[bsize];
|
||||
const int bh = num_8x8_blocks_high_lookup[bsize];
|
||||
const int x_mis = MIN(bw, cm->mi_cols - mi_col);
|
||||
const int y_mis = MIN(bh, cm->mi_rows - mi_row);
|
||||
const int offset = mi_row * cm->mi_stride + mi_col;
|
||||
int x, y;
|
||||
|
||||
xd->mi = cm->mi_grid_visible + offset;
|
||||
xd->mi[0] = &cm->mi[offset];
|
||||
|
||||
for (y = 0; y < y_mis; ++y)
|
||||
for (x = 0; x < x_mis; ++x) {
|
||||
xd->mi[y * cm->mi_stride + x]->mbmi.skip = skip;
|
||||
#if CONFIG_EXT_TX
|
||||
xd->mi[y * cm->mi_stride + x]->mbmi.ext_txfrm = txfm;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
int idx, int mi_row, int mi_col) {
|
||||
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||
@@ -335,14 +426,246 @@ static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
xd->corrupted |= ref_buffer->buf->corrupted;
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static void dec_predict_b_extend(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori,
|
||||
BLOCK_SIZE top_bsize) {
|
||||
set_offsets_extend(cm, xd, tile, top_bsize, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori);
|
||||
|
||||
set_ref(cm, xd, 0, mi_row_ori, mi_col_ori);
|
||||
if (has_second_ref(&xd->mi[0]->mbmi))
|
||||
set_ref(cm, xd, 1, mi_row_ori, mi_col_ori);
|
||||
xd->mi[0]->mbmi.tx_size = b_width_log2(top_bsize);
|
||||
#if !CONFIG_MASKED_INTERINTER
|
||||
vp9_dec_build_inter_predictors_sb(xd, mi_row_ori, mi_col_ori, top_bsize);
|
||||
#else
|
||||
vp9_dec_build_inter_predictors_sb_extend(xd, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori, top_bsize);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dec_predict_b_sub8x8_extend(VP9_COMMON *const cm,
|
||||
MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori,
|
||||
BLOCK_SIZE top_bsize,
|
||||
PARTITION_TYPE partition) {
|
||||
set_offsets_extend(cm, xd, tile, top_bsize, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori);
|
||||
|
||||
set_ref(cm, xd, 0, mi_row_ori, mi_col_ori);
|
||||
if (has_second_ref(&xd->mi[0]->mbmi))
|
||||
set_ref(cm, xd, 1, mi_row_ori, mi_col_ori);
|
||||
xd->mi[0]->mbmi.tx_size = b_width_log2(top_bsize);
|
||||
vp9_dec_build_inter_predictors_sby_sub8x8_extend(xd, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
top_bsize, partition);
|
||||
vp9_dec_build_inter_predictors_sbuv_sub8x8_extend(xd,
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
mi_row, mi_col,
|
||||
#endif
|
||||
mi_row_ori, mi_col_ori,
|
||||
top_bsize);
|
||||
}
|
||||
|
||||
static void dec_predict_sb_complex(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
int mi_row, int mi_col,
|
||||
int mi_row_ori, int mi_col_ori,
|
||||
BLOCK_SIZE bsize, BLOCK_SIZE top_bsize,
|
||||
uint8_t *dst_buf[3], int dst_stride[3]) {
|
||||
const int bsl = b_width_log2(bsize), hbs = (1 << bsl) / 4;
|
||||
PARTITION_TYPE partition;
|
||||
BLOCK_SIZE subsize;
|
||||
MB_MODE_INFO *mbmi;
|
||||
int i, offset = mi_row * cm->mi_stride + mi_col;
|
||||
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf1, MAX_MB_PLANE * 32 * 32);
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf2, MAX_MB_PLANE * 32 * 32);
|
||||
DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf3, MAX_MB_PLANE * 32 * 32);
|
||||
uint8_t *dst_buf1[3] = {tmp_buf1, tmp_buf1 + 32 * 32, tmp_buf1 + 2 * 32 * 32};
|
||||
uint8_t *dst_buf2[3] = {tmp_buf2, tmp_buf2 + 32 * 32, tmp_buf2 + 2 * 32 * 32};
|
||||
uint8_t *dst_buf3[3] = {tmp_buf3, tmp_buf3 + 32 * 32, tmp_buf3 + 2 * 32 * 32};
|
||||
int dst_stride1[3] = {32, 32, 32};
|
||||
int dst_stride2[3] = {32, 32, 32};
|
||||
int dst_stride3[3] = {32, 32, 32};
|
||||
|
||||
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
||||
return;
|
||||
|
||||
xd->mi = cm->mi_grid_visible + offset;
|
||||
xd->mi[0] = &cm->mi[offset];
|
||||
mbmi = &xd->mi[0]->mbmi;
|
||||
partition = partition_lookup[bsl][mbmi->sb_type];
|
||||
subsize = get_subsize(bsize, partition);
|
||||
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
xd->plane[i].dst.buf = dst_buf[i];
|
||||
xd->plane[i].dst.stride = dst_stride[i];
|
||||
}
|
||||
|
||||
switch (partition) {
|
||||
case PARTITION_NONE:
|
||||
assert(bsize < top_bsize);
|
||||
dec_predict_b_extend(cm, xd, tile, mi_row, mi_col, mi_row_ori, mi_col_ori,
|
||||
top_bsize);
|
||||
break;
|
||||
case PARTITION_HORZ:
|
||||
if (bsize > BLOCK_8X8) {
|
||||
dec_predict_b_extend(cm, xd, tile, mi_row, mi_col, mi_row_ori,
|
||||
mi_col_ori, top_bsize);
|
||||
} else {
|
||||
dec_predict_b_sub8x8_extend(cm, xd, tile, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
top_bsize, partition);
|
||||
}
|
||||
if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
xd->plane[i].dst.buf = tmp_buf1 + i * 32 * 32;
|
||||
xd->plane[i].dst.stride = 32;
|
||||
}
|
||||
dec_predict_b_extend(cm, xd, tile, mi_row + hbs, mi_col,
|
||||
mi_row_ori, mi_col_ori, top_bsize);
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
xd->plane[i].dst.buf = dst_buf[i];
|
||||
xd->plane[i].dst.stride = dst_stride[i];
|
||||
vp9_build_masked_inter_predictor_complex(dst_buf[i], dst_stride[i],
|
||||
dst_buf1[i], dst_stride1[i],
|
||||
i,
|
||||
mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
bsize, top_bsize,
|
||||
PARTITION_HORZ);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PARTITION_VERT:
|
||||
if (bsize > BLOCK_8X8) {
|
||||
dec_predict_b_extend(cm, xd, tile, mi_row, mi_col, mi_row_ori,
|
||||
mi_col_ori, top_bsize);
|
||||
} else {
|
||||
dec_predict_b_sub8x8_extend(cm, xd, tile, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
top_bsize, partition);
|
||||
}
|
||||
if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
xd->plane[i].dst.buf = tmp_buf1 + i * 32 * 32;
|
||||
xd->plane[i].dst.stride = 32;
|
||||
}
|
||||
dec_predict_b_extend(cm, xd, tile, mi_row, mi_col + hbs, mi_row_ori,
|
||||
mi_col_ori, top_bsize);
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
xd->plane[i].dst.buf = dst_buf[i];
|
||||
xd->plane[i].dst.stride = dst_stride[i];
|
||||
vp9_build_masked_inter_predictor_complex(dst_buf[i], dst_stride[i],
|
||||
dst_buf1[i], dst_stride1[i],
|
||||
i,
|
||||
mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
bsize, top_bsize,
|
||||
PARTITION_VERT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PARTITION_SPLIT:
|
||||
if (bsize == BLOCK_8X8) {
|
||||
dec_predict_b_sub8x8_extend(cm, xd, tile, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
top_bsize, partition);
|
||||
} else {
|
||||
dec_predict_sb_complex(cm, xd, tile, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori, subsize, top_bsize,
|
||||
dst_buf, dst_stride);
|
||||
if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols)
|
||||
dec_predict_sb_complex(cm, xd, tile, mi_row, mi_col + hbs,
|
||||
mi_row_ori, mi_col_ori, subsize, top_bsize,
|
||||
dst_buf1, dst_stride1);
|
||||
if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols)
|
||||
dec_predict_sb_complex(cm, xd, tile, mi_row + hbs, mi_col,
|
||||
mi_row_ori, mi_col_ori, subsize, top_bsize,
|
||||
dst_buf2, dst_stride2);
|
||||
if (mi_row + hbs < cm->mi_rows && mi_col + hbs < cm->mi_cols)
|
||||
dec_predict_sb_complex(cm, xd, tile, mi_row + hbs, mi_col + hbs,
|
||||
mi_row_ori, mi_col_ori, subsize, top_bsize,
|
||||
dst_buf3, dst_stride3);
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols) {
|
||||
vp9_build_masked_inter_predictor_complex(dst_buf[i], dst_stride[i],
|
||||
dst_buf1[i],
|
||||
dst_stride1[i],
|
||||
i, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
bsize, top_bsize,
|
||||
PARTITION_VERT);
|
||||
if (mi_row + hbs < cm->mi_rows) {
|
||||
vp9_build_masked_inter_predictor_complex(dst_buf2[i],
|
||||
dst_stride2[i],
|
||||
dst_buf3[i],
|
||||
dst_stride3[i],
|
||||
i, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
bsize, top_bsize,
|
||||
PARTITION_VERT);
|
||||
vp9_build_masked_inter_predictor_complex(dst_buf[i],
|
||||
dst_stride[i],
|
||||
dst_buf2[i],
|
||||
dst_stride2[i],
|
||||
i, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
bsize, top_bsize,
|
||||
PARTITION_HORZ);
|
||||
}
|
||||
} else if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols) {
|
||||
vp9_build_masked_inter_predictor_complex(dst_buf[i],
|
||||
dst_stride[i],
|
||||
dst_buf2[i],
|
||||
dst_stride2[i],
|
||||
i, mi_row, mi_col,
|
||||
mi_row_ori, mi_col_ori,
|
||||
bsize, top_bsize,
|
||||
PARTITION_HORZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void decode_block(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col,
|
||||
vp9_reader *r, BLOCK_SIZE bsize) {
|
||||
const int less8x8 = bsize < BLOCK_8X8;
|
||||
#if !CONFIG_SUPERTX
|
||||
MB_MODE_INFO *mbmi = set_offsets(cm, xd, tile, bsize, mi_row, mi_col);
|
||||
vp9_read_mode_info(cm, xd, tile, mi_row, mi_col, r);
|
||||
#else
|
||||
MB_MODE_INFO *mbmi;
|
||||
if (!supertx_enabled) {
|
||||
mbmi = set_offsets(cm, xd, tile, bsize, mi_row, mi_col);
|
||||
} else {
|
||||
set_mb_offsets(cm, xd, tile, bsize, mi_row, mi_col);
|
||||
}
|
||||
#endif
|
||||
vp9_read_mode_info(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r);
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
if (!supertx_enabled) {
|
||||
#endif
|
||||
if (less8x8)
|
||||
bsize = BLOCK_8X8;
|
||||
|
||||
@@ -376,6 +699,9 @@ static void decode_block(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
mbmi->skip = 1; // skip loopfilter
|
||||
}
|
||||
}
|
||||
#if CONFIG_SUPERTX
|
||||
}
|
||||
#endif
|
||||
|
||||
xd->corrupted |= vp9_reader_has_error(r);
|
||||
}
|
||||
@@ -406,49 +732,161 @@ static PARTITION_TYPE read_partition(VP9_COMMON *cm, MACROBLOCKD *xd, int hbs,
|
||||
|
||||
static void decode_partition(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
#if CONFIG_SUPERTX
|
||||
int read_token, int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col,
|
||||
vp9_reader* r, BLOCK_SIZE bsize) {
|
||||
const int hbs = num_8x8_blocks_wide_lookup[bsize] / 2;
|
||||
PARTITION_TYPE partition;
|
||||
BLOCK_SIZE subsize, uv_subsize;
|
||||
BLOCK_SIZE subsize;
|
||||
#if CONFIG_SUPERTX
|
||||
int skip = 0;
|
||||
#if CONFIG_EXT_TX
|
||||
int txfm = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
||||
return;
|
||||
|
||||
partition = read_partition(cm, xd, hbs, mi_row, mi_col, bsize, r);
|
||||
subsize = get_subsize(bsize, partition);
|
||||
uv_subsize = ss_size_lookup[subsize][cm->subsampling_x][cm->subsampling_y];
|
||||
if (subsize >= BLOCK_8X8 && uv_subsize == BLOCK_INVALID)
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Invalid block size.");
|
||||
#if CONFIG_SUPERTX
|
||||
if (cm->frame_type != KEY_FRAME &&
|
||||
partition != PARTITION_NONE &&
|
||||
bsize <= BLOCK_32X32 &&
|
||||
!supertx_enabled) {
|
||||
TX_SIZE supertx_size = b_width_log2(bsize);
|
||||
if (partition == PARTITION_SPLIT) {
|
||||
supertx_enabled = vp9_read(r, cm->fc.supertxsplit_prob[supertx_size]);
|
||||
cm->counts.supertxsplit[supertx_size][supertx_enabled]++;
|
||||
} else {
|
||||
supertx_enabled = vp9_read(r, cm->fc.supertx_prob[supertx_size]);
|
||||
cm->counts.supertx[supertx_size][supertx_enabled]++;
|
||||
}
|
||||
}
|
||||
if (supertx_enabled && read_token) {
|
||||
int offset = mi_row * cm->mi_stride + mi_col;
|
||||
xd->mi = cm->mi_grid_visible + offset;
|
||||
xd->mi[0] = &cm->mi[offset];
|
||||
set_mi_row_col(xd, tile, mi_row, num_8x8_blocks_high_lookup[bsize],
|
||||
mi_col, num_8x8_blocks_wide_lookup[bsize],
|
||||
cm->mi_rows, cm->mi_cols);
|
||||
set_skip_context(xd, mi_row, mi_col);
|
||||
// Here we assume mbmi->segment_id = 0
|
||||
skip = read_skip(cm, xd, 0, r);
|
||||
if (skip)
|
||||
reset_skip_context(xd, bsize);
|
||||
#if CONFIG_EXT_TX
|
||||
if (bsize <= BLOCK_16X16 && !skip) {
|
||||
txfm = vp9_read(r, cm->fc.ext_tx_prob);
|
||||
if (!cm->frame_parallel_decoding_mode)
|
||||
++cm->counts.ext_tx[txfm];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (subsize < BLOCK_8X8) {
|
||||
decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
|
||||
decode_block(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r, subsize);
|
||||
} else {
|
||||
switch (partition) {
|
||||
case PARTITION_NONE:
|
||||
decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
|
||||
decode_block(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r, subsize);
|
||||
break;
|
||||
case PARTITION_HORZ:
|
||||
decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
|
||||
decode_block(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r, subsize);
|
||||
if (mi_row + hbs < cm->mi_rows)
|
||||
decode_block(cm, xd, tile, mi_row + hbs, mi_col, r, subsize);
|
||||
decode_block(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row + hbs, mi_col, r, subsize);
|
||||
break;
|
||||
case PARTITION_VERT:
|
||||
decode_block(cm, xd, tile, mi_row, mi_col, r, subsize);
|
||||
decode_block(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r, subsize);
|
||||
if (mi_col + hbs < cm->mi_cols)
|
||||
decode_block(cm, xd, tile, mi_row, mi_col + hbs, r, subsize);
|
||||
decode_block(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col + hbs, r, subsize);
|
||||
break;
|
||||
case PARTITION_SPLIT:
|
||||
decode_partition(cm, xd, tile, mi_row, mi_col, r, subsize);
|
||||
decode_partition(cm, xd, tile, mi_row, mi_col + hbs, r, subsize);
|
||||
decode_partition(cm, xd, tile, mi_row + hbs, mi_col, r, subsize);
|
||||
decode_partition(cm, xd, tile, mi_row + hbs, mi_col + hbs, r, subsize);
|
||||
decode_partition(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r, subsize);
|
||||
decode_partition(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col + hbs, r, subsize);
|
||||
decode_partition(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row + hbs, mi_col, r, subsize);
|
||||
decode_partition(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row + hbs, mi_col + hbs, r, subsize);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Invalid partition type");
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
if (supertx_enabled && read_token) {
|
||||
uint8_t *dst_buf[3];
|
||||
int dst_stride[3], i;
|
||||
|
||||
vp9_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
|
||||
for (i = 0; i < MAX_MB_PLANE; i++) {
|
||||
dst_buf[i] = xd->plane[i].dst.buf;
|
||||
dst_stride[i] = xd->plane[i].dst.stride;
|
||||
}
|
||||
dec_predict_sb_complex(cm, xd, tile, mi_row, mi_col, mi_row, mi_col,
|
||||
bsize, bsize, dst_buf, dst_stride);
|
||||
|
||||
if (!skip) {
|
||||
int eobtotal = 0;
|
||||
struct inter_args arg = { cm, xd, r, &eobtotal };
|
||||
set_offsets_topblock(cm, xd, tile, bsize, mi_row, mi_col);
|
||||
#if CONFIG_EXT_TX
|
||||
xd->mi[0]->mbmi.ext_txfrm = txfm;
|
||||
#endif
|
||||
vp9_foreach_transformed_block(xd, bsize, reconstruct_inter_block, &arg);
|
||||
if (!(subsize < BLOCK_8X8) && eobtotal == 0)
|
||||
skip = 1;
|
||||
}
|
||||
set_param_topblock(cm, xd, bsize, mi_row, mi_col,
|
||||
#if CONFIG_EXT_TX
|
||||
txfm,
|
||||
#endif
|
||||
skip);
|
||||
}
|
||||
#endif
|
||||
|
||||
// update partition context
|
||||
if (bsize >= BLOCK_8X8 &&
|
||||
(bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
|
||||
@@ -621,7 +1059,6 @@ static void setup_display_size(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
|
||||
}
|
||||
|
||||
static void apply_frame_size(VP9_COMMON *cm, int width, int height) {
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
if (cm->width != width || cm->height != height) {
|
||||
// Change in frame size.
|
||||
// TODO(agrange) Don't test width/height, check overall size.
|
||||
@@ -641,8 +1078,8 @@ static void apply_frame_size(VP9_COMMON *cm, int width, int height) {
|
||||
if (vp9_realloc_frame_buffer(
|
||||
get_frame_new_buffer(cm), cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y, VP9_DEC_BORDER_IN_PIXELS,
|
||||
&pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, pool->get_fb_cb,
|
||||
pool->cb_priv)) {
|
||||
&cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer, cm->get_fb_cb,
|
||||
cm->cb_priv)) {
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate frame buffer");
|
||||
}
|
||||
@@ -672,17 +1109,9 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm,
|
||||
if (!found)
|
||||
read_frame_size(rb, &width, &height);
|
||||
|
||||
// Check that each of the frames that this frame references has valid
|
||||
// dimensions.
|
||||
for (i = 0; i < REFS_PER_FRAME; ++i) {
|
||||
RefBuffer *const ref_frame = &cm->frame_refs[i];
|
||||
const int ref_width = ref_frame->buf->y_width;
|
||||
const int ref_height = ref_frame->buf->y_height;
|
||||
|
||||
if (!valid_ref_frame_size(ref_width, ref_height, width, height))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Referenced frame has invalid size");
|
||||
}
|
||||
if (width <= 0 || height <= 0)
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Referenced frame with invalid size");
|
||||
|
||||
apply_frame_size(cm, width, height);
|
||||
setup_display_size(cm, rb);
|
||||
@@ -772,7 +1201,6 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
|
||||
const uint8_t *data,
|
||||
const uint8_t *data_end) {
|
||||
VP9_COMMON *const cm = &pbi->common;
|
||||
const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
|
||||
const int aligned_cols = mi_cols_aligned_to_sb(cm->mi_cols);
|
||||
const int tile_cols = 1 << cm->log2_tile_cols;
|
||||
const int tile_rows = 1 << cm->log2_tile_rows;
|
||||
@@ -785,7 +1213,7 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
|
||||
CHECK_MEM_ERROR(cm, pbi->lf_worker.data1,
|
||||
vpx_memalign(32, sizeof(LFWorkerData)));
|
||||
pbi->lf_worker.hook = (VP9WorkerHook)vp9_loop_filter_worker;
|
||||
if (pbi->max_threads > 1 && !winterface->reset(&pbi->lf_worker)) {
|
||||
if (pbi->max_threads > 1 && !vp9_worker_reset(&pbi->lf_worker)) {
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
|
||||
"Loop filter thread creation failed");
|
||||
}
|
||||
@@ -856,7 +1284,11 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
|
||||
vp9_zero(tile_data->xd.left_seg_context);
|
||||
for (mi_col = tile.mi_col_start; mi_col < tile.mi_col_end;
|
||||
mi_col += MI_BLOCK_SIZE) {
|
||||
decode_partition(tile_data->cm, &tile_data->xd, &tile, mi_row, mi_col,
|
||||
decode_partition(tile_data->cm, &tile_data->xd, &tile,
|
||||
#if CONFIG_SUPERTX
|
||||
1, 0,
|
||||
#endif
|
||||
mi_row, mi_col,
|
||||
&tile_data->bit_reader, BLOCK_64X64);
|
||||
}
|
||||
}
|
||||
@@ -871,13 +1303,13 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
|
||||
// decoding has completed: finish up the loop filter in this thread.
|
||||
if (mi_row + MI_BLOCK_SIZE >= cm->mi_rows) continue;
|
||||
|
||||
winterface->sync(&pbi->lf_worker);
|
||||
vp9_worker_sync(&pbi->lf_worker);
|
||||
lf_data->start = lf_start;
|
||||
lf_data->stop = mi_row;
|
||||
if (pbi->max_threads > 1) {
|
||||
winterface->launch(&pbi->lf_worker);
|
||||
vp9_worker_launch(&pbi->lf_worker);
|
||||
} else {
|
||||
winterface->execute(&pbi->lf_worker);
|
||||
vp9_worker_execute(&pbi->lf_worker);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -886,10 +1318,10 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
|
||||
// Loopfilter remaining rows in the frame.
|
||||
if (cm->lf.filter_level) {
|
||||
LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
|
||||
winterface->sync(&pbi->lf_worker);
|
||||
vp9_worker_sync(&pbi->lf_worker);
|
||||
lf_data->start = lf_data->stop;
|
||||
lf_data->stop = cm->mi_rows;
|
||||
winterface->execute(&pbi->lf_worker);
|
||||
vp9_worker_execute(&pbi->lf_worker);
|
||||
}
|
||||
|
||||
// Get last tile data.
|
||||
@@ -910,6 +1342,9 @@ static int tile_worker_hook(void *arg1, void *arg2) {
|
||||
for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
|
||||
mi_col += MI_BLOCK_SIZE) {
|
||||
decode_partition(tile_data->cm, &tile_data->xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
1, 0,
|
||||
#endif
|
||||
mi_row, mi_col, &tile_data->bit_reader, BLOCK_64X64);
|
||||
}
|
||||
}
|
||||
@@ -933,7 +1368,6 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi,
|
||||
const uint8_t *data,
|
||||
const uint8_t *data_end) {
|
||||
VP9_COMMON *const cm = &pbi->common;
|
||||
const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
|
||||
const uint8_t *bit_reader_end = NULL;
|
||||
const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols);
|
||||
const int tile_cols = 1 << cm->log2_tile_cols;
|
||||
@@ -960,11 +1394,11 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi,
|
||||
VP9Worker *const worker = &pbi->tile_workers[i];
|
||||
++pbi->num_tile_workers;
|
||||
|
||||
winterface->init(worker);
|
||||
vp9_worker_init(worker);
|
||||
CHECK_MEM_ERROR(cm, worker->data1,
|
||||
vpx_memalign(32, sizeof(TileWorkerData)));
|
||||
CHECK_MEM_ERROR(cm, worker->data2, vpx_malloc(sizeof(TileInfo)));
|
||||
if (i < num_threads - 1 && !winterface->reset(worker)) {
|
||||
if (i < num_threads - 1 && !vp9_worker_reset(worker)) {
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
|
||||
"Tile decoder thread creation failed");
|
||||
}
|
||||
@@ -1027,9 +1461,9 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi,
|
||||
|
||||
worker->had_error = 0;
|
||||
if (i == num_workers - 1 || n == tile_cols - 1) {
|
||||
winterface->execute(worker);
|
||||
vp9_worker_execute(worker);
|
||||
} else {
|
||||
winterface->launch(worker);
|
||||
vp9_worker_launch(worker);
|
||||
}
|
||||
|
||||
if (buf->col == tile_cols - 1) {
|
||||
@@ -1041,7 +1475,7 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi,
|
||||
|
||||
for (; i > 0; --i) {
|
||||
VP9Worker *const worker = &pbi->tile_workers[i - 1];
|
||||
pbi->mb.corrupted |= !winterface->sync(worker);
|
||||
pbi->mb.corrupted |= !vp9_worker_sync(worker);
|
||||
}
|
||||
if (final_worker > -1) {
|
||||
TileWorkerData *const tile_data =
|
||||
@@ -1077,9 +1511,8 @@ static BITSTREAM_PROFILE read_profile(struct vp9_read_bit_buffer *rb) {
|
||||
static size_t read_uncompressed_header(VP9Decoder *pbi,
|
||||
struct vp9_read_bit_buffer *rb) {
|
||||
VP9_COMMON *const cm = &pbi->common;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
int mask, i, ref_index = 0;
|
||||
size_t sz;
|
||||
int i;
|
||||
|
||||
cm->last_frame_type = cm->frame_type;
|
||||
|
||||
@@ -1097,18 +1530,12 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
|
||||
// Show an existing frame directly.
|
||||
const int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
|
||||
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_lock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
if (frame_to_show < 0 || frame_bufs[frame_to_show].ref_count < 1)
|
||||
if (frame_to_show < 0 || cm->frame_bufs[frame_to_show].ref_count < 1)
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
|
||||
"Buffer %d does not contain a decoded frame",
|
||||
frame_to_show);
|
||||
|
||||
ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show);
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_unlock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
ref_cnt_fb(cm->frame_bufs, &cm->new_fb_idx, frame_to_show);
|
||||
pbi->refresh_frame_flags = 0;
|
||||
cm->lf.filter_level = 0;
|
||||
cm->show_frame = 1;
|
||||
@@ -1164,12 +1591,12 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
|
||||
setup_frame_size(cm, rb);
|
||||
} else {
|
||||
pbi->refresh_frame_flags = vp9_rb_read_literal(rb, REF_FRAMES);
|
||||
|
||||
for (i = 0; i < REFS_PER_FRAME; ++i) {
|
||||
const int ref = vp9_rb_read_literal(rb, REF_FRAMES_LOG2);
|
||||
const int idx = cm->ref_frame_map[ref];
|
||||
RefBuffer *const ref_frame = &cm->frame_refs[i];
|
||||
ref_frame->idx = idx;
|
||||
ref_frame->buf = &frame_bufs[idx].buf;
|
||||
cm->frame_refs[i].idx = idx;
|
||||
cm->frame_refs[i].buf = &cm->frame_bufs[idx].buf;
|
||||
cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb);
|
||||
}
|
||||
|
||||
@@ -1204,28 +1631,6 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
|
||||
// below, forcing the use of context 0 for those frame types.
|
||||
cm->frame_context_idx = vp9_rb_read_literal(rb, FRAME_CONTEXTS_LOG2);
|
||||
|
||||
// Update next_ref_frame_map in frame parallel decode.
|
||||
if (pbi->frame_parallel_decode) {
|
||||
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
||||
if (mask & 1) {
|
||||
cm->next_ref_frame_map[ref_index] = cm->new_fb_idx;
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_lock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
++cm->buffer_pool->frame_bufs[cm->new_fb_idx].ref_count;
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_unlock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
} else {
|
||||
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
|
||||
}
|
||||
++ref_index;
|
||||
}
|
||||
|
||||
for (; ref_index < REF_FRAMES; ++ref_index)
|
||||
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
|
||||
}
|
||||
|
||||
if (frame_is_intra_only(cm) || cm->error_resilient_mode)
|
||||
vp9_setup_past_independence(cm);
|
||||
|
||||
@@ -1290,6 +1695,62 @@ static int read_compressed_header(VP9Decoder *pbi, const uint8_t *data,
|
||||
vp9_diff_update_prob(&r, &fc->partition_prob[j][i]);
|
||||
|
||||
read_mv_probs(nmvc, cm->allow_high_precision_mv, &r);
|
||||
|
||||
#if CONFIG_EXT_TX
|
||||
vp9_diff_update_prob(&r, &fc->ext_tx_prob);
|
||||
#endif
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
if (cm->reference_mode != SINGLE_REFERENCE) {
|
||||
cm->use_masked_interinter = vp9_read_bit(&r);
|
||||
if (cm->use_masked_interinter) {
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (get_mask_bits(i))
|
||||
vp9_diff_update_prob(&r, &fc->masked_interinter_prob[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cm->use_masked_interinter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
if (cm->reference_mode != COMPOUND_REFERENCE) {
|
||||
cm->use_interintra = vp9_read_bit(&r);
|
||||
if (cm->use_interintra) {
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (is_interintra_allowed(i)) {
|
||||
vp9_diff_update_prob(&r, &fc->interintra_prob[i]);
|
||||
}
|
||||
}
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
cm->use_masked_interintra = vp9_read_bit(&r);
|
||||
if (cm->use_masked_interintra) {
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
|
||||
vp9_diff_update_prob(&r, &fc->masked_interintra_prob[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cm->use_masked_interintra = 0;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
cm->use_interintra = 0;
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
cm->use_masked_interintra = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
for (j = 0; j < COPY_MODE_CONTEXTS; j++) {
|
||||
for (i = 0; i < 1; i++)
|
||||
vp9_diff_update_prob(&r, &fc->copy_mode_probs_l2[j][i]);
|
||||
for (i = 0; i < 2; i++)
|
||||
vp9_diff_update_prob(&r, &fc->copy_mode_probs[j][i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return vp9_reader_has_error(&r);
|
||||
@@ -1341,6 +1802,10 @@ static void debug_check_frame_counts(const VP9_COMMON *const cm) {
|
||||
assert(!memcmp(&cm->counts.tx, &zero_counts.tx, sizeof(cm->counts.tx)));
|
||||
assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
|
||||
assert(!memcmp(&cm->counts.mv, &zero_counts.mv, sizeof(cm->counts.mv)));
|
||||
#if CONFIG_EXT_TX
|
||||
assert(!memcmp(cm->counts.ext_tx, zero_counts.ext_tx,
|
||||
sizeof(cm->counts.ext_tx)));
|
||||
#endif
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
@@ -1370,8 +1835,7 @@ void vp9_decode_frame(VP9Decoder *pbi,
|
||||
const uint8_t **p_data_end) {
|
||||
VP9_COMMON *const cm = &pbi->common;
|
||||
MACROBLOCKD *const xd = &pbi->mb;
|
||||
struct vp9_read_bit_buffer rb = { NULL, NULL, 0, NULL, 0};
|
||||
|
||||
struct vp9_read_bit_buffer rb = { 0 };
|
||||
uint8_t clear_data[MAX_VP9_HEADER_SIZE];
|
||||
const size_t first_partition_size = read_uncompressed_header(pbi,
|
||||
init_read_bit_buffer(pbi, &rb, data, data_end, clear_data));
|
||||
@@ -1422,17 +1886,6 @@ void vp9_decode_frame(VP9Decoder *pbi,
|
||||
|
||||
new_fb->corrupted |= xd->corrupted;
|
||||
|
||||
// Update progress in frame parallel decode.
|
||||
if (pbi->frame_parallel_decode) {
|
||||
VP9Worker *worker = pbi->owner_frame_worker;
|
||||
FrameWorkerData *const worker_data = worker->data1;
|
||||
pthread_mutex_lock(&worker_data->stats_mutex);
|
||||
pbi->cur_buf->row = INT_MAX;
|
||||
pbi->cur_buf->col = INT_MAX;
|
||||
pthread_cond_signal(&worker_data->stats_cond);
|
||||
pthread_mutex_unlock(&worker_data->stats_mutex);
|
||||
}
|
||||
|
||||
if (!new_fb->corrupted) {
|
||||
if (!cm->error_resilient_mode && !cm->frame_parallel_decoding_mode) {
|
||||
vp9_adapt_coef_probs(cm);
|
||||
|
@@ -54,6 +54,36 @@ static PREDICTION_MODE read_inter_mode(VP9_COMMON *cm, vp9_reader *r, int ctx) {
|
||||
return NEARESTMV + mode;
|
||||
}
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
static COPY_MODE read_copy_mode(VP9_COMMON *cm, vp9_reader *r,
|
||||
int num_candidate, int ctx) {
|
||||
COPY_MODE mode;
|
||||
|
||||
switch (num_candidate) {
|
||||
case 0:
|
||||
assert(0);
|
||||
break;
|
||||
case 1:
|
||||
mode = REF0;
|
||||
break;
|
||||
case 2:
|
||||
mode = REF0 + vp9_read_tree(r, vp9_copy_mode_tree_l2,
|
||||
cm->fc.copy_mode_probs_l2[ctx]);
|
||||
if (!cm->frame_parallel_decoding_mode)
|
||||
++cm->counts.copy_mode_l2[ctx][mode - REF0];
|
||||
break;
|
||||
default:
|
||||
mode = REF0 + vp9_read_tree(r, vp9_copy_mode_tree,
|
||||
cm->fc.copy_mode_probs[ctx]);
|
||||
if (!cm->frame_parallel_decoding_mode)
|
||||
++cm->counts.copy_mode[ctx][mode - REF0];
|
||||
break;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int read_segment_id(vp9_reader *r, const struct segmentation *seg) {
|
||||
return vp9_read_tree(r, vp9_segment_tree, seg->tree_probs);
|
||||
}
|
||||
@@ -144,7 +174,11 @@ static int read_inter_segment_id(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
||||
return segment_id;
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
|
||||
#else
|
||||
static int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
|
||||
#endif
|
||||
int segment_id, vp9_reader *r) {
|
||||
if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
|
||||
return 1;
|
||||
@@ -175,29 +209,85 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm,
|
||||
|
||||
switch (bsize) {
|
||||
case BLOCK_4X4:
|
||||
#if !CONFIG_FILTERINTRA
|
||||
for (i = 0; i < 4; ++i)
|
||||
#else
|
||||
for (i = 0; i < 4; ++i) {
|
||||
#endif
|
||||
mi->bmi[i].as_mode =
|
||||
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, i));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[i].as_mode))
|
||||
mi->b_filter_info[i] =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
|
||||
else
|
||||
mi->b_filter_info[i] = 0;
|
||||
}
|
||||
mbmi->filterbit = mi->b_filter_info[3];
|
||||
#endif
|
||||
mbmi->mode = mi->bmi[3].as_mode;
|
||||
break;
|
||||
case BLOCK_4X8:
|
||||
mi->bmi[0].as_mode = mi->bmi[2].as_mode =
|
||||
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[0].as_mode))
|
||||
mi->b_filter_info[0] = mi->b_filter_info[2] =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
|
||||
else
|
||||
mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
|
||||
#endif
|
||||
mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
|
||||
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 1));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[1].as_mode))
|
||||
mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
|
||||
else
|
||||
mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
|
||||
#endif
|
||||
break;
|
||||
case BLOCK_8X4:
|
||||
mi->bmi[0].as_mode = mi->bmi[1].as_mode =
|
||||
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[0].as_mode))
|
||||
mi->b_filter_info[0] = mi->b_filter_info[1] =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
|
||||
else
|
||||
mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
|
||||
#endif
|
||||
mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
|
||||
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 2));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[2].as_mode))
|
||||
mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
|
||||
else
|
||||
mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
mbmi->mode = read_intra_mode(r,
|
||||
get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_enabled(mbmi->tx_size) && is_filter_allowed(mbmi->mode))
|
||||
mbmi->filterbit = vp9_read(r,
|
||||
cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
|
||||
else
|
||||
mbmi->filterbit = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_enabled(get_uv_tx_size(mbmi)) &&
|
||||
is_filter_allowed(mbmi->uv_mode))
|
||||
mbmi->uv_filterbit = vp9_read(r,
|
||||
cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
|
||||
else
|
||||
mbmi->uv_filterbit = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int read_mv_component(vp9_reader *r,
|
||||
@@ -335,25 +425,97 @@ static void read_intra_block_mode_info(VP9_COMMON *const cm, MODE_INFO *mi,
|
||||
|
||||
switch (bsize) {
|
||||
case BLOCK_4X4:
|
||||
#if !CONFIG_FILTERINTRA
|
||||
for (i = 0; i < 4; ++i)
|
||||
#else
|
||||
for (i = 0; i < 4; ++i) {
|
||||
#endif
|
||||
mi->bmi[i].as_mode = read_intra_mode_y(cm, r, 0);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[i].as_mode)) {
|
||||
mi->b_filter_info[i] =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
|
||||
cm->counts.filterintra[0][mi->bmi[i].as_mode]
|
||||
[mi->b_filter_info[i]]++;
|
||||
} else {
|
||||
mi->b_filter_info[i] = 0;
|
||||
}
|
||||
}
|
||||
mbmi->filterbit = mi->b_filter_info[3];
|
||||
#endif
|
||||
mbmi->mode = mi->bmi[3].as_mode;
|
||||
break;
|
||||
case BLOCK_4X8:
|
||||
mi->bmi[0].as_mode = mi->bmi[2].as_mode = read_intra_mode_y(cm, r, 0);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[0].as_mode)) {
|
||||
mi->b_filter_info[0] = mi->b_filter_info[2] =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
|
||||
cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
|
||||
} else {
|
||||
mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
|
||||
}
|
||||
#endif
|
||||
mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
|
||||
read_intra_mode_y(cm, r, 0);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[1].as_mode)) {
|
||||
mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
|
||||
cm->counts.filterintra[0][mi->bmi[1].as_mode][mi->b_filter_info[1]]++;
|
||||
} else {
|
||||
mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case BLOCK_8X4:
|
||||
mi->bmi[0].as_mode = mi->bmi[1].as_mode = read_intra_mode_y(cm, r, 0);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[0].as_mode)) {
|
||||
mi->b_filter_info[0] = mi->b_filter_info[1] =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
|
||||
cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
|
||||
} else {
|
||||
mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
|
||||
}
|
||||
#endif
|
||||
mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
|
||||
read_intra_mode_y(cm, r, 0);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[2].as_mode)) {
|
||||
mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
|
||||
vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
|
||||
cm->counts.filterintra[0][mi->bmi[2].as_mode][mi->b_filter_info[2]]++;
|
||||
} else {
|
||||
mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
mbmi->mode = read_intra_mode_y(cm, r, size_group_lookup[bsize]);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size)) {
|
||||
mbmi->filterbit = vp9_read(r,
|
||||
cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
|
||||
cm->counts.filterintra[mbmi->tx_size][mbmi->mode][mbmi->filterbit]++;
|
||||
} else {
|
||||
mbmi->filterbit = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
mbmi->uv_mode = read_intra_mode_uv(cm, r, mbmi->mode);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mbmi->uv_mode) &&
|
||||
is_filter_enabled(get_uv_tx_size(mbmi))) {
|
||||
mbmi->uv_filterbit = vp9_read(r,
|
||||
cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
|
||||
cm->counts.filterintra[get_uv_tx_size(mbmi)]
|
||||
[mbmi->uv_mode][mbmi->uv_filterbit]++;
|
||||
} else {
|
||||
mbmi->uv_filterbit = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE int is_mv_valid(const MV *mv) {
|
||||
@@ -422,6 +584,9 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
|
||||
MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
MODE_INFO *const mi,
|
||||
#if CONFIG_SUPERTX && CONFIG_EXT_TX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col, vp9_reader *r) {
|
||||
MB_MODE_INFO *const mbmi = &mi->mbmi;
|
||||
const BLOCK_SIZE bsize = mbmi->sb_type;
|
||||
@@ -464,6 +629,37 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
|
||||
? read_switchable_interp_filter(cm, xd, r)
|
||||
: cm->interp_filter;
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
if ((cm->use_interintra) &&
|
||||
is_interintra_allowed(bsize) &&
|
||||
is_inter_mode(mbmi->mode) &&
|
||||
(mbmi->ref_frame[1] <= INTRA_FRAME)) {
|
||||
mbmi->ref_frame[1] = vp9_read(r, cm->fc.interintra_prob[bsize]) ?
|
||||
INTRA_FRAME : NONE;
|
||||
cm->counts.interintra[bsize][mbmi->ref_frame[1] == INTRA_FRAME]++;
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
mbmi->use_masked_interintra = 0;
|
||||
#endif
|
||||
if (mbmi->ref_frame[1] == INTRA_FRAME) {
|
||||
mbmi->interintra_mode =
|
||||
read_intra_mode_y(cm, r, size_group_lookup[bsize]);
|
||||
mbmi->interintra_uv_mode = mbmi->interintra_mode;
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (cm->use_masked_interintra && get_mask_bits_interintra(bsize)) {
|
||||
mbmi->use_masked_interintra = vp9_read(r,
|
||||
cm->fc.masked_interintra_prob[bsize]);
|
||||
cm->counts.masked_interintra[bsize][mbmi->use_masked_interintra]++;
|
||||
if (mbmi->use_masked_interintra) {
|
||||
mbmi->interintra_mask_index = vp9_read_literal(r,
|
||||
get_mask_bits_interintra(bsize));
|
||||
mbmi->interintra_uv_mask_index = mbmi->interintra_mask_index;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bsize < BLOCK_8X8) {
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; // 1 or 2
|
||||
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; // 1 or 2
|
||||
@@ -508,35 +704,160 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
|
||||
xd->corrupted |= !assign_mv(cm, mbmi->mode, mbmi->mv, nearestmv,
|
||||
nearestmv, nearmv, is_compound, allow_hp, r);
|
||||
}
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
mbmi->use_masked_interinter = 0;
|
||||
if (cm->use_masked_interinter &&
|
||||
cm->reference_mode != SINGLE_REFERENCE &&
|
||||
is_inter_mode(mbmi->mode) &&
|
||||
get_mask_bits(bsize) &&
|
||||
mbmi->ref_frame[1] > INTRA_FRAME) {
|
||||
mbmi->use_masked_interinter =
|
||||
vp9_read(r, cm->fc.masked_interinter_prob[bsize]);
|
||||
cm->counts.masked_interinter[bsize][mbmi->use_masked_interinter]++;
|
||||
if (mbmi->use_masked_interinter) {
|
||||
mbmi->mask_index = vp9_read_literal(r, get_mask_bits(bsize));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void read_inter_frame_mode_info(VP9_COMMON *const cm,
|
||||
MACROBLOCKD *const xd,
|
||||
const TileInfo *const tile,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col, vp9_reader *r) {
|
||||
MODE_INFO *const mi = xd->mi[0];
|
||||
MB_MODE_INFO *const mbmi = &mi->mbmi;
|
||||
int inter_block;
|
||||
#if CONFIG_COPY_CODING
|
||||
int num_candidate = 0;
|
||||
MB_MODE_INFO *inter_ref_list[18] = {NULL};
|
||||
#endif
|
||||
|
||||
mbmi->mv[0].as_int = 0;
|
||||
mbmi->mv[1].as_int = 0;
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
if (mbmi->sb_type >= BLOCK_8X8)
|
||||
num_candidate = vp9_construct_ref_inter_list(cm, xd, mbmi->sb_type,
|
||||
mi_row, mi_col, inter_ref_list);
|
||||
if (mbmi->sb_type >= BLOCK_8X8 && num_candidate > 0) {
|
||||
int ctx = vp9_get_copy_mode_context(xd);
|
||||
int is_copy = vp9_read(r, cm->fc.copy_noref_prob[ctx][mbmi->sb_type]);
|
||||
|
||||
++cm->counts.copy_noref[ctx][mbmi->sb_type][is_copy];
|
||||
if (!is_copy) {
|
||||
mbmi->copy_mode = NOREF;
|
||||
} else {
|
||||
mbmi->copy_mode = read_copy_mode(cm, r, num_candidate, ctx);
|
||||
}
|
||||
} else {
|
||||
mbmi->copy_mode = NOREF;
|
||||
}
|
||||
if (mbmi->copy_mode != NOREF) {
|
||||
BLOCK_SIZE bsize_backup = mbmi->sb_type;
|
||||
int skip_backup = mbmi->skip;
|
||||
COPY_MODE copy_mode_backup = mbmi->copy_mode;
|
||||
#if CONFIG_SUPERTX
|
||||
TX_SIZE tx_size_backup = mbmi->tx_size;
|
||||
#endif
|
||||
#if CONFIG_EXT_TX
|
||||
EXT_TX_TYPE ext_txfrm_backup = mbmi->ext_txfrm;
|
||||
#endif
|
||||
|
||||
inter_block = 1;
|
||||
*mbmi = *inter_ref_list[mbmi->copy_mode - REF0];
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
mbmi->use_masked_interinter = 0;
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
if (mbmi->ref_frame[1] == INTRA_FRAME)
|
||||
mbmi->ref_frame[1] = NONE;
|
||||
#endif
|
||||
#if CONFIG_SUPERTX
|
||||
mbmi->tx_size = tx_size_backup;
|
||||
#endif
|
||||
#if CONFIG_EXT_TX
|
||||
mbmi->ext_txfrm = ext_txfrm_backup;
|
||||
#endif
|
||||
mbmi->sb_type = bsize_backup;
|
||||
mbmi->mode = NEARESTMV;
|
||||
mbmi->skip = skip_backup;
|
||||
mbmi->copy_mode = copy_mode_backup;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
if (!supertx_enabled) {
|
||||
#endif
|
||||
mbmi->segment_id = read_inter_segment_id(cm, xd, mi_row, mi_col, r);
|
||||
mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
if (mbmi->copy_mode == NOREF)
|
||||
#endif
|
||||
inter_block = read_is_inter_block(cm, xd, mbmi->segment_id, r);
|
||||
mbmi->tx_size = read_tx_size(cm, xd, cm->tx_mode, mbmi->sb_type,
|
||||
!mbmi->skip || !inter_block, r);
|
||||
#if CONFIG_EXT_TX
|
||||
if (inter_block &&
|
||||
mbmi->tx_size <= TX_16X16 &&
|
||||
mbmi->sb_type >= BLOCK_8X8 &&
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled &&
|
||||
#endif
|
||||
!vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) &&
|
||||
!mbmi->skip) {
|
||||
mbmi->ext_txfrm = vp9_read(r, cm->fc.ext_tx_prob);
|
||||
if (!cm->frame_parallel_decoding_mode)
|
||||
++cm->counts.ext_tx[mbmi->ext_txfrm];
|
||||
} else {
|
||||
mbmi->ext_txfrm = NORM;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_SUPERTX
|
||||
} else {
|
||||
const int ctx = vp9_get_intra_inter_context(xd);
|
||||
mbmi->segment_id = 0;
|
||||
inter_block = 1;
|
||||
if (!cm->frame_parallel_decoding_mode)
|
||||
#if CONFIG_COPY_CODING
|
||||
if (mbmi->copy_mode == NOREF)
|
||||
#endif
|
||||
++cm->counts.intra_inter[ctx][1];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
if (mbmi->copy_mode == NOREF) {
|
||||
#endif
|
||||
if (inter_block)
|
||||
read_inter_block_mode_info(cm, xd, tile, mi, mi_row, mi_col, r);
|
||||
read_inter_block_mode_info(cm, xd, tile, mi,
|
||||
#if CONFIG_SUPERTX && CONFIG_EXT_TX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r);
|
||||
else
|
||||
read_intra_block_mode_info(cm, mi, r);
|
||||
#if CONFIG_COPY_CODING
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
const TileInfo *const tile,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col, vp9_reader *r) {
|
||||
if (frame_is_intra_only(cm))
|
||||
read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
|
||||
else
|
||||
read_inter_frame_mode_info(cm, xd, tile, mi_row, mi_col, r);
|
||||
read_inter_frame_mode_info(cm, xd, tile,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, r);
|
||||
}
|
||||
|
@@ -21,8 +21,16 @@ struct TileInfo;
|
||||
|
||||
void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
const struct TileInfo *const tile,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col, vp9_reader *r);
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
|
||||
int segment_id, vp9_reader *r);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -41,7 +41,7 @@ static void initialize_dec() {
|
||||
}
|
||||
}
|
||||
|
||||
VP9Decoder *vp9_decoder_create(BufferPool *const pool) {
|
||||
VP9Decoder *vp9_decoder_create() {
|
||||
VP9Decoder *const pbi = vpx_memalign(32, sizeof(*pbi));
|
||||
VP9_COMMON *const cm = pbi ? &pbi->common : NULL;
|
||||
|
||||
@@ -63,11 +63,9 @@ VP9Decoder *vp9_decoder_create(BufferPool *const pool) {
|
||||
|
||||
// Initialize the references to not point to any frame buffers.
|
||||
vpx_memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
|
||||
vpx_memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map));
|
||||
|
||||
cm->current_video_frame = 0;
|
||||
pbi->ready_for_new_data = 1;
|
||||
pbi->common.buffer_pool = pool;
|
||||
|
||||
// vp9_init_dequantizer() is first called here. Add check in
|
||||
// frame_init_dequantizer() to avoid unnecessary calling of
|
||||
@@ -78,7 +76,7 @@ VP9Decoder *vp9_decoder_create(BufferPool *const pool) {
|
||||
|
||||
cm->error.setjmp = 0;
|
||||
|
||||
vp9_get_worker_interface()->init(&pbi->lf_worker);
|
||||
vp9_worker_init(&pbi->lf_worker);
|
||||
|
||||
return pbi;
|
||||
}
|
||||
@@ -88,12 +86,12 @@ void vp9_decoder_remove(VP9Decoder *pbi) {
|
||||
int i;
|
||||
|
||||
vp9_remove_common(cm);
|
||||
vp9_get_worker_interface()->end(&pbi->lf_worker);
|
||||
vp9_worker_end(&pbi->lf_worker);
|
||||
vpx_free(pbi->lf_worker.data1);
|
||||
vpx_free(pbi->tile_data);
|
||||
for (i = 0; i < pbi->num_tile_workers; ++i) {
|
||||
VP9Worker *const worker = &pbi->tile_workers[i];
|
||||
vp9_get_worker_interface()->end(worker);
|
||||
vp9_worker_end(worker);
|
||||
vpx_free(worker->data1);
|
||||
vpx_free(worker->data2);
|
||||
}
|
||||
@@ -126,7 +124,7 @@ vpx_codec_err_t vp9_copy_reference_dec(VP9Decoder *pbi,
|
||||
*/
|
||||
if (ref_frame_flag == VP9_LAST_FLAG) {
|
||||
const YV12_BUFFER_CONFIG *const cfg =
|
||||
&cm->buffer_pool->frame_bufs[cm->ref_frame_map[0]].buf;
|
||||
&cm->frame_bufs[cm->ref_frame_map[0]].buf;
|
||||
if (!equal_dimensions(cfg, sd))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
|
||||
"Incorrect buffer dimensions");
|
||||
@@ -145,7 +143,6 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
||||
VP9_REFFRAME ref_frame_flag,
|
||||
YV12_BUFFER_CONFIG *sd) {
|
||||
RefBuffer *ref_buf = NULL;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
// TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
|
||||
// encoder is using the frame buffers for. This is just a stub to keep the
|
||||
@@ -173,11 +170,11 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
||||
const int free_fb = get_free_fb(cm);
|
||||
// Decrease ref_count since it will be increased again in
|
||||
// ref_cnt_fb() below.
|
||||
--frame_bufs[free_fb].ref_count;
|
||||
cm->frame_bufs[free_fb].ref_count--;
|
||||
|
||||
// Manage the reference counters and copy image.
|
||||
ref_cnt_fb(frame_bufs, ref_fb_ptr, free_fb);
|
||||
ref_buf->buf = &frame_bufs[*ref_fb_ptr].buf;
|
||||
ref_cnt_fb(cm->frame_bufs, ref_fb_ptr, free_fb);
|
||||
ref_buf->buf = &cm->frame_bufs[*ref_fb_ptr].buf;
|
||||
vp8_yv12_copy_frame(sd, ref_buf->buf);
|
||||
}
|
||||
|
||||
@@ -187,44 +184,35 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
||||
|
||||
int vp9_get_reference_dec(VP9Decoder *pbi, int index, YV12_BUFFER_CONFIG **fb) {
|
||||
VP9_COMMON *cm = &pbi->common;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
if (index < 0 || index >= REF_FRAMES)
|
||||
return -1;
|
||||
|
||||
*fb = &frame_bufs[cm->ref_frame_map[index]].buf;
|
||||
*fb = &cm->frame_bufs[cm->ref_frame_map[index]].buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If any buffer updating is signaled it should be done here. */
|
||||
static void swap_frame_buffers(VP9Decoder *pbi) {
|
||||
int ref_index = 0, mask;
|
||||
VP9_COMMON * const cm = &pbi->common;
|
||||
BufferPool * const pool = cm->buffer_pool;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
VP9_COMMON *const cm = &pbi->common;
|
||||
|
||||
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
||||
if (mask & 1) {
|
||||
const int old_idx = cm->ref_frame_map[ref_index];
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_lock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
ref_cnt_fb(frame_bufs, &cm->ref_frame_map[ref_index],
|
||||
ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index],
|
||||
cm->new_fb_idx);
|
||||
if (old_idx >= 0 && frame_bufs[old_idx].ref_count == 0)
|
||||
pool->release_fb_cb(pool->cb_priv,
|
||||
&frame_bufs[old_idx].raw_frame_buffer);
|
||||
if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0)
|
||||
cm->release_fb_cb(cm->cb_priv,
|
||||
&cm->frame_bufs[old_idx].raw_frame_buffer);
|
||||
}
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_unlock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
++ref_index;
|
||||
}
|
||||
|
||||
cm->frame_to_show = get_frame_new_buffer(cm);
|
||||
|
||||
if (!pbi->frame_parallel_decode || !cm->show_frame) {
|
||||
--frame_bufs[cm->new_fb_idx].ref_count;
|
||||
--cm->frame_bufs[cm->new_fb_idx].ref_count;
|
||||
}
|
||||
|
||||
// Invalidate these references until the next frame starts.
|
||||
@@ -235,8 +223,6 @@ static void swap_frame_buffers(VP9Decoder *pbi) {
|
||||
int vp9_receive_compressed_data(VP9Decoder *pbi,
|
||||
size_t size, const uint8_t **psource) {
|
||||
VP9_COMMON *const cm = &pbi->common;
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
const uint8_t *source = *psource;
|
||||
int retcode = 0;
|
||||
|
||||
@@ -258,22 +244,11 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
|
||||
// Check if the previous frame was a frame without any references to it.
|
||||
// Release frame buffer if not decoding in frame parallel mode.
|
||||
if (!pbi->frame_parallel_decode && cm->new_fb_idx >= 0
|
||||
&& frame_bufs[cm->new_fb_idx].ref_count == 0)
|
||||
pool->release_fb_cb(pool->cb_priv,
|
||||
&frame_bufs[cm->new_fb_idx].raw_frame_buffer);
|
||||
&& cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
|
||||
cm->release_fb_cb(cm->cb_priv,
|
||||
&cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
|
||||
cm->new_fb_idx = get_free_fb(cm);
|
||||
|
||||
if (pbi->frame_parallel_decode) {
|
||||
VP9Worker *worker = pbi->owner_frame_worker;
|
||||
FrameWorkerData *const worker_data = worker->data1;
|
||||
pbi->cur_buf = &pool->frame_bufs[cm->new_fb_idx];
|
||||
pool->frame_bufs[cm->new_fb_idx].owner_worker_id = worker_data->worker_id;
|
||||
|
||||
// Reset the decoding progress.
|
||||
pbi->cur_buf->row = -1;
|
||||
pbi->cur_buf->col = -1;
|
||||
}
|
||||
|
||||
if (setjmp(cm->error.jmp)) {
|
||||
cm->error.setjmp = 0;
|
||||
|
||||
@@ -287,8 +262,8 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
|
||||
if (cm->frame_refs[0].idx != INT_MAX && cm->frame_refs[0].buf != NULL)
|
||||
cm->frame_refs[0].buf->corrupted = 1;
|
||||
|
||||
if (frame_bufs[cm->new_fb_idx].ref_count > 0)
|
||||
--frame_bufs[cm->new_fb_idx].ref_count;
|
||||
if (cm->new_fb_idx > 0 && cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
|
||||
cm->frame_bufs[cm->new_fb_idx].ref_count--;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@@ -45,14 +45,8 @@ typedef struct VP9Decoder {
|
||||
|
||||
int frame_parallel_decode; // frame-based threading.
|
||||
|
||||
// TODO(hkuang): Combine this with cur_buf in macroblockd as they are
|
||||
// the same.
|
||||
RefCntBuffer *cur_buf; // current decoding reference buffer.
|
||||
|
||||
VP9Worker lf_worker;
|
||||
VP9Worker *tile_workers;
|
||||
VP9Worker *owner_frame_worker; // frame_worker that owns this pbi;
|
||||
|
||||
int num_tile_workers;
|
||||
|
||||
TileData *tile_data;
|
||||
@@ -84,7 +78,7 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
||||
int vp9_get_reference_dec(struct VP9Decoder *pbi,
|
||||
int index, YV12_BUFFER_CONFIG **fb);
|
||||
|
||||
struct VP9Decoder *vp9_decoder_create(BufferPool *const pool);
|
||||
struct VP9Decoder *vp9_decoder_create();
|
||||
|
||||
void vp9_decoder_remove(struct VP9Decoder *pbi);
|
||||
|
||||
|
@@ -124,7 +124,7 @@ static void loop_filter_rows_mt(const YV12_BUFFER_CONFIG *const frame_buffer,
|
||||
static int loop_filter_row_worker(void *arg1, void *arg2) {
|
||||
TileWorkerData *const tile_data = (TileWorkerData*)arg1;
|
||||
LFWorkerData *const lf_data = &tile_data->lfdata;
|
||||
(void) arg2;
|
||||
|
||||
loop_filter_rows_mt(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
|
||||
lf_data->start, lf_data->stop, lf_data->y_only,
|
||||
lf_data->lf_sync, lf_data->num_lf_workers);
|
||||
@@ -138,7 +138,6 @@ void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame,
|
||||
int frame_filter_level,
|
||||
int y_only) {
|
||||
VP9LfSync *const lf_sync = &pbi->lf_row_sync;
|
||||
const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
|
||||
// Number of superblock rows and cols
|
||||
const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
|
||||
const int tile_cols = 1 << cm->log2_tile_cols;
|
||||
@@ -198,15 +197,15 @@ void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame,
|
||||
|
||||
// Start loopfiltering
|
||||
if (i == num_workers - 1) {
|
||||
winterface->execute(worker);
|
||||
vp9_worker_execute(worker);
|
||||
} else {
|
||||
winterface->launch(worker);
|
||||
vp9_worker_launch(worker);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait till all rows are finished
|
||||
for (i = 0; i < num_workers; ++i) {
|
||||
winterface->sync(&pbi->tile_workers[i]);
|
||||
vp9_worker_sync(&pbi->tile_workers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,78 +278,3 @@ void vp9_loop_filter_dealloc(VP9LfSync *lf_sync, int rows) {
|
||||
vp9_zero(*lf_sync);
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_frameworker_wait(VP9Worker* const worker, int row, int col,
|
||||
RefCntBuffer *ref_buf) {
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
const VP9Decoder *const pbi = worker_data->pbi;
|
||||
const RefCntBuffer *const cur_buf = pbi->cur_buf;
|
||||
|
||||
// Check if worker already release the ref_buf.
|
||||
if (!worker || ref_buf->owner_worker_id == -1) return;
|
||||
|
||||
pthread_mutex_lock(&worker_data->stats_mutex);
|
||||
while (!(cur_buf->row >= row && cur_buf->col >= col)
|
||||
&& pbi->cur_buf == ref_buf && ref_buf->owner_worker_id != -1) {
|
||||
pthread_cond_wait(&worker_data->stats_cond, &worker_data->stats_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&worker_data->stats_mutex);
|
||||
}
|
||||
|
||||
void vp9_frameworker_broadcast(VP9Worker* const worker, int row, int col) {
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
const VP9Decoder *const pbi = worker_data->pbi;
|
||||
RefCntBuffer *const cur_buf = pbi->cur_buf;
|
||||
|
||||
pthread_mutex_lock(&worker_data->stats_mutex);
|
||||
cur_buf->row = row;
|
||||
cur_buf->col = col;
|
||||
pthread_cond_signal(&worker_data->stats_cond);
|
||||
pthread_mutex_unlock(&worker_data->stats_mutex);
|
||||
}
|
||||
|
||||
void vp9_frameworker_copy_context(VP9Worker *const dst_worker,
|
||||
const VP9Worker *const src_worker) {
|
||||
FrameWorkerData *const src_worker_data =
|
||||
(FrameWorkerData *)dst_worker->data1;
|
||||
FrameWorkerData *const dst_worker_data =
|
||||
(FrameWorkerData *)src_worker->data1;
|
||||
const VP9_COMMON *const src_cm = &src_worker_data->pbi->common;
|
||||
VP9_COMMON *const dst_cm = &dst_worker_data->pbi->common;
|
||||
int i;
|
||||
|
||||
// Wait until source frame's context is ready.
|
||||
pthread_mutex_lock(&src_worker_data->stats_mutex);
|
||||
while (!src_worker_data->frame_context_ready) {
|
||||
pthread_cond_wait(&src_worker_data->stats_cond,
|
||||
&src_worker_data->stats_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&src_worker_data->stats_mutex);
|
||||
|
||||
dst_cm->last_width = src_cm->width;
|
||||
dst_cm->last_height = src_cm->height;
|
||||
dst_cm->subsampling_x = src_cm->subsampling_x;
|
||||
dst_cm->subsampling_y = src_cm->subsampling_y;
|
||||
|
||||
for (i = 0; i < REF_FRAMES; ++i)
|
||||
dst_cm->ref_frame_map[i] = src_cm->next_ref_frame_map[i];
|
||||
|
||||
dst_cm->last_show_frame = src_cm->show_frame;
|
||||
|
||||
dst_cm->prev_mip = src_cm->mip;
|
||||
dst_cm->prev_mi = src_cm->mi;
|
||||
dst_cm->prev_mi_grid_base = src_cm->mi_grid_base;
|
||||
dst_cm->prev_mi_grid_visible = src_cm->mi_grid_visible;
|
||||
dst_cm->lf.last_sharpness_level = src_cm->lf.sharpness_level;
|
||||
|
||||
for (i = 0; i < MAX_REF_LF_DELTAS; ++i) {
|
||||
dst_cm->lf.last_ref_deltas[i] = src_cm->lf.ref_deltas[i];
|
||||
dst_cm->lf.ref_deltas[i] = src_cm->lf.ref_deltas[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MODE_LF_DELTAS; ++i)
|
||||
dst_cm-> lf.last_mode_deltas[i] = src_cm->lf.mode_deltas[i];
|
||||
|
||||
for (i = 0; i < FRAME_CONTEXTS; ++i)
|
||||
dst_cm-> frame_contexts[i] = src_cm->frame_contexts[i];
|
||||
}
|
||||
|
@@ -55,11 +55,6 @@ typedef struct FrameWorkerData {
|
||||
// It is used to make a copy of the compressed data.
|
||||
uint8_t *scratch_buffer;
|
||||
size_t scratch_buffer_size;
|
||||
|
||||
pthread_mutex_t stats_mutex;
|
||||
pthread_cond_t stats_cond;
|
||||
|
||||
int frame_context_ready; // Current frame's context is ready to read.
|
||||
} FrameWorkerData;
|
||||
|
||||
// Allocate memory for loopfilter row synchronization.
|
||||
@@ -76,19 +71,4 @@ void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame,
|
||||
int frame_filter_level,
|
||||
int y_only);
|
||||
|
||||
// Wait for FrameWorker to finish decoding ref_buf to (r,c) position.
|
||||
// Note: worker may already finish decoding ref_buf and release it in order to
|
||||
// start decoding next frame. So need to check whether worker is still decoding
|
||||
// ref_buf.
|
||||
void vp9_frameworker_wait(VP9Worker* const worker, int row, int col,
|
||||
RefCntBuffer *ref_buf);
|
||||
|
||||
// FrameWorker broadcasts its decoding progress so other workers that are
|
||||
// waiting it could resume decoding.
|
||||
void vp9_frameworker_broadcast(VP9Worker* const worker, int row, int col);
|
||||
|
||||
// Copy necessary decoding context from src worker to dst worker.
|
||||
void vp9_frameworker_copy_context(VP9Worker *const dst_worker,
|
||||
const VP9Worker *const src_worker);
|
||||
|
||||
#endif // VP9_DECODER_VP9_DTHREAD_H_
|
||||
|
@@ -11,79 +11,71 @@
|
||||
//
|
||||
// Original source:
|
||||
// http://git.chromium.org/webm/libwebp.git
|
||||
// 100644 blob 08ad4e1fecba302bf1247645e84a7d2779956bc3 src/utils/thread.c
|
||||
// 100644 blob eff8f2a8c20095aade3c292b0e9292dac6cb3587 src/utils/thread.c
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h> // for memset()
|
||||
#include "./vp9_thread.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_MULTITHREAD
|
||||
|
||||
struct VP9WorkerImpl {
|
||||
pthread_mutex_t mutex_;
|
||||
pthread_cond_t condition_;
|
||||
pthread_t thread_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static void execute(VP9Worker *const worker); // Forward declaration.
|
||||
|
||||
static THREADFN thread_loop(void *ptr) {
|
||||
VP9Worker *const worker = (VP9Worker*)ptr;
|
||||
static THREADFN thread_loop(void *ptr) { // thread loop
|
||||
VP9Worker* const worker = (VP9Worker*)ptr;
|
||||
int done = 0;
|
||||
while (!done) {
|
||||
pthread_mutex_lock(&worker->impl_->mutex_);
|
||||
pthread_mutex_lock(&worker->mutex_);
|
||||
while (worker->status_ == OK) { // wait in idling mode
|
||||
pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
|
||||
pthread_cond_wait(&worker->condition_, &worker->mutex_);
|
||||
}
|
||||
if (worker->status_ == WORK) {
|
||||
execute(worker);
|
||||
vp9_worker_execute(worker);
|
||||
worker->status_ = OK;
|
||||
} else if (worker->status_ == NOT_OK) { // finish the worker
|
||||
done = 1;
|
||||
}
|
||||
// signal to the main thread that we're done (for sync())
|
||||
pthread_cond_signal(&worker->impl_->condition_);
|
||||
pthread_mutex_unlock(&worker->impl_->mutex_);
|
||||
// signal to the main thread that we're done (for Sync())
|
||||
pthread_cond_signal(&worker->condition_);
|
||||
pthread_mutex_unlock(&worker->mutex_);
|
||||
}
|
||||
return THREAD_RETURN(NULL); // Thread is finished
|
||||
}
|
||||
|
||||
// main thread state control
|
||||
static void change_state(VP9Worker *const worker,
|
||||
static void change_state(VP9Worker* const worker,
|
||||
VP9WorkerStatus new_status) {
|
||||
// No-op when attempting to change state on a thread that didn't come up.
|
||||
// Checking status_ without acquiring the lock first would result in a data
|
||||
// race.
|
||||
if (worker->impl_ == NULL) return;
|
||||
// no-op when attempting to change state on a thread that didn't come up
|
||||
if (worker->status_ < OK) return;
|
||||
|
||||
pthread_mutex_lock(&worker->impl_->mutex_);
|
||||
if (worker->status_ >= OK) {
|
||||
// wait for the worker to finish
|
||||
while (worker->status_ != OK) {
|
||||
pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
|
||||
}
|
||||
// assign new status and release the working thread if needed
|
||||
if (new_status != OK) {
|
||||
worker->status_ = new_status;
|
||||
pthread_cond_signal(&worker->impl_->condition_);
|
||||
}
|
||||
pthread_mutex_lock(&worker->mutex_);
|
||||
// wait for the worker to finish
|
||||
while (worker->status_ != OK) {
|
||||
pthread_cond_wait(&worker->condition_, &worker->mutex_);
|
||||
}
|
||||
pthread_mutex_unlock(&worker->impl_->mutex_);
|
||||
// assign new status and release the working thread if needed
|
||||
if (new_status != OK) {
|
||||
worker->status_ = new_status;
|
||||
pthread_cond_signal(&worker->condition_);
|
||||
}
|
||||
pthread_mutex_unlock(&worker->mutex_);
|
||||
}
|
||||
|
||||
#endif // CONFIG_MULTITHREAD
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static void init(VP9Worker *const worker) {
|
||||
void vp9_worker_init(VP9Worker* const worker) {
|
||||
memset(worker, 0, sizeof(*worker));
|
||||
worker->status_ = NOT_OK;
|
||||
}
|
||||
|
||||
static int sync(VP9Worker *const worker) {
|
||||
int vp9_worker_sync(VP9Worker* const worker) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
change_state(worker, OK);
|
||||
#endif
|
||||
@@ -91,93 +83,59 @@ static int sync(VP9Worker *const worker) {
|
||||
return !worker->had_error;
|
||||
}
|
||||
|
||||
static int reset(VP9Worker *const worker) {
|
||||
int vp9_worker_reset(VP9Worker* const worker) {
|
||||
int ok = 1;
|
||||
worker->had_error = 0;
|
||||
if (worker->status_ < OK) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
worker->impl_ = (VP9WorkerImpl*)vpx_calloc(1, sizeof(*worker->impl_));
|
||||
if (worker->impl_ == NULL) {
|
||||
if (pthread_mutex_init(&worker->mutex_, NULL) ||
|
||||
pthread_cond_init(&worker->condition_, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) {
|
||||
goto Error;
|
||||
}
|
||||
if (pthread_cond_init(&worker->impl_->condition_, NULL)) {
|
||||
pthread_mutex_destroy(&worker->impl_->mutex_);
|
||||
goto Error;
|
||||
}
|
||||
pthread_mutex_lock(&worker->impl_->mutex_);
|
||||
ok = !pthread_create(&worker->impl_->thread_, NULL, thread_loop, worker);
|
||||
pthread_mutex_lock(&worker->mutex_);
|
||||
ok = !pthread_create(&worker->thread_, NULL, thread_loop, worker);
|
||||
if (ok) worker->status_ = OK;
|
||||
pthread_mutex_unlock(&worker->impl_->mutex_);
|
||||
if (!ok) {
|
||||
pthread_mutex_destroy(&worker->impl_->mutex_);
|
||||
pthread_cond_destroy(&worker->impl_->condition_);
|
||||
Error:
|
||||
vpx_free(worker->impl_);
|
||||
worker->impl_ = NULL;
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_unlock(&worker->mutex_);
|
||||
#else
|
||||
worker->status_ = OK;
|
||||
#endif
|
||||
} else if (worker->status_ > OK) {
|
||||
ok = sync(worker);
|
||||
ok = vp9_worker_sync(worker);
|
||||
}
|
||||
assert(!ok || (worker->status_ == OK));
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void execute(VP9Worker *const worker) {
|
||||
void vp9_worker_execute(VP9Worker* const worker) {
|
||||
if (worker->hook != NULL) {
|
||||
worker->had_error |= !worker->hook(worker->data1, worker->data2);
|
||||
}
|
||||
}
|
||||
|
||||
static void launch(VP9Worker *const worker) {
|
||||
void vp9_worker_launch(VP9Worker* const worker) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
change_state(worker, WORK);
|
||||
#else
|
||||
execute(worker);
|
||||
vp9_worker_execute(worker);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void end(VP9Worker *const worker) {
|
||||
void vp9_worker_end(VP9Worker* const worker) {
|
||||
if (worker->status_ >= OK) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
change_state(worker, NOT_OK);
|
||||
pthread_join(worker->impl_->thread_, NULL);
|
||||
pthread_mutex_destroy(&worker->impl_->mutex_);
|
||||
pthread_cond_destroy(&worker->impl_->condition_);
|
||||
pthread_join(worker->thread_, NULL);
|
||||
pthread_mutex_destroy(&worker->mutex_);
|
||||
pthread_cond_destroy(&worker->condition_);
|
||||
#else
|
||||
worker->status_ = NOT_OK;
|
||||
#endif
|
||||
}
|
||||
vpx_free(worker->impl_);
|
||||
worker->impl_ = NULL;
|
||||
assert(worker->status_ == NOT_OK);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static VP9WorkerInterface g_worker_interface = {
|
||||
init, reset, sync, launch, execute, end
|
||||
};
|
||||
|
||||
int vp9_set_worker_interface(const VP9WorkerInterface* const winterface) {
|
||||
if (winterface == NULL ||
|
||||
winterface->init == NULL || winterface->reset == NULL ||
|
||||
winterface->sync == NULL || winterface->launch == NULL ||
|
||||
winterface->execute == NULL || winterface->end == NULL) {
|
||||
return 0;
|
||||
}
|
||||
g_worker_interface = *winterface;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const VP9WorkerInterface *vp9_get_worker_interface(void) {
|
||||
return &g_worker_interface;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -11,7 +11,8 @@
|
||||
//
|
||||
// Original source:
|
||||
// http://git.chromium.org/webm/libwebp.git
|
||||
// 100644 blob 7bd451b124ae3b81596abfbcc823e3cb129d3a38 src/utils/thread.h
|
||||
// 100644 blob 13a61a4c84194c3374080cbf03d881d3cd6af40d src/utils/thread.h
|
||||
|
||||
|
||||
#ifndef VP9_DECODER_VP9_THREAD_H_
|
||||
#define VP9_DECODER_VP9_THREAD_H_
|
||||
@@ -162,53 +163,40 @@ typedef enum {
|
||||
// arguments (data1 and data2), and should return false in case of error.
|
||||
typedef int (*VP9WorkerHook)(void*, void*);
|
||||
|
||||
// Platform-dependent implementation details for the worker.
|
||||
typedef struct VP9WorkerImpl VP9WorkerImpl;
|
||||
|
||||
// Synchronization object used to launch job in the worker thread
|
||||
// Synchronize object used to launch job in the worker thread
|
||||
typedef struct {
|
||||
VP9WorkerImpl *impl_;
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_t mutex_;
|
||||
pthread_cond_t condition_;
|
||||
pthread_t thread_;
|
||||
#endif
|
||||
VP9WorkerStatus status_;
|
||||
VP9WorkerHook hook; // hook to call
|
||||
void *data1; // first argument passed to 'hook'
|
||||
void *data2; // second argument passed to 'hook'
|
||||
void* data1; // first argument passed to 'hook'
|
||||
void* data2; // second argument passed to 'hook'
|
||||
int had_error; // return value of the last call to 'hook'
|
||||
} VP9Worker;
|
||||
|
||||
// The interface for all thread-worker related functions. All these functions
|
||||
// must be implemented.
|
||||
typedef struct {
|
||||
// Must be called first, before any other method.
|
||||
void (*init)(VP9Worker *const worker);
|
||||
// Must be called to initialize the object and spawn the thread. Re-entrant.
|
||||
// Will potentially launch the thread. Returns false in case of error.
|
||||
int (*reset)(VP9Worker *const worker);
|
||||
// Makes sure the previous work is finished. Returns true if worker->had_error
|
||||
// was not set and no error condition was triggered by the working thread.
|
||||
int (*sync)(VP9Worker *const worker);
|
||||
// Triggers the thread to call hook() with data1 and data2 arguments. These
|
||||
// hook/data1/data2 values can be changed at any time before calling this
|
||||
// function, but not be changed afterward until the next call to Sync().
|
||||
void (*launch)(VP9Worker *const worker);
|
||||
// This function is similar to launch() except that it calls the
|
||||
// hook directly instead of using a thread. Convenient to bypass the thread
|
||||
// mechanism while still using the VP9Worker structs. sync() must
|
||||
// still be called afterward (for error reporting).
|
||||
void (*execute)(VP9Worker *const worker);
|
||||
// Kill the thread and terminate the object. To use the object again, one
|
||||
// must call reset() again.
|
||||
void (*end)(VP9Worker *const worker);
|
||||
} VP9WorkerInterface;
|
||||
|
||||
// Install a new set of threading functions, overriding the defaults. This
|
||||
// should be done before any workers are started, i.e., before any encoding or
|
||||
// decoding takes place. The contents of the interface struct are copied, it
|
||||
// is safe to free the corresponding memory after this call. This function is
|
||||
// not thread-safe. Return false in case of invalid pointer or methods.
|
||||
int vp9_set_worker_interface(const VP9WorkerInterface *const winterface);
|
||||
|
||||
// Retrieve the currently set thread worker interface.
|
||||
const VP9WorkerInterface *vp9_get_worker_interface(void);
|
||||
// Must be called first, before any other method.
|
||||
void vp9_worker_init(VP9Worker* const worker);
|
||||
// Must be called to initialize the object and spawn the thread. Re-entrant.
|
||||
// Will potentially launch the thread. Returns false in case of error.
|
||||
int vp9_worker_reset(VP9Worker* const worker);
|
||||
// Makes sure the previous work is finished. Returns true if worker->had_error
|
||||
// was not set and no error condition was triggered by the working thread.
|
||||
int vp9_worker_sync(VP9Worker* const worker);
|
||||
// Triggers the thread to call hook() with data1 and data2 argument. These
|
||||
// hook/data1/data2 can be changed at any time before calling this function,
|
||||
// but not be changed afterward until the next call to vp9_worker_sync().
|
||||
void vp9_worker_launch(VP9Worker* const worker);
|
||||
// This function is similar to vp9_worker_launch() except that it calls the
|
||||
// hook directly instead of using a thread. Convenient to bypass the thread
|
||||
// mechanism while still using the VP9Worker structs. vp9_worker_sync() must
|
||||
// still be called afterward (for error reporting).
|
||||
void vp9_worker_execute(VP9Worker* const worker);
|
||||
// Kill the thread and terminate the object. To use the object again, one
|
||||
// must call vp9_worker_reset() again.
|
||||
void vp9_worker_end(VP9Worker* const worker);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@@ -15,19 +15,8 @@
|
||||
|
||||
#include "vp9/encoder/vp9_segmentation.h"
|
||||
|
||||
#define AQ_C_SEGMENTS 3
|
||||
#define AQ_C_STRENGTHS 3
|
||||
static const int aq_c_active_segments[AQ_C_STRENGTHS] = {1, 2, 3};
|
||||
static const double aq_c_q_adj_factor[AQ_C_STRENGTHS][AQ_C_SEGMENTS] =
|
||||
{{1.0, 1.0, 1.0}, {1.0, 2.0, 1.0}, {1.0, 1.5, 2.5}};
|
||||
static const double aq_c_transitions[AQ_C_STRENGTHS][AQ_C_SEGMENTS] =
|
||||
{{1.0, 1.0, 1.0}, {1.0, 0.25, 0.0}, {1.0, 0.5, 0.25}};
|
||||
|
||||
static int get_aq_c_strength(int q_index) {
|
||||
// Approximate base quatizer (truncated to int)
|
||||
int base_quant = vp9_ac_quant(q_index, 0) / 4;
|
||||
return (base_quant > 20) + (base_quant > 45);
|
||||
}
|
||||
static const double in_frame_q_adj_ratio[MAX_SEGMENTS] =
|
||||
{1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
@@ -40,8 +29,6 @@ void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
|
||||
cpi->refresh_alt_ref_frame ||
|
||||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
|
||||
int segment;
|
||||
const int aq_strength = get_aq_c_strength(cm->base_qindex);
|
||||
const int active_segments = aq_c_active_segments[aq_strength];
|
||||
|
||||
// Clear down the segment map.
|
||||
vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
|
||||
@@ -49,16 +36,8 @@ void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
|
||||
// Clear down the complexity map used for rd.
|
||||
vpx_memset(cpi->complexity_map, 0, cm->mi_rows * cm->mi_cols);
|
||||
|
||||
vp9_clearall_segfeatures(seg);
|
||||
|
||||
// Segmentation only makes sense if the target bits per SB is above a
|
||||
// threshold. Below this the overheads will usually outweigh any benefit.
|
||||
if (cpi->rc.sb64_target_rate < 256) {
|
||||
vp9_disable_segmentation(seg);
|
||||
return;
|
||||
}
|
||||
|
||||
vp9_enable_segmentation(seg);
|
||||
vp9_clearall_segfeatures(seg);
|
||||
|
||||
// Select delta coding method.
|
||||
seg->abs_delta = SEGMENT_DELTADATA;
|
||||
@@ -67,14 +46,14 @@ void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
|
||||
vp9_disable_segfeature(seg, 0, SEG_LVL_ALT_Q);
|
||||
|
||||
// Use some of the segments for in frame Q adjustment.
|
||||
for (segment = 1; segment < active_segments; ++segment) {
|
||||
for (segment = 1; segment < 2; segment++) {
|
||||
int qindex_delta =
|
||||
vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type, cm->base_qindex,
|
||||
aq_c_q_adj_factor[aq_strength][segment]);
|
||||
in_frame_q_adj_ratio[segment]);
|
||||
|
||||
// For AQ complexity mode, we dont allow Q0 in a segment if the base
|
||||
// Q is not 0. Q0 (lossless) implies 4x4 only and in AQ mode 2 a segment
|
||||
// Q delta is sometimes applied without going back around the rd loop.
|
||||
// For AQ mode 2, we dont allow Q0 in a segment if the base Q is not 0.
|
||||
// Q0 (lossless) implies 4x4 only and in AQ mode 2 a segment Q delta
|
||||
// is sometimes applied without going back around the rd loop.
|
||||
// This could lead to an illegal combination of partition size and q.
|
||||
if ((cm->base_qindex != 0) && ((cm->base_qindex + qindex_delta) == 0)) {
|
||||
qindex_delta = -cm->base_qindex + 1;
|
||||
@@ -87,15 +66,10 @@ void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
|
||||
}
|
||||
}
|
||||
|
||||
// Select a segment for the current SB64 block.
|
||||
// The choice of segment for a block depends on the ratio of the projected
|
||||
// bits for the block vs a target average.
|
||||
// An "aq_strength" value determines how many segments are supported,
|
||||
// the set of transition points to use and the extent of the quantizer
|
||||
// adjustment for each segment (configured in vp9_setup_in_frame_q_adj()).
|
||||
// Select a segment for the current SB64
|
||||
void vp9_select_in_frame_q_segment(VP9_COMP *cpi,
|
||||
int mi_row, int mi_col,
|
||||
int output_enabled, int projected_rate) {
|
||||
int mi_row, int mi_col,
|
||||
int output_enabled, int projected_rate) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
|
||||
const int mi_offset = mi_row * cm->mi_cols + mi_col;
|
||||
@@ -115,22 +89,11 @@ void vp9_select_in_frame_q_segment(VP9_COMP *cpi,
|
||||
// It is converted to bits * 256 units.
|
||||
const int target_rate = (cpi->rc.sb64_target_rate * xmis * ymis * 256) /
|
||||
(bw * bh);
|
||||
const int aq_strength = get_aq_c_strength(cm->base_qindex);
|
||||
const int active_segments = aq_c_active_segments[aq_strength];
|
||||
|
||||
// The number of segments considered and the transition points used to
|
||||
// select them is determined by the "aq_strength" value.
|
||||
// Currently this loop only supports segments that reduce Q (i.e. where
|
||||
// there is undershoot.
|
||||
// The loop counts down towards segment 0 which is the default segment
|
||||
// with no Q adjustment.
|
||||
segment = active_segments - 1;
|
||||
while (segment > 0) {
|
||||
if (projected_rate <
|
||||
(target_rate * aq_c_transitions[aq_strength][segment])) {
|
||||
break;
|
||||
}
|
||||
--segment;
|
||||
if (projected_rate < (target_rate / 4)) {
|
||||
segment = 1;
|
||||
} else {
|
||||
segment = 0;
|
||||
}
|
||||
|
||||
if (target_rate > 0) {
|
||||
|
@@ -38,12 +38,32 @@ static struct vp9_token intra_mode_encodings[INTRA_MODES];
|
||||
static struct vp9_token switchable_interp_encodings[SWITCHABLE_FILTERS];
|
||||
static struct vp9_token partition_encodings[PARTITION_TYPES];
|
||||
static struct vp9_token inter_mode_encodings[INTER_MODES];
|
||||
#if CONFIG_COPY_CODING
|
||||
static struct vp9_token copy_mode_encodings_l2[2];
|
||||
static struct vp9_token copy_mode_encodings[COPY_MODE_COUNT - 1];
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static int vp9_check_supertx(VP9_COMMON *cm, int mi_row, int mi_col,
|
||||
BLOCK_SIZE bsize) {
|
||||
MODE_INFO **mi;
|
||||
|
||||
mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
|
||||
|
||||
return mi[0]->mbmi.tx_size == bsize_to_tx_size(bsize) &&
|
||||
mi[0]->mbmi.sb_type < bsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
void vp9_entropy_mode_init() {
|
||||
vp9_tokens_from_tree(intra_mode_encodings, vp9_intra_mode_tree);
|
||||
vp9_tokens_from_tree(switchable_interp_encodings, vp9_switchable_interp_tree);
|
||||
vp9_tokens_from_tree(partition_encodings, vp9_partition_tree);
|
||||
vp9_tokens_from_tree(inter_mode_encodings, vp9_inter_mode_tree);
|
||||
#if CONFIG_COPY_CODING
|
||||
vp9_tokens_from_tree(copy_mode_encodings_l2, vp9_copy_mode_tree_l2);
|
||||
vp9_tokens_from_tree(copy_mode_encodings, vp9_copy_mode_tree);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void write_intra_mode(vp9_writer *w, PREDICTION_MODE mode,
|
||||
@@ -58,6 +78,21 @@ static void write_inter_mode(vp9_writer *w, PREDICTION_MODE mode,
|
||||
&inter_mode_encodings[INTER_OFFSET(mode)]);
|
||||
}
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
static void write_copy_mode(VP9_COMMON *cm, vp9_writer *w, COPY_MODE mode,
|
||||
int inter_ref_count, int copy_mode_context) {
|
||||
if (inter_ref_count == 2) {
|
||||
vp9_write_token(w, vp9_copy_mode_tree_l2,
|
||||
cm->fc.copy_mode_probs_l2[copy_mode_context],
|
||||
©_mode_encodings_l2[mode - REF0]);
|
||||
} else if (inter_ref_count > 2) {
|
||||
vp9_write_token(w, vp9_copy_mode_tree,
|
||||
cm->fc.copy_mode_probs[copy_mode_context],
|
||||
©_mode_encodings[mode - REF0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void encode_unsigned_max(struct vp9_write_bit_buffer *wb,
|
||||
int data, int max) {
|
||||
vp9_wb_write_literal(wb, data, get_unsigned_bits(max));
|
||||
@@ -225,6 +260,9 @@ static void write_ref_frames(const VP9_COMP *cpi, vp9_writer *w) {
|
||||
}
|
||||
|
||||
static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
vp9_writer *w) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
const nmv_context *nmvc = &cm->fc.nmvc;
|
||||
@@ -239,7 +277,19 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
|
||||
const int is_inter = is_inter_block(mbmi);
|
||||
const int is_compound = has_second_ref(mbmi);
|
||||
int skip, ref;
|
||||
#if CONFIG_COPY_CODING
|
||||
int copy_mode_context = vp9_get_copy_mode_context(xd);
|
||||
#endif
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
if (bsize >= BLOCK_8X8 && mbmi->inter_ref_count > 0) {
|
||||
vp9_write(w, mbmi->copy_mode != NOREF,
|
||||
cm->fc.copy_noref_prob[copy_mode_context][bsize]);
|
||||
if (mbmi->copy_mode != NOREF)
|
||||
write_copy_mode(cm, w, mbmi->copy_mode, mbmi->inter_ref_count,
|
||||
copy_mode_context);
|
||||
}
|
||||
#endif
|
||||
if (seg->update_map) {
|
||||
if (seg->temporal_update) {
|
||||
const int pred_flag = mbmi->seg_id_predicted;
|
||||
@@ -252,20 +302,57 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
if (!supertx_enabled)
|
||||
#endif
|
||||
skip = write_skip(cpi, segment_id, mi, w);
|
||||
#if CONFIG_SUPERTX
|
||||
else
|
||||
skip = mbmi->skip;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
if (!supertx_enabled) {
|
||||
#endif
|
||||
#if CONFIG_COPY_CODING
|
||||
if (mbmi->copy_mode == NOREF)
|
||||
#endif
|
||||
if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
|
||||
vp9_write(w, is_inter, vp9_get_intra_inter_prob(cm, xd));
|
||||
#if CONFIG_SUPERTX
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled &&
|
||||
#endif
|
||||
!(is_inter &&
|
||||
(skip || vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)))) {
|
||||
write_selected_tx_size(cpi, mbmi->tx_size, bsize, w);
|
||||
}
|
||||
#if CONFIG_EXT_TX
|
||||
if (is_inter &&
|
||||
mbmi->tx_size <= TX_16X16 &&
|
||||
bsize >= BLOCK_8X8 &&
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled &&
|
||||
#endif
|
||||
!mbmi->skip &&
|
||||
!vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
|
||||
vp9_write(w, mbmi->ext_txfrm, cm->fc.ext_tx_prob);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!is_inter) {
|
||||
if (bsize >= BLOCK_8X8) {
|
||||
write_intra_mode(w, mode, cm->fc.y_mode_prob[size_group_lookup[bsize]]);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mode) && is_filter_enabled(mbmi->tx_size)) {
|
||||
vp9_write(w, mbmi->filterbit,
|
||||
cm->fc.filterintra_prob[mbmi->tx_size][mode]);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
int idx, idy;
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
||||
@@ -274,11 +361,28 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
|
||||
for (idx = 0; idx < 2; idx += num_4x4_w) {
|
||||
const PREDICTION_MODE b_mode = mi->bmi[idy * 2 + idx].as_mode;
|
||||
write_intra_mode(w, b_mode, cm->fc.y_mode_prob[0]);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(b_mode)) {
|
||||
vp9_write(w, mi->b_filter_info[idy * 2 + idx],
|
||||
cm->fc.filterintra_prob[0][b_mode]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
write_intra_mode(w, mbmi->uv_mode, cm->fc.uv_mode_prob[mode]);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mbmi->uv_mode) &&
|
||||
is_filter_enabled(get_uv_tx_size(mbmi))) {
|
||||
vp9_write(w, mbmi->uv_filterbit,
|
||||
cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
|
||||
}
|
||||
#endif
|
||||
#if !CONFIG_COPY_CODING
|
||||
} else {
|
||||
#else
|
||||
} else if (mbmi->copy_mode == NOREF) {
|
||||
#endif
|
||||
const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
|
||||
const vp9_prob *const inter_probs = cm->fc.inter_mode_probs[mode_ctx];
|
||||
write_ref_frames(cpi, w);
|
||||
@@ -300,6 +404,32 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
|
||||
assert(mbmi->interp_filter == cm->interp_filter);
|
||||
}
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
if ((cm->use_interintra) &&
|
||||
cpi->common.reference_mode != COMPOUND_REFERENCE &&
|
||||
is_interintra_allowed(bsize) &&
|
||||
is_inter_mode(mode) &&
|
||||
(mbmi->ref_frame[1] <= INTRA_FRAME)) {
|
||||
vp9_write(w, mbmi->ref_frame[1] == INTRA_FRAME,
|
||||
cm->fc.interintra_prob[bsize]);
|
||||
if (mbmi->ref_frame[1] == INTRA_FRAME) {
|
||||
write_intra_mode(w, mbmi->interintra_mode,
|
||||
cm->fc.y_mode_prob[size_group_lookup[bsize]]);
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (get_mask_bits_interintra(bsize) &&
|
||||
cm->use_masked_interintra) {
|
||||
vp9_write(w, mbmi->use_masked_interintra,
|
||||
cm->fc.masked_interintra_prob[bsize]);
|
||||
if (mbmi->use_masked_interintra) {
|
||||
vp9_write_literal(w, mbmi->interintra_mask_index,
|
||||
get_mask_bits_interintra(bsize));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bsize < BLOCK_8X8) {
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
||||
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
||||
@@ -326,6 +456,18 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
|
||||
allow_hp);
|
||||
}
|
||||
}
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
if (cm->use_masked_interinter &&
|
||||
cm->reference_mode != SINGLE_REFERENCE &&
|
||||
is_inter_mode(mode) &&
|
||||
get_mask_bits(mbmi->sb_type) &&
|
||||
mbmi->ref_frame[1] > INTRA_FRAME) {
|
||||
vp9_write(w, mbmi->use_masked_interinter,
|
||||
cm->fc.masked_interinter_prob[bsize]);
|
||||
if (mbmi->use_masked_interinter)
|
||||
vp9_write_literal(w, mbmi->mask_index, get_mask_bits(mbmi->sb_type));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,6 +492,11 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO **mi_8x8,
|
||||
|
||||
if (bsize >= BLOCK_8X8) {
|
||||
write_intra_mode(w, mbmi->mode, get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
|
||||
vp9_write(w, mbmi->filterbit,
|
||||
cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
|
||||
#endif
|
||||
} else {
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
||||
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
||||
@@ -360,15 +507,29 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, MODE_INFO **mi_8x8,
|
||||
const int block = idy * 2 + idx;
|
||||
write_intra_mode(w, mi->bmi[block].as_mode,
|
||||
get_y_mode_probs(mi, above_mi, left_mi, block));
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mi->bmi[block].as_mode))
|
||||
vp9_write(w, mi->b_filter_info[block],
|
||||
cm->fc.filterintra_prob[0][mi->bmi[block].as_mode]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_intra_mode(w, mbmi->uv_mode, vp9_kf_uv_mode_prob[mbmi->mode]);
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mbmi->uv_mode) &&
|
||||
is_filter_enabled(get_uv_tx_size(mbmi)))
|
||||
vp9_write(w, mbmi->uv_filterbit,
|
||||
cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void write_modes_b(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
vp9_writer *w, TOKENEXTRA **tok, TOKENEXTRA *tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
||||
@@ -384,11 +545,21 @@ static void write_modes_b(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
if (frame_is_intra_only(cm)) {
|
||||
write_mb_modes_kf(cpi, xd->mi, w);
|
||||
} else {
|
||||
#if CONFIG_SUPERTX
|
||||
pack_inter_mode_mvs(cpi, m, supertx_enabled, w);
|
||||
#else
|
||||
pack_inter_mode_mvs(cpi, m, w);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
if (!supertx_enabled) {
|
||||
#endif
|
||||
assert(*tok < tok_end);
|
||||
pack_mb_tokens(w, tok, tok_end);
|
||||
#if CONFIG_SUPERTX
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void write_partition(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
@@ -415,6 +586,9 @@ static void write_partition(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
static void write_modes_sb(VP9_COMP *cpi,
|
||||
const TileInfo *const tile,
|
||||
vp9_writer *w, TOKENEXTRA **tok, TOKENEXTRA *tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
int pack_token, int supertx_enabled,
|
||||
#endif
|
||||
int mi_row, int mi_col, BLOCK_SIZE bsize) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
||||
@@ -431,36 +605,105 @@ static void write_modes_sb(VP9_COMP *cpi,
|
||||
partition = partition_lookup[bsl][m->mbmi.sb_type];
|
||||
write_partition(cm, xd, bs, mi_row, mi_col, partition, bsize, w);
|
||||
subsize = get_subsize(bsize, partition);
|
||||
#if CONFIG_SUPERTX
|
||||
xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
|
||||
set_mi_row_col(xd, tile,
|
||||
mi_row, num_8x8_blocks_high_lookup[bsize],
|
||||
mi_col, num_8x8_blocks_wide_lookup[bsize],
|
||||
cm->mi_rows, cm->mi_cols);
|
||||
if (!supertx_enabled && cm->frame_type != KEY_FRAME &&
|
||||
partition != PARTITION_NONE && bsize <= BLOCK_32X32) {
|
||||
TX_SIZE supertx_size = bsize_to_tx_size(bsize); // b_width_log2(bsize);
|
||||
vp9_prob prob = partition == PARTITION_SPLIT ?
|
||||
cm->fc.supertxsplit_prob[supertx_size] :
|
||||
cm->fc.supertx_prob[supertx_size];
|
||||
supertx_enabled = (xd->mi[0]->mbmi.tx_size == supertx_size);
|
||||
vp9_write(w, supertx_enabled, prob);
|
||||
if (supertx_enabled) {
|
||||
vp9_write(w, xd->mi[0]->mbmi.skip, vp9_get_skip_prob(cm, xd));
|
||||
#if CONFIG_EXT_TX
|
||||
if (supertx_size <= TX_16X16 && !xd->mi[0]->mbmi.skip)
|
||||
vp9_write(w, xd->mi[0]->mbmi.ext_txfrm, cm->fc.ext_tx_prob);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (subsize < BLOCK_8X8) {
|
||||
write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
|
||||
write_modes_b(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col);
|
||||
} else {
|
||||
switch (partition) {
|
||||
case PARTITION_NONE:
|
||||
write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
|
||||
write_modes_b(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col);
|
||||
break;
|
||||
case PARTITION_HORZ:
|
||||
write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
|
||||
write_modes_b(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col);
|
||||
if (mi_row + bs < cm->mi_rows)
|
||||
write_modes_b(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col);
|
||||
write_modes_b(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row + bs, mi_col);
|
||||
break;
|
||||
case PARTITION_VERT:
|
||||
write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
|
||||
write_modes_b(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col);
|
||||
if (mi_col + bs < cm->mi_cols)
|
||||
write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs);
|
||||
write_modes_b(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col + bs);
|
||||
break;
|
||||
case PARTITION_SPLIT:
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, subsize);
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs,
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col, subsize);
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row, mi_col + bs,
|
||||
subsize);
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col,
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row + bs, mi_col,
|
||||
subsize);
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col + bs,
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
!supertx_enabled, supertx_enabled,
|
||||
#endif
|
||||
mi_row + bs, mi_col + bs,
|
||||
subsize);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
#if CONFIG_SUPERTX
|
||||
if (partition != PARTITION_NONE && supertx_enabled && pack_token) {
|
||||
assert(*tok < tok_end);
|
||||
pack_mb_tokens(w, tok, tok_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
// update partition context
|
||||
if (bsize >= BLOCK_8X8 &&
|
||||
@@ -478,7 +721,11 @@ static void write_modes(VP9_COMP *cpi,
|
||||
vp9_zero(cpi->mb.e_mbd.left_seg_context);
|
||||
for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
|
||||
mi_col += MI_BLOCK_SIZE)
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col,
|
||||
write_modes_sb(cpi, tile, w, tok, tok_end,
|
||||
#if CONFIG_SUPERTX
|
||||
1, 0,
|
||||
#endif
|
||||
mi_row, mi_col,
|
||||
BLOCK_64X64);
|
||||
}
|
||||
}
|
||||
@@ -1176,6 +1423,104 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) {
|
||||
cm->counts.partition[i], PARTITION_TYPES, &header_bc);
|
||||
|
||||
vp9_write_nmv_probs(cm, cm->allow_high_precision_mv, &header_bc);
|
||||
|
||||
#if CONFIG_EXT_TX
|
||||
vp9_cond_prob_diff_update(&header_bc, &fc->ext_tx_prob, cm->counts.ext_tx);
|
||||
#endif
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
if (cm->reference_mode != SINGLE_REFERENCE) {
|
||||
if (!cpi->dummy_packing && cm->use_masked_interinter) {
|
||||
cm->use_masked_interinter = 0;
|
||||
for (i = 0; i < BLOCK_SIZES; i++)
|
||||
if (get_mask_bits(i) && (cm->counts.masked_interinter[i][1] > 0)) {
|
||||
cm->use_masked_interinter = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vp9_write_bit(&header_bc, cm->use_masked_interinter);
|
||||
if (cm->use_masked_interinter) {
|
||||
for (i = 0; i < BLOCK_SIZES; i++)
|
||||
if (get_mask_bits(i))
|
||||
vp9_cond_prob_diff_update(&header_bc,
|
||||
&fc->masked_interinter_prob[i],
|
||||
cm->counts.masked_interinter[i]);
|
||||
} else {
|
||||
vp9_zero(cm->counts.masked_interinter);
|
||||
}
|
||||
} else {
|
||||
if (!cpi->dummy_packing)
|
||||
cm->use_masked_interinter = 0;
|
||||
vp9_zero(cm->counts.masked_interinter);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
if (cm->reference_mode != COMPOUND_REFERENCE) {
|
||||
if (!cpi->dummy_packing && cm->use_interintra) {
|
||||
cm->use_interintra = 0;
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (is_interintra_allowed(i) && (cm->counts.interintra[i][1] > 0)) {
|
||||
cm->use_interintra = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vp9_write_bit(&header_bc, cm->use_interintra);
|
||||
if (cm->use_interintra) {
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (is_interintra_allowed(i)) {
|
||||
vp9_cond_prob_diff_update(&header_bc,
|
||||
&fc->interintra_prob[i],
|
||||
cm->counts.interintra[i]);
|
||||
}
|
||||
}
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (!cpi->dummy_packing && cm->use_masked_interintra) {
|
||||
cm->use_masked_interintra = 0;
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (is_interintra_allowed(i) && get_mask_bits_interintra(i) &&
|
||||
(cm->counts.masked_interintra[i][1] > 0)) {
|
||||
cm->use_masked_interintra = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vp9_write_bit(&header_bc, cm->use_masked_interintra);
|
||||
if (cm->use_masked_interintra) {
|
||||
for (i = 0; i < BLOCK_SIZES; i++) {
|
||||
if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
|
||||
vp9_cond_prob_diff_update(&header_bc,
|
||||
&fc->masked_interintra_prob[i],
|
||||
cm->counts.masked_interintra[i]);
|
||||
}
|
||||
} else {
|
||||
vp9_zero(cm->counts.masked_interintra);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
vp9_zero(cm->counts.interintra);
|
||||
}
|
||||
} else {
|
||||
if (!cpi->dummy_packing)
|
||||
cm->use_interintra = 0;
|
||||
vp9_zero(cm->counts.interintra);
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (!cpi->dummy_packing)
|
||||
cm->use_masked_interintra = 0;
|
||||
vp9_zero(cm->counts.masked_interintra);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_COPY_CODING
|
||||
for (i = 0; i < COPY_MODE_CONTEXTS; i++) {
|
||||
prob_diff_update(vp9_copy_mode_tree_l2, cm->fc.copy_mode_probs_l2[i],
|
||||
cm->counts.copy_mode_l2[i], 2, &header_bc);
|
||||
prob_diff_update(vp9_copy_mode_tree, cm->fc.copy_mode_probs[i],
|
||||
cm->counts.copy_mode[i], 3, &header_bc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
vp9_stop_encode(&header_bc);
|
||||
|
@@ -20,12 +20,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned int sse;
|
||||
int sum;
|
||||
unsigned int var;
|
||||
} diff;
|
||||
|
||||
struct macroblock_plane {
|
||||
DECLARE_ALIGNED(16, int16_t, src_diff[64 * 64]);
|
||||
int16_t *qcoeff;
|
||||
@@ -35,7 +29,6 @@ struct macroblock_plane {
|
||||
|
||||
// Quantizer setings
|
||||
int16_t *quant_fp;
|
||||
int16_t *round_fp;
|
||||
int16_t *quant;
|
||||
int16_t *quant_shift;
|
||||
int16_t *zbin;
|
||||
@@ -111,9 +104,6 @@ struct macroblock {
|
||||
int use_lp32x32fdct;
|
||||
int skip_encode;
|
||||
|
||||
// use fast quantization process
|
||||
int quant_fp;
|
||||
|
||||
// skip forward transform and quantization
|
||||
int skip_txfm;
|
||||
|
||||
|
@@ -9,26 +9,21 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include "vpx_scale/yv12config.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
#include "vp9/common/vp9_reconinter.h"
|
||||
#include "vp9/encoder/vp9_denoiser.h"
|
||||
|
||||
#ifdef OUTPUT_YUV_DENOISED
|
||||
static void make_grayscale(YV12_BUFFER_CONFIG *yuv);
|
||||
#endif
|
||||
|
||||
static const int widths[] = {4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64};
|
||||
static const int heights[] = {4, 8, 4, 8, 16, 8, 16, 32, 16, 32, 64, 32, 64};
|
||||
|
||||
static VP9_DENOISER_DECISION update_running_avg(const uint8_t *mc_avg,
|
||||
int mc_avg_stride,
|
||||
uint8_t *avg, int avg_stride,
|
||||
const uint8_t *sig,
|
||||
int sig_stride,
|
||||
int increase_denoising,
|
||||
BLOCK_SIZE bs) {
|
||||
int vp9_denoiser_filter() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_running_avg(const uint8_t *mc_avg, int mc_avg_stride,
|
||||
uint8_t *avg, int avg_stride,
|
||||
const uint8_t *sig, int sig_stride,
|
||||
int increase_denoising, BLOCK_SIZE bs) {
|
||||
int r, c;
|
||||
int diff, adj, absdiff;
|
||||
int shift_inc1 = 0, shift_inc2 = 1;
|
||||
@@ -93,144 +88,9 @@ void copy_block(uint8_t *dest, int dest_stride,
|
||||
}
|
||||
}
|
||||
|
||||
static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser,
|
||||
MACROBLOCK *mb,
|
||||
BLOCK_SIZE bs,
|
||||
int increase_denoising,
|
||||
int mi_row,
|
||||
int mi_col) {
|
||||
// constants
|
||||
// TODO(tkopp): empirically determine good constants, or functions of block
|
||||
// size.
|
||||
int NOISE_MOTION_THRESHOLD = 25 * 25;
|
||||
int SSE_DIFF_THRESHOLD = heights[bs] * widths[bs] * 20;
|
||||
unsigned int SSE_THRESH = heights[bs] * widths[bs] * 40;
|
||||
unsigned int SSE_THRESH_HI = heights[bs] * widths[bs] * 60;
|
||||
|
||||
int mv_col, mv_row;
|
||||
int sse_diff = denoiser->zero_mv_sse - denoiser->best_sse;
|
||||
int sse_diff_thresh;
|
||||
int sse_thresh;
|
||||
MV_REFERENCE_FRAME frame;
|
||||
MACROBLOCKD *filter_mbd = &mb->e_mbd;
|
||||
MB_MODE_INFO *mbmi = &filter_mbd->mi[0]->mbmi;
|
||||
|
||||
// We will restore these after motion compensation.
|
||||
MB_MODE_INFO saved_mbmi = *mbmi;
|
||||
struct buf_2d saved_dst = filter_mbd->plane[0].dst;
|
||||
struct buf_2d saved_pre[2];
|
||||
saved_pre[0] = filter_mbd->plane[0].pre[0];
|
||||
saved_pre[1] = filter_mbd->plane[0].pre[1];
|
||||
|
||||
// Decide the threshold for sum squared error.
|
||||
mv_col = denoiser->best_sse_mv.as_mv.col;
|
||||
mv_row = denoiser->best_sse_mv.as_mv.row;
|
||||
if (mv_row * mv_row + mv_col * mv_col > NOISE_MOTION_THRESHOLD) {
|
||||
sse_diff_thresh = 0;
|
||||
} else {
|
||||
sse_diff_thresh = SSE_DIFF_THRESHOLD;
|
||||
}
|
||||
|
||||
frame = denoiser->best_reference_frame;
|
||||
|
||||
// If the best reference frame uses inter-prediction and there is enough of a
|
||||
// difference in sum-squared-error, use it.
|
||||
if (frame != INTRA_FRAME && sse_diff > sse_diff_thresh) {
|
||||
mbmi->ref_frame[0] = denoiser->best_reference_frame;
|
||||
mbmi->mode = denoiser->best_sse_inter_mode;
|
||||
mbmi->mv[0] = denoiser->best_sse_mv;
|
||||
} else {
|
||||
// Otherwise, use the zero reference frame.
|
||||
frame = denoiser->best_zeromv_reference_frame;
|
||||
|
||||
mbmi->ref_frame[0] = denoiser->best_zeromv_reference_frame;
|
||||
mbmi->mode = ZEROMV;
|
||||
mbmi->mv[0].as_int = 0;
|
||||
|
||||
denoiser->best_sse_inter_mode = ZEROMV;
|
||||
denoiser->best_sse_mv.as_int = 0;
|
||||
denoiser->best_sse = denoiser->zero_mv_sse;
|
||||
}
|
||||
|
||||
// Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser
|
||||
// struct.
|
||||
filter_mbd->plane[0].pre[0].buf =
|
||||
block_start(denoiser->running_avg_y[frame].y_buffer,
|
||||
denoiser->running_avg_y[frame].y_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[0].pre[0].stride = denoiser->running_avg_y[frame].y_stride;
|
||||
|
||||
filter_mbd->plane[1].pre[0].buf =
|
||||
block_start(denoiser->running_avg_y[frame].u_buffer,
|
||||
denoiser->running_avg_y[frame].uv_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[1].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
|
||||
|
||||
filter_mbd->plane[2].pre[0].buf =
|
||||
block_start(denoiser->running_avg_y[frame].v_buffer,
|
||||
denoiser->running_avg_y[frame].uv_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[2].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
|
||||
|
||||
filter_mbd->plane[0].pre[1].buf =
|
||||
block_start(denoiser->running_avg_y[frame].y_buffer,
|
||||
denoiser->running_avg_y[frame].y_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[0].pre[1].stride = denoiser->running_avg_y[frame].y_stride;
|
||||
|
||||
filter_mbd->plane[1].pre[1].buf =
|
||||
block_start(denoiser->running_avg_y[frame].u_buffer,
|
||||
denoiser->running_avg_y[frame].uv_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[1].pre[1].stride = denoiser->running_avg_y[frame].uv_stride;
|
||||
|
||||
filter_mbd->plane[2].pre[1].buf =
|
||||
block_start(denoiser->running_avg_y[frame].v_buffer,
|
||||
denoiser->running_avg_y[frame].uv_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[2].pre[1].stride = denoiser->running_avg_y[frame].uv_stride;
|
||||
|
||||
filter_mbd->plane[0].dst.buf =
|
||||
block_start(denoiser->mc_running_avg_y.y_buffer,
|
||||
denoiser->mc_running_avg_y.y_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[0].dst.stride = denoiser->mc_running_avg_y.y_stride;
|
||||
|
||||
filter_mbd->plane[1].dst.buf =
|
||||
block_start(denoiser->mc_running_avg_y.u_buffer,
|
||||
denoiser->mc_running_avg_y.uv_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[1].dst.stride = denoiser->mc_running_avg_y.y_stride;
|
||||
|
||||
filter_mbd->plane[2].dst.buf =
|
||||
block_start(denoiser->mc_running_avg_y.v_buffer,
|
||||
denoiser->mc_running_avg_y.uv_stride,
|
||||
mi_row, mi_col);
|
||||
filter_mbd->plane[2].dst.stride = denoiser->mc_running_avg_y.y_stride;
|
||||
|
||||
vp9_build_inter_predictors_sby(filter_mbd, mv_row, mv_col, bs);
|
||||
|
||||
// Restore everything to its original state
|
||||
filter_mbd->plane[0].pre[0] = saved_pre[0];
|
||||
filter_mbd->plane[0].pre[1] = saved_pre[1];
|
||||
filter_mbd->plane[0].dst = saved_dst;
|
||||
*mbmi = saved_mbmi;
|
||||
|
||||
mv_row = denoiser->best_sse_mv.as_mv.row;
|
||||
mv_col = denoiser->best_sse_mv.as_mv.col;
|
||||
sse_thresh = denoiser->increase_denoising ? SSE_THRESH_HI : SSE_THRESH;
|
||||
|
||||
// TODO(tkopp) why 8?
|
||||
if (denoiser->best_sse > sse_thresh ||
|
||||
mv_row * mv_row + mv_col * mv_col > 8 * NOISE_MOTION_THRESHOLD) {
|
||||
return COPY_BLOCK;
|
||||
}
|
||||
return FILTER_BLOCK;
|
||||
}
|
||||
|
||||
void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
|
||||
int mi_row, int mi_col, BLOCK_SIZE bs) {
|
||||
VP9_DENOISER_DECISION decision = FILTER_BLOCK;
|
||||
int decision = COPY_BLOCK;
|
||||
|
||||
YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
|
||||
YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
|
||||
@@ -239,9 +99,7 @@ void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
|
||||
mi_row, mi_col);
|
||||
struct buf_2d src = mb->plane[0].src;
|
||||
|
||||
decision = perform_motion_compensation(denoiser, mb, bs,
|
||||
denoiser->increase_denoising,
|
||||
mi_row, mi_col);
|
||||
|
||||
update_running_avg(mc_avg_start, mc_avg.y_stride, avg_start, avg.y_stride,
|
||||
mb->plane[0].src.buf, mb->plane[0].src.stride, 0, bs);
|
||||
|
||||
@@ -298,25 +156,7 @@ void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_denoiser_reset_frame_stats(VP9_DENOISER *denoiser) {
|
||||
denoiser->zero_mv_sse = UINT_MAX;
|
||||
denoiser->best_sse = UINT_MAX;
|
||||
}
|
||||
|
||||
void vp9_denoiser_update_frame_stats(VP9_DENOISER *denoiser, MB_MODE_INFO *mbmi,
|
||||
unsigned int sse, PREDICTION_MODE mode) {
|
||||
// TODO(tkopp): Use both MVs if possible
|
||||
if (mbmi->mv[0].as_int == 0 && sse < denoiser->zero_mv_sse) {
|
||||
denoiser->zero_mv_sse = sse;
|
||||
denoiser->best_zeromv_reference_frame = mbmi->ref_frame[0];
|
||||
}
|
||||
|
||||
if (mbmi->mv[0].as_int != 0 && sse < denoiser->best_sse) {
|
||||
denoiser->best_sse = sse;
|
||||
denoiser->best_sse_inter_mode = mode;
|
||||
denoiser->best_sse_mv = mbmi->mv[0];
|
||||
denoiser->best_reference_frame = mbmi->ref_frame[0];
|
||||
}
|
||||
void vp9_denoiser_update_frame_stats() {
|
||||
}
|
||||
|
||||
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
||||
@@ -331,9 +171,6 @@ int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
||||
vp9_denoiser_free(denoiser);
|
||||
return 1;
|
||||
}
|
||||
#ifdef OUTPUT_YUV_DENOISED
|
||||
make_grayscale(&denoiser->running_avg_y[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
|
||||
@@ -342,10 +179,6 @@ int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
||||
vp9_denoiser_free(denoiser);
|
||||
return 1;
|
||||
}
|
||||
#ifdef OUTPUT_YUV_DENOISED
|
||||
make_grayscale(&denoiser->running_avg_y[i]);
|
||||
#endif
|
||||
denoiser->increase_denoising = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -364,22 +197,3 @@ void vp9_denoiser_free(VP9_DENOISER *denoiser) {
|
||||
vp9_free_frame_buffer(&denoiser->mc_running_avg_y);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OUTPUT_YUV_DENOISED
|
||||
static void make_grayscale(YV12_BUFFER_CONFIG *yuv) {
|
||||
int r, c;
|
||||
uint8_t *u = yuv->u_buffer;
|
||||
uint8_t *v = yuv->v_buffer;
|
||||
|
||||
// The '/2's are there because we have a 440 buffer, but we want to output
|
||||
// 420.
|
||||
for (r = 0; r < yuv->uv_height / 2; ++r) {
|
||||
for (c = 0; c < yuv->uv_width / 2; ++c) {
|
||||
u[c] = UINT8_MAX / 2;
|
||||
v[c] = UINT8_MAX / 2;
|
||||
}
|
||||
u += yuv->uv_stride + yuv->uv_width / 2;
|
||||
v += yuv->uv_stride + yuv->uv_width / 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -18,22 +18,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum vp9_denoiser_decision {
|
||||
enum vp9_denoiser_decision {
|
||||
COPY_BLOCK,
|
||||
FILTER_BLOCK
|
||||
} VP9_DENOISER_DECISION;
|
||||
};
|
||||
|
||||
typedef struct vp9_denoiser {
|
||||
YV12_BUFFER_CONFIG running_avg_y[MAX_REF_FRAMES];
|
||||
YV12_BUFFER_CONFIG mc_running_avg_y;
|
||||
|
||||
unsigned int zero_mv_sse;
|
||||
unsigned int best_sse;
|
||||
int increase_denoising;
|
||||
PREDICTION_MODE best_sse_inter_mode;
|
||||
int_mv best_sse_mv;
|
||||
MV_REFERENCE_FRAME best_reference_frame;
|
||||
MV_REFERENCE_FRAME best_zeromv_reference_frame;
|
||||
} VP9_DENOISER;
|
||||
|
||||
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
|
||||
@@ -46,10 +38,7 @@ void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
|
||||
void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
|
||||
int mi_row, int mi_col, BLOCK_SIZE bs);
|
||||
|
||||
void vp9_denoiser_reset_frame_stats(VP9_DENOISER *denoiser);
|
||||
|
||||
void vp9_denoiser_update_frame_stats(VP9_DENOISER *denoiser, MB_MODE_INFO *mbmi,
|
||||
unsigned int sse, PREDICTION_MODE mode);
|
||||
void vp9_denoiser_update_frame_stats();
|
||||
|
||||
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
||||
int ssx, int ssy, int border);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -20,13 +20,6 @@ struct macroblock;
|
||||
struct yv12_buffer_config;
|
||||
struct VP9_COMP;
|
||||
|
||||
// Constants used in SOURCE_VAR_BASED_PARTITION
|
||||
#define VAR_HIST_MAX_BG_VAR 1000
|
||||
#define VAR_HIST_FACTOR 10
|
||||
#define VAR_HIST_BINS (VAR_HIST_MAX_BG_VAR / VAR_HIST_FACTOR + 1)
|
||||
#define VAR_HIST_LARGE_CUT_OFF 75
|
||||
#define VAR_HIST_SMALL_CUT_OFF 45
|
||||
|
||||
void vp9_setup_src_planes(struct macroblock *x,
|
||||
const struct yv12_buffer_config *src,
|
||||
int mi_row, int mi_col);
|
||||
|
@@ -306,56 +306,6 @@ void vp9_xform_quant_fp(MACROBLOCK *x, int plane, int block,
|
||||
MACROBLOCKD *const xd = &x->e_mbd;
|
||||
const struct macroblock_plane *const p = &x->plane[plane];
|
||||
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||
const scan_order *const scan_order = &vp9_default_scan_orders[tx_size];
|
||||
int16_t *const coeff = BLOCK_OFFSET(p->coeff, block);
|
||||
int16_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
|
||||
int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
|
||||
uint16_t *const eob = &p->eobs[block];
|
||||
const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
|
||||
int i, j;
|
||||
const int16_t *src_diff;
|
||||
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
|
||||
src_diff = &p->src_diff[4 * (j * diff_stride + i)];
|
||||
|
||||
switch (tx_size) {
|
||||
case TX_32X32:
|
||||
fdct32x32(x->use_lp32x32fdct, src_diff, coeff, diff_stride);
|
||||
vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round,
|
||||
p->quant, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob, scan_order->scan,
|
||||
scan_order->iscan);
|
||||
break;
|
||||
case TX_16X16:
|
||||
vp9_fdct16x16(src_diff, coeff, diff_stride);
|
||||
vp9_quantize_fp(coeff, 256, x->skip_block, p->zbin, p->round_fp,
|
||||
p->quant_fp, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob,
|
||||
scan_order->scan, scan_order->iscan);
|
||||
break;
|
||||
case TX_8X8:
|
||||
vp9_fdct8x8(src_diff, coeff, diff_stride);
|
||||
vp9_quantize_fp(coeff, 64, x->skip_block, p->zbin, p->round_fp,
|
||||
p->quant_fp, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob,
|
||||
scan_order->scan, scan_order->iscan);
|
||||
break;
|
||||
case TX_4X4:
|
||||
x->fwd_txm4x4(src_diff, coeff, diff_stride);
|
||||
vp9_quantize_fp(coeff, 16, x->skip_block, p->zbin, p->round_fp,
|
||||
p->quant_fp, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob,
|
||||
scan_order->scan, scan_order->iscan);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_xform_quant_dc(MACROBLOCK *x, int plane, int block,
|
||||
BLOCK_SIZE plane_bsize, TX_SIZE tx_size) {
|
||||
MACROBLOCKD *const xd = &x->e_mbd;
|
||||
const struct macroblock_plane *const p = &x->plane[plane];
|
||||
const struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||
int16_t *const coeff = BLOCK_OFFSET(p->coeff, block);
|
||||
int16_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
|
||||
int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
|
||||
@@ -410,6 +360,9 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
|
||||
const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
|
||||
int i, j;
|
||||
const int16_t *src_diff;
|
||||
#if CONFIG_EXT_TX
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
#endif
|
||||
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
|
||||
src_diff = &p->src_diff[4 * (j * diff_stride + i)];
|
||||
|
||||
@@ -422,21 +375,45 @@ void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
|
||||
scan_order->iscan);
|
||||
break;
|
||||
case TX_16X16:
|
||||
#if CONFIG_EXT_TX
|
||||
if (plane != 0 || mbmi->ext_txfrm == NORM) {
|
||||
#endif
|
||||
vp9_fdct16x16(src_diff, coeff, diff_stride);
|
||||
#if CONFIG_EXT_TX
|
||||
} else {
|
||||
vp9_fht16x16(src_diff, coeff, diff_stride, ADST_ADST);
|
||||
}
|
||||
#endif
|
||||
vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
|
||||
p->quant, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob,
|
||||
scan_order->scan, scan_order->iscan);
|
||||
break;
|
||||
case TX_8X8:
|
||||
#if CONFIG_EXT_TX
|
||||
if (plane != 0 || mbmi->ext_txfrm == NORM) {
|
||||
#endif
|
||||
vp9_fdct8x8(src_diff, coeff, diff_stride);
|
||||
#if CONFIG_EXT_TX
|
||||
} else {
|
||||
vp9_fht8x8(src_diff, coeff, diff_stride, ADST_ADST);
|
||||
}
|
||||
#endif
|
||||
vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round,
|
||||
p->quant, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob,
|
||||
scan_order->scan, scan_order->iscan);
|
||||
break;
|
||||
case TX_4X4:
|
||||
#if CONFIG_EXT_TX
|
||||
if (plane != 0 || mbmi->ext_txfrm == NORM) {
|
||||
#endif
|
||||
x->fwd_txm4x4(src_diff, coeff, diff_stride);
|
||||
#if CONFIG_EXT_TX
|
||||
} else {
|
||||
vp9_fht4x4(src_diff, coeff, diff_stride, ADST_ADST);
|
||||
}
|
||||
#endif
|
||||
vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round,
|
||||
p->quant, p->quant_shift, qcoeff, dqcoeff,
|
||||
pd->dequant, p->zbin_extra, eob,
|
||||
@@ -459,6 +436,9 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
int i, j;
|
||||
uint8_t *dst;
|
||||
ENTROPY_CONTEXT *a, *l;
|
||||
#if CONFIG_EXT_TX
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
#endif
|
||||
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
|
||||
dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
|
||||
a = &ctx->ta[plane][i];
|
||||
@@ -474,15 +454,11 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
|
||||
if (x->skip_txfm == 0) {
|
||||
// full forward transform and quantization
|
||||
if (!x->skip_recode) {
|
||||
if (x->quant_fp)
|
||||
vp9_xform_quant_fp(x, plane, block, plane_bsize, tx_size);
|
||||
else
|
||||
vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
|
||||
}
|
||||
if (!x->skip_recode)
|
||||
vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
|
||||
} else if (x->skip_txfm == 2) {
|
||||
// fast path forward transform and quantization
|
||||
vp9_xform_quant_dc(x, plane, block, plane_bsize, tx_size);
|
||||
vp9_xform_quant_fp(x, plane, block, plane_bsize, tx_size);
|
||||
} else {
|
||||
// skip forward transform
|
||||
p->eobs[block] = 0;
|
||||
@@ -508,16 +484,43 @@ static void encode_block(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
|
||||
break;
|
||||
case TX_16X16:
|
||||
#if CONFIG_EXT_TX
|
||||
if (plane != 0 || mbmi->ext_txfrm == NORM) {
|
||||
#endif
|
||||
vp9_idct16x16_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
|
||||
#if CONFIG_EXT_TX
|
||||
} else {
|
||||
vp9_iht16x16_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
|
||||
p->eobs[block]);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case TX_8X8:
|
||||
#if CONFIG_EXT_TX
|
||||
if (plane != 0 || mbmi->ext_txfrm == NORM) {
|
||||
#endif
|
||||
vp9_idct8x8_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
|
||||
#if CONFIG_EXT_TX
|
||||
} else {
|
||||
vp9_iht8x8_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
|
||||
p->eobs[block]);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case TX_4X4:
|
||||
#if CONFIG_EXT_TX
|
||||
if (plane != 0 || mbmi->ext_txfrm == NORM) {
|
||||
#endif
|
||||
// this is like vp9_short_idct4x4 but has a special case around eob<=1
|
||||
// which is significant (not just an optimization) for the lossless
|
||||
// case.
|
||||
x->itxm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
|
||||
#if CONFIG_EXT_TX
|
||||
} else {
|
||||
vp9_iht4x4_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
|
||||
p->eobs[block]);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Invalid transform size");
|
||||
@@ -533,6 +536,10 @@ static void encode_block_pass1(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
|
||||
int i, j;
|
||||
uint8_t *dst;
|
||||
#if CONFIG_EXT_TX
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
mbmi->ext_txfrm = NORM;
|
||||
#endif
|
||||
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
|
||||
dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
|
||||
|
||||
@@ -561,7 +568,7 @@ void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize) {
|
||||
|
||||
if (x->optimize && (!x->skip_recode || !x->skip_optimize)) {
|
||||
const struct macroblockd_plane* const pd = &xd->plane[plane];
|
||||
const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
|
||||
const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi) : mbmi->tx_size;
|
||||
vp9_get_entropy_contexts(bsize, tx_size, pd,
|
||||
ctx.ta[plane], ctx.tl[plane]);
|
||||
}
|
||||
@@ -571,6 +578,26 @@ void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize) {
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
void vp9_encode_sb_supertx(MACROBLOCK *x, BLOCK_SIZE bsize) {
|
||||
MACROBLOCKD *const xd = &x->e_mbd;
|
||||
struct optimize_ctx ctx;
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
struct encode_b_args arg = {x, &ctx, &mbmi->skip};
|
||||
int plane;
|
||||
|
||||
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
||||
BLOCK_SIZE plane_size = bsize - 3 * (plane > 0);
|
||||
const struct macroblockd_plane* const pd = &xd->plane[plane];
|
||||
const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi) : mbmi->tx_size;
|
||||
vp9_subtract_plane(x, bsize, plane);
|
||||
vp9_get_entropy_contexts(bsize, tx_size, pd,
|
||||
ctx.ta[plane], ctx.tl[plane]);
|
||||
encode_block(plane, 0, plane_size, bsize_to_tx_size(plane_size), &arg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
TX_SIZE tx_size, void *arg) {
|
||||
struct encode_b_args* const args = arg;
|
||||
@@ -585,6 +612,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
const scan_order *scan_order;
|
||||
TX_TYPE tx_type;
|
||||
PREDICTION_MODE mode;
|
||||
#if CONFIG_FILTERINTRA
|
||||
int fbit = 0;
|
||||
#endif
|
||||
const int bwl = b_width_log2(plane_bsize);
|
||||
const int diff_stride = 4 * (1 << bwl);
|
||||
uint8_t *src, *dst;
|
||||
@@ -598,11 +628,20 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
src = &p->src.buf[4 * (j * src_stride + i)];
|
||||
src_diff = &p->src_diff[4 * (j * diff_stride + i)];
|
||||
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
|
||||
fbit = xd->mi[0]->b_filter_info[block];
|
||||
else
|
||||
fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
|
||||
#endif
|
||||
switch (tx_size) {
|
||||
case TX_32X32:
|
||||
scan_order = &vp9_default_scan_orders[TX_32X32];
|
||||
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
|
||||
vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
fbit,
|
||||
#endif
|
||||
x->skip_encode ? src : dst,
|
||||
x->skip_encode ? src_stride : dst_stride,
|
||||
dst, dst_stride, i, j, plane);
|
||||
@@ -623,6 +662,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
scan_order = &vp9_scan_orders[TX_16X16][tx_type];
|
||||
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
|
||||
vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
fbit,
|
||||
#endif
|
||||
x->skip_encode ? src : dst,
|
||||
x->skip_encode ? src_stride : dst_stride,
|
||||
dst, dst_stride, i, j, plane);
|
||||
@@ -643,6 +685,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
scan_order = &vp9_scan_orders[TX_8X8][tx_type];
|
||||
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
|
||||
vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
fbit,
|
||||
#endif
|
||||
x->skip_encode ? src : dst,
|
||||
x->skip_encode ? src_stride : dst_stride,
|
||||
dst, dst_stride, i, j, plane);
|
||||
@@ -663,6 +708,9 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
|
||||
scan_order = &vp9_scan_orders[TX_4X4][tx_type];
|
||||
mode = plane == 0 ? get_y_mode(xd->mi[0], block) : mbmi->uv_mode;
|
||||
vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
fbit,
|
||||
#endif
|
||||
x->skip_encode ? src : dst,
|
||||
x->skip_encode ? src_stride : dst_stride,
|
||||
dst, dst_stride, i, j, plane);
|
||||
|
@@ -21,11 +21,12 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize);
|
||||
#if CONFIG_SUPERTX
|
||||
void vp9_encode_sb_supertx(MACROBLOCK *x, BLOCK_SIZE bsize);
|
||||
#endif
|
||||
void vp9_encode_sby_pass1(MACROBLOCK *x, BLOCK_SIZE bsize);
|
||||
void vp9_xform_quant_fp(MACROBLOCK *x, int plane, int block,
|
||||
BLOCK_SIZE plane_bsize, TX_SIZE tx_size);
|
||||
void vp9_xform_quant_dc(MACROBLOCK *x, int plane, int block,
|
||||
BLOCK_SIZE plane_bsize, TX_SIZE tx_size);
|
||||
void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
|
||||
BLOCK_SIZE plane_bsize, TX_SIZE tx_size);
|
||||
|
||||
|
@@ -194,18 +194,6 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
|
||||
lc->rc_twopass_stats_in.buf = NULL;
|
||||
lc->rc_twopass_stats_in.sz = 0;
|
||||
}
|
||||
|
||||
if (cpi->source_diff_var != NULL) {
|
||||
vpx_free(cpi->source_diff_var);
|
||||
cpi->source_diff_var = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
if (cpi->use_fp_mb_stats) {
|
||||
vpx_free(cpi->twopass.this_frame_mb_stats.mb_stats);
|
||||
cpi->twopass.this_frame_mb_stats.mb_stats = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void save_coding_context(VP9_COMP *cpi) {
|
||||
@@ -665,7 +653,12 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
|
||||
|
||||
#if CONFIG_DENOISING
|
||||
vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
// TODO(tkopp) An unrelated bug causes
|
||||
// cm->subsampling_{x,y} to be uninitialized at this point
|
||||
// in execution. For now we assume YUV-420, which is x/y
|
||||
// subsampling of 1.
|
||||
1, 1,
|
||||
// cm->subsampling_x, cm->subsampling_y,
|
||||
VP9_ENC_BORDER_IN_PIXELS);
|
||||
#endif
|
||||
}
|
||||
@@ -713,8 +706,7 @@ static void cal_nmvsadcosts_hp(int *mvsadcost[2]) {
|
||||
}
|
||||
|
||||
|
||||
VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
BufferPool *const pool) {
|
||||
VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
|
||||
unsigned int i, j;
|
||||
VP9_COMP *const cpi = vpx_memalign(32, sizeof(VP9_COMP));
|
||||
VP9_COMMON *const cm = cpi != NULL ? &cpi->common : NULL;
|
||||
@@ -735,7 +727,6 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
vp9_rtcd();
|
||||
|
||||
cpi->use_svc = 0;
|
||||
cpi->common.buffer_pool = pool;
|
||||
|
||||
init_config(cpi, oxcf);
|
||||
vp9_rc_init(&cpi->oxcf, cpi->pass, &cpi->rc);
|
||||
@@ -749,8 +740,6 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
cpi->alt_is_last = 0;
|
||||
cpi->gold_is_alt = 0;
|
||||
|
||||
cpi->skippable_frame = 0;
|
||||
|
||||
// Create the encoder segmentation map and set all entries to 0
|
||||
CHECK_MEM_ERROR(cm, cpi->segmentation_map,
|
||||
vpx_calloc(cm->mi_rows * cm->mi_cols, 1));
|
||||
@@ -775,17 +764,6 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
sizeof(*cpi->mbgraph_stats[i].mb_stats), 1));
|
||||
}
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
cpi->use_fp_mb_stats = 0;
|
||||
if (cpi->use_fp_mb_stats) {
|
||||
// a place holder for the mb stats obtained from the first pass
|
||||
CHECK_MEM_ERROR(cm, cpi->twopass.this_frame_mb_stats.mb_stats,
|
||||
vpx_calloc(cm->MBs * sizeof(FIRSTPASS_MB_STATS), 1));
|
||||
} else {
|
||||
cpi->twopass.this_frame_mb_stats.mb_stats = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
cpi->refresh_alt_ref_frame = 0;
|
||||
|
||||
// Note that at the moment multi_arf will not work with svc.
|
||||
@@ -932,12 +910,6 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
|
||||
set_speed_features(cpi);
|
||||
|
||||
// Allocate memory to store variances for a frame.
|
||||
CHECK_MEM_ERROR(cm, cpi->source_diff_var,
|
||||
vpx_calloc(cm->MBs, sizeof(diff)));
|
||||
cpi->source_var_thresh = 0;
|
||||
cpi->frames_till_next_var_check = 0;
|
||||
|
||||
// Default rd threshold factors for mode selection
|
||||
for (i = 0; i < BLOCK_SIZES; ++i) {
|
||||
for (j = 0; j < MAX_MODES; ++j)
|
||||
@@ -1013,6 +985,41 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
vp9_sub_pixel_avg_variance4x4,
|
||||
vp9_sad4x4x3, vp9_sad4x4x8, vp9_sad4x4x4d)
|
||||
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
#define MBFP(BT, MSDF, MVF, MSVF) \
|
||||
cpi->fn_ptr[BT].msdf = MSDF; \
|
||||
cpi->fn_ptr[BT].mvf = MVF; \
|
||||
cpi->fn_ptr[BT].msvf = MSVF;
|
||||
|
||||
MBFP(BLOCK_64X64, vp9_masked_sad64x64, vp9_masked_variance64x64,
|
||||
vp9_masked_sub_pixel_variance64x64)
|
||||
MBFP(BLOCK_64X32, vp9_masked_sad64x32, vp9_masked_variance64x32,
|
||||
vp9_masked_sub_pixel_variance64x32)
|
||||
MBFP(BLOCK_32X64, vp9_masked_sad32x64, vp9_masked_variance32x64,
|
||||
vp9_masked_sub_pixel_variance32x64)
|
||||
MBFP(BLOCK_32X32, vp9_masked_sad32x32, vp9_masked_variance32x32,
|
||||
vp9_masked_sub_pixel_variance32x32)
|
||||
MBFP(BLOCK_32X16, vp9_masked_sad32x16, vp9_masked_variance32x16,
|
||||
vp9_masked_sub_pixel_variance32x16)
|
||||
MBFP(BLOCK_16X32, vp9_masked_sad16x32, vp9_masked_variance16x32,
|
||||
vp9_masked_sub_pixel_variance16x32)
|
||||
MBFP(BLOCK_16X16, vp9_masked_sad16x16, vp9_masked_variance16x16,
|
||||
vp9_masked_sub_pixel_variance16x16)
|
||||
MBFP(BLOCK_16X8, vp9_masked_sad16x8, vp9_masked_variance16x8,
|
||||
vp9_masked_sub_pixel_variance16x8)
|
||||
MBFP(BLOCK_8X16, vp9_masked_sad8x16, vp9_masked_variance8x16,
|
||||
vp9_masked_sub_pixel_variance8x16)
|
||||
MBFP(BLOCK_8X8, vp9_masked_sad8x8, vp9_masked_variance8x8,
|
||||
vp9_masked_sub_pixel_variance8x8)
|
||||
MBFP(BLOCK_4X8, vp9_masked_sad4x8, vp9_masked_variance4x8,
|
||||
vp9_masked_sub_pixel_variance4x8)
|
||||
MBFP(BLOCK_8X4, vp9_masked_sad8x4, vp9_masked_variance8x4,
|
||||
vp9_masked_sub_pixel_variance8x4)
|
||||
MBFP(BLOCK_4X4, vp9_masked_sad4x4, vp9_masked_variance4x4,
|
||||
vp9_masked_sub_pixel_variance4x4)
|
||||
#endif
|
||||
|
||||
cpi->full_search_sad = vp9_full_search_sad;
|
||||
cpi->diamond_search_sad = vp9_diamond_search_sad;
|
||||
cpi->refining_search_sad = vp9_refining_search_sad;
|
||||
@@ -1275,7 +1282,7 @@ int vp9_get_reference_enc(VP9_COMP *cpi, int index, YV12_BUFFER_CONFIG **fb) {
|
||||
if (index < 0 || index >= REF_FRAMES)
|
||||
return -1;
|
||||
|
||||
*fb = &cm->buffer_pool->frame_bufs[cm->ref_frame_map[index]].buf;
|
||||
*fb = &cm->frame_bufs[cm->ref_frame_map[index]].buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1297,7 +1304,7 @@ int vp9_update_entropy(VP9_COMP * cpi, int update) {
|
||||
}
|
||||
|
||||
|
||||
#if defined(OUTPUT_YUV_SRC)
|
||||
#if defined(OUTPUT_YUV_SRC) || defined(OUTPUT_YUV_DENOISED)
|
||||
void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s, FILE *f) {
|
||||
uint8_t *src = s->y_buffer;
|
||||
int h = s->y_height;
|
||||
@@ -1325,38 +1332,6 @@ void vp9_write_yuv_frame(YV12_BUFFER_CONFIG *s, FILE *f) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OUTPUT_YUV_DENOISED)
|
||||
// The denoiser buffer is allocated as a YUV 440 buffer. This function writes it
|
||||
// as YUV 420. We simply use the top-left pixels of the UV buffers, since we do
|
||||
// not denoise the UV channels at this time. If ever we implement UV channel
|
||||
// denoising we will have to modify this.
|
||||
void vp9_write_yuv_frame_420(YV12_BUFFER_CONFIG *s, FILE *f) {
|
||||
uint8_t *src = s->y_buffer;
|
||||
int h = s->y_height;
|
||||
|
||||
do {
|
||||
fwrite(src, s->y_width, 1, f);
|
||||
src += s->y_stride;
|
||||
} while (--h);
|
||||
|
||||
src = s->u_buffer;
|
||||
h = s->uv_height / 2;
|
||||
|
||||
do {
|
||||
fwrite(src, s->uv_width / 2, 1, f);
|
||||
src += s->uv_stride + s->uv_width / 2;
|
||||
} while (--h);
|
||||
|
||||
src = s->v_buffer;
|
||||
h = s->uv_height / 2;
|
||||
|
||||
do {
|
||||
fwrite(src, s->uv_width / 2, 1, f);
|
||||
src += s->uv_stride + s->uv_width / 2;
|
||||
} while (--h);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OUTPUT_YUV_REC
|
||||
void vp9_write_yuv_rec_frame(VP9_COMMON *cm) {
|
||||
YV12_BUFFER_CONFIG *s = cm->frame_to_show;
|
||||
@@ -1544,13 +1519,14 @@ static int recode_loop_test(const VP9_COMP *cpi,
|
||||
|
||||
void vp9_update_reference_frames(VP9_COMP *cpi) {
|
||||
VP9_COMMON * const cm = &cpi->common;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
// 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) {
|
||||
ref_cnt_fb(frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
|
||||
ref_cnt_fb(frame_bufs, &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
|
||||
ref_cnt_fb(cm->frame_bufs,
|
||||
&cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
|
||||
ref_cnt_fb(cm->frame_bufs,
|
||||
&cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
|
||||
} else if (!cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
|
||||
cpi->rc.is_src_frame_alt_ref && !cpi->use_svc) {
|
||||
/* Preserve the previously existing golden frame and update the frame in
|
||||
@@ -1564,7 +1540,8 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
|
||||
*/
|
||||
int tmp;
|
||||
|
||||
ref_cnt_fb(frame_bufs, &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
|
||||
ref_cnt_fb(cm->frame_bufs,
|
||||
&cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
|
||||
|
||||
tmp = cpi->alt_fb_idx;
|
||||
cpi->alt_fb_idx = cpi->gld_fb_idx;
|
||||
@@ -1577,17 +1554,19 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
|
||||
arf_idx = gf_group->arf_update_idx[gf_group->index];
|
||||
}
|
||||
|
||||
ref_cnt_fb(frame_bufs, &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
|
||||
ref_cnt_fb(cm->frame_bufs,
|
||||
&cm->ref_frame_map[arf_idx], cm->new_fb_idx);
|
||||
}
|
||||
|
||||
if (cpi->refresh_golden_frame) {
|
||||
ref_cnt_fb(frame_bufs,
|
||||
ref_cnt_fb(cm->frame_bufs,
|
||||
&cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpi->refresh_last_frame) {
|
||||
ref_cnt_fb(frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
|
||||
ref_cnt_fb(cm->frame_bufs,
|
||||
&cm->ref_frame_map[cpi->lst_fb_idx], cm->new_fb_idx);
|
||||
}
|
||||
#if CONFIG_DENOISING
|
||||
vp9_denoiser_update_frame_info(&cpi->denoiser,
|
||||
@@ -1628,36 +1607,34 @@ void vp9_scale_references(VP9_COMP *cpi) {
|
||||
VP9_COMMON *cm = &cpi->common;
|
||||
MV_REFERENCE_FRAME ref_frame;
|
||||
const VP9_REFFRAME ref_mask[3] = {VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG};
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
|
||||
const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
|
||||
const YV12_BUFFER_CONFIG *const ref = &frame_bufs[idx].buf;
|
||||
const YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf;
|
||||
|
||||
// Need to convert from VP9_REFFRAME to index into ref_mask (subtract 1).
|
||||
if ((cpi->ref_frame_flags & ref_mask[ref_frame - 1]) &&
|
||||
(ref->y_crop_width != cm->width || ref->y_crop_height != cm->height)) {
|
||||
const int new_fb = get_free_fb(cm);
|
||||
vp9_realloc_frame_buffer(&frame_bufs[new_fb].buf,
|
||||
vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
|
||||
scale_and_extend_frame(ref, &frame_bufs[new_fb].buf);
|
||||
scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf);
|
||||
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
|
||||
} else {
|
||||
cpi->scaled_ref_idx[ref_frame - 1] = idx;
|
||||
++frame_bufs[idx].ref_count;
|
||||
cm->frame_bufs[idx].ref_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void release_scaled_references(VP9_COMP *cpi) {
|
||||
VP9_COMMON *cm = &cpi->common;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
--frame_bufs[cpi->scaled_ref_idx[i]].ref_count;
|
||||
for (i = 0; i < 3; i++)
|
||||
cm->frame_bufs[cpi->scaled_ref_idx[i]].ref_count--;
|
||||
}
|
||||
|
||||
static void full_to_model_count(unsigned int *model_count,
|
||||
@@ -2025,28 +2002,44 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_skippable_frame(VP9_COMP *cpi) {
|
||||
// If the current frame does not have non-zero motion vector detected in the
|
||||
// first pass, and so do its previous and forward frames, then this frame
|
||||
// can be skipped for partition check, and the partition size is assigned
|
||||
// according to the variance
|
||||
|
||||
SVC *const svc = &cpi->svc;
|
||||
const int is_spatial_svc = (svc->number_spatial_layers > 1) &&
|
||||
(svc->number_temporal_layers == 1);
|
||||
TWO_PASS *const twopass = is_spatial_svc ?
|
||||
&svc->layer_context[svc->spatial_layer_id].twopass
|
||||
: &cpi->twopass;
|
||||
|
||||
cpi->skippable_frame = (!frame_is_intra_only(&cpi->common) &&
|
||||
twopass->stats_in - 2 > twopass->stats_in_start &&
|
||||
twopass->stats_in < twopass->stats_in_end &&
|
||||
(twopass->stats_in - 1)->pcnt_inter - (twopass->stats_in - 1)->pcnt_motion
|
||||
== 1 &&
|
||||
(twopass->stats_in - 2)->pcnt_inter - (twopass->stats_in - 2)->pcnt_motion
|
||||
== 1 &&
|
||||
twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1);
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
static void select_masked_interinter_mode(VP9_COMP *cpi) {
|
||||
static const double threshold = 1/128.0;
|
||||
VP9_COMMON *cm = &cpi->common;
|
||||
int sum = cpi->masked_interinter_select_counts[1] +
|
||||
cpi->masked_interinter_select_counts[0];
|
||||
if (sum) {
|
||||
double fraction = (double) cpi->masked_interinter_select_counts[1] / sum;
|
||||
cm->use_masked_interinter = (fraction > threshold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
static void select_interintra_mode(VP9_COMP *cpi) {
|
||||
static const double threshold = 0.007;
|
||||
VP9_COMMON *cm = &cpi->common;
|
||||
int sum = cpi->interintra_select_count[1] + cpi->interintra_select_count[0];
|
||||
if (sum) {
|
||||
double fraction = (double)cpi->interintra_select_count[1] / (double)sum;
|
||||
cm->use_interintra = (fraction > threshold);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
static void select_masked_interintra_mode(VP9_COMP *cpi) {
|
||||
static const double threshold = 1/100.0;
|
||||
VP9_COMMON *cm = &cpi->common;
|
||||
int sum = cpi->masked_interintra_select_count[1] +
|
||||
cpi->masked_interintra_select_count[0];
|
||||
if (sum) {
|
||||
double fraction = (double)cpi->masked_interintra_select_count[1] /
|
||||
(double)sum;
|
||||
cm->use_masked_interintra = (fraction > threshold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
||||
size_t *size,
|
||||
@@ -2143,13 +2136,6 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
||||
if (cpi->pass == 2 && cpi->sf.static_segmentation)
|
||||
configure_static_seg_features(cpi);
|
||||
|
||||
// Check if the current frame is skippable for the partition search in the
|
||||
// second pass according to the first pass stats
|
||||
if (cpi->pass == 2 &&
|
||||
(!cpi->use_svc || cpi->svc.number_temporal_layers == 1)) {
|
||||
configure_skippable_frame(cpi);
|
||||
}
|
||||
|
||||
// For 1 pass CBR, check if we are dropping this frame.
|
||||
// Never drop on key frame.
|
||||
if (cpi->pass == 0 &&
|
||||
@@ -2190,7 +2176,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
||||
#endif
|
||||
|
||||
#ifdef OUTPUT_YUV_DENOISED
|
||||
vp9_write_yuv_frame_420(&cpi->denoiser.running_avg_y[INTRA_FRAME],
|
||||
vp9_write_yuv_frame(&cpi->denoiser.running_avg_y[INTRA_FRAME],
|
||||
yuv_denoised_file);
|
||||
#endif
|
||||
#ifdef OUTPUT_YUV_SRC
|
||||
@@ -2208,6 +2194,20 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
||||
vp9_set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
|
||||
}
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
if (cm->current_video_frame == 0)
|
||||
cm->use_masked_interinter = 0;
|
||||
#endif
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
if (cm->current_video_frame == 0) {
|
||||
cm->use_interintra = 1;
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
cm->use_masked_interintra = 1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cpi->sf.recode_loop == DISALLOW_RECODE) {
|
||||
encode_without_recode_loop(cpi, q);
|
||||
} else {
|
||||
@@ -2269,6 +2269,18 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
||||
vp9_adapt_mode_probs(cm);
|
||||
vp9_adapt_mv_probs(cm, cm->allow_high_precision_mv);
|
||||
}
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
select_masked_interinter_mode(cpi);
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
select_interintra_mode(cpi);
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
if (cpi->common.use_interintra)
|
||||
select_masked_interintra_mode(cpi);
|
||||
else
|
||||
cpi->common.use_masked_interintra = 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cpi->refresh_golden_frame == 1)
|
||||
@@ -2518,9 +2530,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||
MV_REFERENCE_FRAME ref_frame;
|
||||
int arf_src_index;
|
||||
const int is_spatial_svc = cpi->use_svc &&
|
||||
(cpi->svc.number_temporal_layers == 1) &&
|
||||
(cpi->svc.number_spatial_layers > 1);
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
(cpi->svc.number_temporal_layers == 1);
|
||||
|
||||
if (!cpi)
|
||||
return -1;
|
||||
@@ -2603,8 +2613,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||
cm->show_frame = 1;
|
||||
cm->intra_only = 0;
|
||||
|
||||
// Check to see if the frame to be encoded is an overlay for a previous
|
||||
// arf frame and if so configure it as such.
|
||||
// Check to see if the frame should be encoded as an arf overlay.
|
||||
check_src_altref(cpi);
|
||||
}
|
||||
}
|
||||
@@ -2658,7 +2667,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||
/* find a free buffer for the new frame, releasing the reference previously
|
||||
* held.
|
||||
*/
|
||||
--frame_bufs[cm->new_fb_idx].ref_count;
|
||||
cm->frame_bufs[cm->new_fb_idx].ref_count--;
|
||||
cm->new_fb_idx = get_free_fb(cm);
|
||||
|
||||
if (!cpi->use_svc && cpi->multi_arf_allowed) {
|
||||
@@ -2692,7 +2701,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
||||
|
||||
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
|
||||
const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
|
||||
YV12_BUFFER_CONFIG *const buf = &frame_bufs[idx].buf;
|
||||
YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf;
|
||||
RefBuffer *const ref_buf = &cm->frame_refs[ref_frame - 1];
|
||||
ref_buf->buf = buf;
|
||||
ref_buf->idx = idx;
|
||||
|
@@ -64,7 +64,6 @@ typedef struct {
|
||||
FRAME_CONTEXT fc;
|
||||
} CODING_CONTEXT;
|
||||
|
||||
|
||||
typedef enum {
|
||||
// encode_breakout is disabled.
|
||||
ENCODE_BREAKOUT_DISABLED = 0,
|
||||
@@ -262,8 +261,6 @@ typedef struct VP9_COMP {
|
||||
int alt_is_last; // Alt same as last ( short circuit altref search)
|
||||
int gold_is_alt; // don't do both alt and gold search ( just do gold).
|
||||
|
||||
int skippable_frame;
|
||||
|
||||
int scaled_ref_idx[3];
|
||||
int lst_fb_idx;
|
||||
int gld_fb_idx;
|
||||
@@ -348,10 +345,6 @@ typedef struct VP9_COMP {
|
||||
uint64_t time_pick_lpf;
|
||||
uint64_t time_encode_sb_row;
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
int use_fp_mb_stats;
|
||||
#endif
|
||||
|
||||
TWO_PASS twopass;
|
||||
|
||||
YV12_BUFFER_CONFIG alt_ref_buffer;
|
||||
@@ -405,11 +398,7 @@ typedef struct VP9_COMP {
|
||||
|
||||
SVC svc;
|
||||
|
||||
// Store frame variance info in SOURCE_VAR_BASED_PARTITION search type.
|
||||
diff *source_diff_var;
|
||||
// The threshold used in SOURCE_VAR_BASED_PARTITION search type.
|
||||
unsigned int source_var_thresh;
|
||||
int frames_till_next_var_check;
|
||||
int use_large_partition_rate;
|
||||
|
||||
int frame_flags;
|
||||
|
||||
@@ -420,6 +409,10 @@ typedef struct VP9_COMP {
|
||||
int intra_uv_mode_cost[FRAME_TYPES][INTRA_MODES];
|
||||
int y_mode_costs[INTRA_MODES][INTRA_MODES][INTRA_MODES];
|
||||
int switchable_interp_costs[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
|
||||
#if CONFIG_COPY_CODING
|
||||
int copy_mode_cost_l2[COPY_MODE_CONTEXTS][2];
|
||||
int copy_mode_cost[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 1];
|
||||
#endif
|
||||
|
||||
PICK_MODE_CONTEXT *leaf_tree;
|
||||
PC_TREE *pc_tree;
|
||||
@@ -432,12 +425,21 @@ typedef struct VP9_COMP {
|
||||
#if CONFIG_DENOISING
|
||||
VP9_DENOISER denoiser;
|
||||
#endif
|
||||
|
||||
#if CONFIG_MASKED_INTERINTER
|
||||
unsigned int masked_interinter_select_counts[2];
|
||||
#endif
|
||||
#if CONFIG_INTERINTRA
|
||||
unsigned int interintra_select_count[2];
|
||||
#if CONFIG_MASKED_INTERINTRA
|
||||
unsigned int masked_interintra_select_count[2];
|
||||
#endif
|
||||
#endif
|
||||
} VP9_COMP;
|
||||
|
||||
void vp9_initialize_enc();
|
||||
|
||||
struct VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
|
||||
BufferPool *const pool);
|
||||
struct VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf);
|
||||
void vp9_remove_compressor(VP9_COMP *cpi);
|
||||
|
||||
void vp9_change_config(VP9_COMP *cpi, const VP9EncoderConfig *oxcf);
|
||||
@@ -495,9 +497,8 @@ static INLINE int get_ref_frame_idx(const VP9_COMP *cpi,
|
||||
|
||||
static INLINE YV12_BUFFER_CONFIG *get_ref_frame_buffer(
|
||||
VP9_COMP *cpi, MV_REFERENCE_FRAME ref_frame) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
return &pool->frame_bufs[cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]]
|
||||
VP9_COMMON * const cm = &cpi->common;
|
||||
return &cm->frame_bufs[cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]]
|
||||
.buf;
|
||||
}
|
||||
|
||||
|
@@ -106,34 +106,6 @@ static int read_frame_stats(const TWO_PASS *p,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
static int input_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats,
|
||||
const VP9_COMMON *const cm) {
|
||||
FILE *fpfile;
|
||||
int ret;
|
||||
|
||||
fpfile = fopen("firstpass_mb.stt", "r");
|
||||
fseek(fpfile, cm->current_video_frame * cm->MBs * sizeof(FIRSTPASS_MB_STATS),
|
||||
SEEK_SET);
|
||||
ret = fread(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs,
|
||||
fpfile);
|
||||
fclose(fpfile);
|
||||
if (ret < cm->MBs) {
|
||||
return EOF;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void output_mb_stats(FIRSTPASS_FRAME_MB_STATS *fp_frame_stats,
|
||||
const VP9_COMMON *const cm) {
|
||||
FILE *fpfile;
|
||||
|
||||
fpfile = fopen("firstpass_mb.stt", "a");
|
||||
fwrite(fp_frame_stats->mb_stats, sizeof(FIRSTPASS_MB_STATS), cm->MBs, fpfile);
|
||||
fclose(fpfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) {
|
||||
if (p->stats_in >= p->stats_in_end)
|
||||
return EOF;
|
||||
@@ -480,10 +452,6 @@ void vp9_first_pass(VP9_COMP *cpi) {
|
||||
const MV zero_mv = {0, 0};
|
||||
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
FIRSTPASS_FRAME_MB_STATS *this_frame_mb_stats = &twopass->this_frame_mb_stats;
|
||||
#endif
|
||||
|
||||
vp9_clear_system_state();
|
||||
|
||||
set_first_pass_params(cpi);
|
||||
@@ -611,17 +579,6 @@ void vp9_first_pass(VP9_COMP *cpi) {
|
||||
// Accumulate the intra error.
|
||||
intra_error += (int64_t)this_error;
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
if (cpi->use_fp_mb_stats) {
|
||||
this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode =
|
||||
DC_PRED;
|
||||
this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err =
|
||||
this_error;
|
||||
this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv.as_int
|
||||
= 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set up limit values for motion vectors to prevent them extending
|
||||
// outside the UMV borders.
|
||||
x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
|
||||
@@ -747,17 +704,6 @@ void vp9_first_pass(VP9_COMP *cpi) {
|
||||
|
||||
best_ref_mv.as_int = mv.as_int;
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
if (cpi->use_fp_mb_stats) {
|
||||
this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mode =
|
||||
NEWMV;
|
||||
this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].err =
|
||||
motion_error;
|
||||
this_frame_mb_stats->mb_stats[mb_row * cm->mb_cols + mb_col].mv.
|
||||
as_int = mv.as_int;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mv.as_int) {
|
||||
++mvcount;
|
||||
|
||||
@@ -862,12 +808,6 @@ void vp9_first_pass(VP9_COMP *cpi) {
|
||||
twopass->this_frame_stats = fps;
|
||||
output_stats(&twopass->this_frame_stats, cpi->output_pkt_list);
|
||||
accumulate_stats(&twopass->total_stats, &fps);
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
if (cpi->use_fp_mb_stats) {
|
||||
output_mb_stats(this_frame_mb_stats, cm);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Copy the previous Last Frame back into gf and and arf buffers if
|
||||
@@ -1420,8 +1360,7 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
|
||||
twopass->gf_group.arf_src_offset[frame_index] =
|
||||
(unsigned char)(rc->baseline_gf_interval - 1);
|
||||
twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0];
|
||||
twopass->gf_group.arf_ref_idx[frame_index] =
|
||||
arf_buffer_indices[cpi->multi_arf_enabled && rc->source_alt_ref_active];
|
||||
twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
|
||||
++frame_index;
|
||||
|
||||
if (cpi->multi_arf_enabled) {
|
||||
@@ -2227,12 +2166,6 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
|
||||
|
||||
// Update the total stats remaining structure.
|
||||
subtract_stats(&twopass->total_left_stats, &this_frame);
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
if (cpi->use_fp_mb_stats) {
|
||||
input_mb_stats(&twopass->this_frame_mb_stats, cm);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void vp9_twopass_postencode_update(VP9_COMP *cpi) {
|
||||
|
@@ -18,18 +18,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
typedef struct {
|
||||
PREDICTION_MODE mode;
|
||||
int err;
|
||||
int_mv mv;
|
||||
} FIRSTPASS_MB_STATS;
|
||||
|
||||
typedef struct {
|
||||
FIRSTPASS_MB_STATS *mb_stats;
|
||||
} FIRSTPASS_FRAME_MB_STATS;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
double frame;
|
||||
double intra_error;
|
||||
@@ -88,10 +76,6 @@ typedef struct {
|
||||
double kf_intra_err_min;
|
||||
double gf_intra_err_min;
|
||||
|
||||
#if CONFIG_FP_MB_STATS
|
||||
FIRSTPASS_FRAME_MB_STATS this_frame_mb_stats;
|
||||
#endif
|
||||
|
||||
// Projected total bits available for a key frame group of frames
|
||||
int64_t kf_group_bits;
|
||||
|
||||
|
@@ -64,6 +64,9 @@ static unsigned int do_16x16_motion_iteration(VP9_COMP *cpi,
|
||||
xd->mi[0]->mbmi.mode = NEWMV;
|
||||
xd->mi[0]->mbmi.mv[0].as_mv = *dst_mv;
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
xd->mi[0]->mbmi.ref_frame[1] = NONE;
|
||||
#endif
|
||||
vp9_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_16X16);
|
||||
|
||||
/* restore UMV window */
|
||||
@@ -141,6 +144,9 @@ static int find_best_16x16_intra(VP9_COMP *cpi, PREDICTION_MODE *pbest_mode) {
|
||||
|
||||
xd->mi[0]->mbmi.mode = mode;
|
||||
vp9_predict_intra_block(xd, 0, 2, TX_16X16, mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
0,
|
||||
#endif
|
||||
x->plane[0].src.buf, x->plane[0].src.stride,
|
||||
xd->plane[0].dst.buf, xd->plane[0].dst.stride,
|
||||
0, 0, 0);
|
||||
|
@@ -1640,3 +1640,354 @@ int vp9_full_pixel_search(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
/* returns subpixel variance error function */
|
||||
#define DIST(r, c) \
|
||||
vfp->msvf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
|
||||
src_stride, mask, mask_stride, &sse)
|
||||
|
||||
/* checks if (r, c) has better score than previous best */
|
||||
|
||||
#define MVC(r, c) \
|
||||
(mvcost ? \
|
||||
((mvjcost[((r) != rr) * 2 + ((c) != rc)] + \
|
||||
mvcost[0][((r) - rr)] + mvcost[1][((c) - rc)]) * \
|
||||
error_per_bit + 4096) >> 13 : 0)
|
||||
|
||||
#define CHECK_BETTER(v, r, c) \
|
||||
if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
|
||||
thismse = (DIST(r, c)); \
|
||||
if ((v = MVC(r, c) + thismse) < besterr) { \
|
||||
besterr = v; \
|
||||
br = r; \
|
||||
bc = c; \
|
||||
*distortion = thismse; \
|
||||
*sse1 = sse; \
|
||||
} \
|
||||
} else { \
|
||||
v = INT_MAX; \
|
||||
}
|
||||
|
||||
int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
|
||||
uint8_t *mask, int mask_stride,
|
||||
MV *bestmv, const MV *ref_mv,
|
||||
int allow_hp,
|
||||
int error_per_bit,
|
||||
const vp9_variance_fn_ptr_t *vfp,
|
||||
int forced_stop,
|
||||
int iters_per_step,
|
||||
int *mvjcost, int *mvcost[2],
|
||||
int *distortion,
|
||||
unsigned int *sse1, int is_second) {
|
||||
const uint8_t *const z = x->plane[0].src.buf;
|
||||
const int src_stride = x->plane[0].src.stride;
|
||||
const MACROBLOCKD *xd = &x->e_mbd;
|
||||
unsigned int besterr = INT_MAX;
|
||||
unsigned int sse;
|
||||
unsigned int whichdir;
|
||||
int thismse;
|
||||
unsigned int halfiters = iters_per_step;
|
||||
unsigned int quarteriters = iters_per_step;
|
||||
unsigned int eighthiters = iters_per_step;
|
||||
|
||||
const int y_stride = xd->plane[0].pre[is_second].stride;
|
||||
const int offset = bestmv->row * y_stride + bestmv->col;
|
||||
const uint8_t *const y = xd->plane[0].pre[is_second].buf;
|
||||
|
||||
int rr = ref_mv->row;
|
||||
int rc = ref_mv->col;
|
||||
int br = bestmv->row * 8;
|
||||
int bc = bestmv->col * 8;
|
||||
int hstep = 4;
|
||||
const int minc = MAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
|
||||
const int maxc = MIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
|
||||
const int minr = MAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
|
||||
const int maxr = MIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
|
||||
|
||||
int tr = br;
|
||||
int tc = bc;
|
||||
|
||||
// central mv
|
||||
bestmv->row *= 8;
|
||||
bestmv->col *= 8;
|
||||
|
||||
// calculate central point error
|
||||
besterr = vfp->mvf(y + offset, y_stride, z, src_stride, mask, mask_stride,
|
||||
sse1);
|
||||
*distortion = besterr;
|
||||
besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
|
||||
|
||||
// 1/2 pel
|
||||
FIRST_LEVEL_CHECKS;
|
||||
if (halfiters > 1) {
|
||||
SECOND_LEVEL_CHECKS;
|
||||
}
|
||||
tr = br;
|
||||
tc = bc;
|
||||
|
||||
// Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
|
||||
if (forced_stop != 2) {
|
||||
hstep >>= 1;
|
||||
FIRST_LEVEL_CHECKS;
|
||||
if (quarteriters > 1) {
|
||||
SECOND_LEVEL_CHECKS;
|
||||
}
|
||||
tr = br;
|
||||
tc = bc;
|
||||
}
|
||||
|
||||
if (allow_hp && vp9_use_mv_hp(ref_mv) && forced_stop == 0) {
|
||||
hstep >>= 1;
|
||||
FIRST_LEVEL_CHECKS;
|
||||
if (eighthiters > 1) {
|
||||
SECOND_LEVEL_CHECKS;
|
||||
}
|
||||
tr = br;
|
||||
tc = bc;
|
||||
}
|
||||
// These lines insure static analysis doesn't warn that
|
||||
// tr and tc aren't used after the above point.
|
||||
(void) tr;
|
||||
(void) tc;
|
||||
|
||||
bestmv->row = br;
|
||||
bestmv->col = bc;
|
||||
|
||||
if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
|
||||
(abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
|
||||
return INT_MAX;
|
||||
|
||||
return besterr;
|
||||
}
|
||||
|
||||
#undef DIST
|
||||
#undef MVC
|
||||
#undef CHECK_BETTER
|
||||
|
||||
int vp9_get_masked_mvpred_var(const MACROBLOCK *x,
|
||||
uint8_t *mask, int mask_stride,
|
||||
const MV *best_mv, const MV *center_mv,
|
||||
const vp9_variance_fn_ptr_t *vfp,
|
||||
int use_mvcost, int is_second) {
|
||||
const MACROBLOCKD *const xd = &x->e_mbd;
|
||||
const struct buf_2d *const what = &x->plane[0].src;
|
||||
const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
|
||||
const MV mv = {best_mv->row * 8, best_mv->col * 8};
|
||||
unsigned int unused;
|
||||
|
||||
return vfp->mvf(what->buf, what->stride,
|
||||
get_buf_from_mv(in_what, best_mv), in_what->stride,
|
||||
mask, mask_stride, &unused) +
|
||||
(use_mvcost ? mv_err_cost(&mv, center_mv, x->nmvjointcost,
|
||||
x->mvcost, x->errorperbit) : 0);
|
||||
}
|
||||
|
||||
int vp9_masked_refining_search_sad_c(const MACROBLOCK *x,
|
||||
uint8_t *mask, int mask_stride,
|
||||
MV *ref_mv, int error_per_bit,
|
||||
int search_range,
|
||||
const vp9_variance_fn_ptr_t *fn_ptr,
|
||||
const MV *center_mv, int is_second) {
|
||||
const MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
|
||||
const MACROBLOCKD *const xd = &x->e_mbd;
|
||||
const struct buf_2d *const what = &x->plane[0].src;
|
||||
const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
|
||||
const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
|
||||
unsigned int best_sad = fn_ptr->msdf(what->buf, what->stride,
|
||||
get_buf_from_mv(in_what, ref_mv),
|
||||
in_what->stride, mask, mask_stride) +
|
||||
mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < search_range; i++) {
|
||||
int best_site = -1;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
const MV mv = {ref_mv->row + neighbors[j].row,
|
||||
ref_mv->col + neighbors[j].col};
|
||||
if (is_mv_in(x, &mv)) {
|
||||
unsigned int sad = fn_ptr->msdf(what->buf, what->stride,
|
||||
get_buf_from_mv(in_what, &mv), in_what->stride, mask, mask_stride);
|
||||
if (sad < best_sad) {
|
||||
sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
|
||||
if (sad < best_sad) {
|
||||
best_sad = sad;
|
||||
best_site = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_site == -1) {
|
||||
break;
|
||||
} else {
|
||||
ref_mv->row += neighbors[best_site].row;
|
||||
ref_mv->col += neighbors[best_site].col;
|
||||
}
|
||||
}
|
||||
return best_sad;
|
||||
}
|
||||
|
||||
int vp9_masked_diamond_search_sad_c(const MACROBLOCK *x,
|
||||
const search_site_config *cfg,
|
||||
uint8_t *mask, int mask_stride,
|
||||
MV *ref_mv, MV *best_mv,
|
||||
int search_param, int sad_per_bit, int *num00,
|
||||
const vp9_variance_fn_ptr_t *fn_ptr,
|
||||
const MV *center_mv, int is_second) {
|
||||
const MACROBLOCKD *const xd = &x->e_mbd;
|
||||
const struct buf_2d *const what = &x->plane[0].src;
|
||||
const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
|
||||
// search_param determines the length of the initial step and hence the number
|
||||
// of iterations
|
||||
// 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 =
|
||||
// (MAX_FIRST_STEP/4) pel... etc.
|
||||
const search_site *const ss = &cfg->ss[search_param * cfg->searches_per_step];
|
||||
const int tot_steps = (cfg->ss_count / cfg->searches_per_step) - search_param;
|
||||
const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
|
||||
const uint8_t *best_address, *in_what_ref;
|
||||
int best_sad = INT_MAX;
|
||||
int best_site = 0;
|
||||
int last_site = 0;
|
||||
int i, j, step;
|
||||
|
||||
clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
|
||||
in_what_ref = get_buf_from_mv(in_what, ref_mv);
|
||||
best_address = in_what_ref;
|
||||
*num00 = 0;
|
||||
*best_mv = *ref_mv;
|
||||
|
||||
// Check the starting position
|
||||
best_sad = fn_ptr->msdf(what->buf, what->stride,
|
||||
best_address, in_what->stride,
|
||||
mask, mask_stride) +
|
||||
mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit);
|
||||
|
||||
i = 1;
|
||||
|
||||
for (step = 0; step < tot_steps; step++) {
|
||||
for (j = 0; j < cfg->searches_per_step; j++) {
|
||||
const MV mv = {best_mv->row + ss[i].mv.row,
|
||||
best_mv->col + ss[i].mv.col};
|
||||
if (is_mv_in(x, &mv)) {
|
||||
int sad = fn_ptr->msdf(what->buf, what->stride,
|
||||
best_address + ss[i].offset, in_what->stride,
|
||||
mask, mask_stride);
|
||||
if (sad < best_sad) {
|
||||
sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit);
|
||||
if (sad < best_sad) {
|
||||
best_sad = sad;
|
||||
best_site = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (best_site != last_site) {
|
||||
best_mv->row += ss[best_site].mv.row;
|
||||
best_mv->col += ss[best_site].mv.col;
|
||||
best_address += ss[best_site].offset;
|
||||
last_site = best_site;
|
||||
#if defined(NEW_DIAMOND_SEARCH)
|
||||
while (1) {
|
||||
const MV this_mv = {best_mv->row + ss[best_site].mv.row,
|
||||
best_mv->col + ss[best_site].mv.col};
|
||||
if (is_mv_in(x, &this_mv)) {
|
||||
int sad = fn_ptr->msdf(what->buf, what->stride,
|
||||
best_address + ss[best_site].offset,
|
||||
in_what->stride, mask, mask_stride);
|
||||
if (sad < best_sad) {
|
||||
sad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
|
||||
if (sad < best_sad) {
|
||||
best_sad = sad;
|
||||
best_mv->row += ss[best_site].mv.row;
|
||||
best_mv->col += ss[best_site].mv.col;
|
||||
best_address += ss[best_site].offset;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} else if (best_address == in_what_ref) {
|
||||
(*num00)++;
|
||||
}
|
||||
}
|
||||
return best_sad;
|
||||
}
|
||||
|
||||
int vp9_masked_full_pixel_diamond(const VP9_COMP *cpi, MACROBLOCK *x,
|
||||
uint8_t *mask, int mask_stride,
|
||||
MV *mvp_full, int step_param,
|
||||
int sadpb, int further_steps, int do_refine,
|
||||
const vp9_variance_fn_ptr_t *fn_ptr,
|
||||
const MV *ref_mv, MV *dst_mv,
|
||||
int is_second) {
|
||||
MV temp_mv;
|
||||
int thissme, n, num00 = 0;
|
||||
int bestsme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
|
||||
mask, mask_stride,
|
||||
mvp_full, &temp_mv,
|
||||
step_param, sadpb, &n,
|
||||
fn_ptr, ref_mv, is_second);
|
||||
if (bestsme < INT_MAX)
|
||||
bestsme = vp9_get_masked_mvpred_var(x, mask, mask_stride, &temp_mv, ref_mv,
|
||||
fn_ptr, 1, is_second);
|
||||
*dst_mv = temp_mv;
|
||||
|
||||
// If there won't be more n-step search, check to see if refining search is
|
||||
// needed.
|
||||
if (n > further_steps)
|
||||
do_refine = 0;
|
||||
|
||||
while (n < further_steps) {
|
||||
++n;
|
||||
|
||||
if (num00) {
|
||||
num00--;
|
||||
} else {
|
||||
thissme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
|
||||
mask, mask_stride,
|
||||
mvp_full, &temp_mv,
|
||||
step_param + n, sadpb, &num00,
|
||||
fn_ptr, ref_mv, is_second);
|
||||
if (thissme < INT_MAX)
|
||||
thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
|
||||
&temp_mv, ref_mv, fn_ptr, 1,
|
||||
is_second);
|
||||
|
||||
// check to see if refining search is needed.
|
||||
if (num00 > further_steps - n)
|
||||
do_refine = 0;
|
||||
|
||||
if (thissme < bestsme) {
|
||||
bestsme = thissme;
|
||||
*dst_mv = temp_mv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// final 1-away diamond refining search
|
||||
if (do_refine) {
|
||||
const int search_range = 8;
|
||||
MV best_mv = *dst_mv;
|
||||
thissme = vp9_masked_refining_search_sad_c(x, mask, mask_stride,
|
||||
&best_mv, sadpb, search_range,
|
||||
fn_ptr, ref_mv, is_second);
|
||||
if (thissme < INT_MAX)
|
||||
thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
|
||||
&best_mv, ref_mv, fn_ptr, 1,
|
||||
is_second);
|
||||
if (thissme < bestsme) {
|
||||
bestsme = thissme;
|
||||
*dst_mv = best_mv;
|
||||
}
|
||||
}
|
||||
return bestsme;
|
||||
}
|
||||
#endif
|
||||
|
@@ -153,6 +153,29 @@ int vp9_full_pixel_search(struct VP9_COMP *cpi, MACROBLOCK *x,
|
||||
int step_param, int error_per_bit,
|
||||
const MV *ref_mv, MV *tmp_mv,
|
||||
int var_max, int rd);
|
||||
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
|
||||
uint8_t *mask, int mask_stride,
|
||||
MV *bestmv, const MV *ref_mv,
|
||||
int allow_hp,
|
||||
int error_per_bit,
|
||||
const vp9_variance_fn_ptr_t *vfp,
|
||||
int forced_stop,
|
||||
int iters_per_step,
|
||||
int *mvjcost, int *mvcost[2],
|
||||
int *distortion,
|
||||
unsigned int *sse1, int is_second);
|
||||
int vp9_masked_full_pixel_diamond(const struct VP9_COMP *cpi, MACROBLOCK *x,
|
||||
uint8_t *mask, int mask_stride,
|
||||
MV *mvp_full, int step_param,
|
||||
int sadpb, int further_steps, int do_refine,
|
||||
const vp9_variance_fn_ptr_t *fn_ptr,
|
||||
const MV *ref_mv, MV *dst_mv,
|
||||
int is_second);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -144,9 +144,7 @@ void vp9_pick_filter_level(const YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi,
|
||||
lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0
|
||||
: cpi->oxcf.sharpness;
|
||||
|
||||
if (method == LPF_PICK_MINIMAL_LPF && lf->filter_level) {
|
||||
lf->filter_level = 0;
|
||||
} else if (method >= LPF_PICK_FROM_Q) {
|
||||
if (method == LPF_PICK_FROM_Q) {
|
||||
const int min_filter_level = 0;
|
||||
const int max_filter_level = get_max_filter_level(cpi);
|
||||
const int q = vp9_ac_quant(cm->base_qindex, 0);
|
||||
|
@@ -252,17 +252,6 @@ static void model_rd_for_sb_y(VP9_COMP *cpi, BLOCK_SIZE bsize,
|
||||
else
|
||||
x->skip_txfm = 0;
|
||||
|
||||
if (cpi->common.tx_mode == TX_MODE_SELECT) {
|
||||
if (sse > (var << 2))
|
||||
xd->mi[0]->mbmi.tx_size = MIN(max_txsize_lookup[bsize],
|
||||
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
|
||||
else
|
||||
xd->mi[0]->mbmi.tx_size = TX_8X8;
|
||||
} else {
|
||||
xd->mi[0]->mbmi.tx_size = MIN(max_txsize_lookup[bsize],
|
||||
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
|
||||
}
|
||||
|
||||
vp9_model_rd_from_var_lapndz(sse - var, 1 << num_pels_log2_lookup[bsize],
|
||||
dc_quant >> 3, &rate, &dist);
|
||||
*out_rate_sum = rate >> 1;
|
||||
@@ -290,93 +279,6 @@ static void free_pred_buffer(PRED_BUFFER *p) {
|
||||
p->in_use = 0;
|
||||
}
|
||||
|
||||
static void encode_breakout_test(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
BLOCK_SIZE bsize, int mi_row, int mi_col,
|
||||
MV_REFERENCE_FRAME ref_frame,
|
||||
PREDICTION_MODE this_mode,
|
||||
unsigned int var_y, unsigned int sse_y,
|
||||
struct buf_2d yv12_mb[][MAX_MB_PLANE],
|
||||
int *rate, int64_t *dist) {
|
||||
MACROBLOCKD *xd = &x->e_mbd;
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
|
||||
const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
|
||||
unsigned int var = var_y, sse = sse_y;
|
||||
// Skipping threshold for ac.
|
||||
unsigned int thresh_ac;
|
||||
// Skipping threshold for dc.
|
||||
unsigned int thresh_dc;
|
||||
if (x->encode_breakout > 0) {
|
||||
// Set a maximum for threshold to avoid big PSNR loss in low bit rate
|
||||
// case. Use extreme low threshold for static frames to limit
|
||||
// skipping.
|
||||
const unsigned int max_thresh = 36000;
|
||||
// The encode_breakout input
|
||||
const unsigned int min_thresh =
|
||||
MIN(((unsigned int)x->encode_breakout << 4), max_thresh);
|
||||
|
||||
// Calculate threshold according to dequant value.
|
||||
thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
|
||||
thresh_ac = clamp(thresh_ac, min_thresh, max_thresh);
|
||||
|
||||
// Adjust ac threshold according to partition size.
|
||||
thresh_ac >>=
|
||||
8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
|
||||
|
||||
thresh_dc = (xd->plane[0].dequant[0] * xd->plane[0].dequant[0] >> 6);
|
||||
} else {
|
||||
thresh_ac = 0;
|
||||
thresh_dc = 0;
|
||||
}
|
||||
|
||||
// Y skipping condition checking for ac and dc.
|
||||
if (var <= thresh_ac && (sse - var) <= thresh_dc) {
|
||||
unsigned int sse_u, sse_v;
|
||||
unsigned int var_u, var_v;
|
||||
|
||||
// Skip UV prediction unless breakout is zero (lossless) to save
|
||||
// computation with low impact on the result
|
||||
if (x->encode_breakout == 0) {
|
||||
xd->plane[1].pre[0] = yv12_mb[ref_frame][1];
|
||||
xd->plane[2].pre[0] = yv12_mb[ref_frame][2];
|
||||
vp9_build_inter_predictors_sbuv(xd, mi_row, mi_col, bsize);
|
||||
}
|
||||
|
||||
var_u = cpi->fn_ptr[uv_size].vf(x->plane[1].src.buf,
|
||||
x->plane[1].src.stride,
|
||||
xd->plane[1].dst.buf,
|
||||
xd->plane[1].dst.stride, &sse_u);
|
||||
|
||||
// U skipping condition checking
|
||||
if ((var_u * 4 <= thresh_ac) && (sse_u - var_u <= thresh_dc)) {
|
||||
var_v = cpi->fn_ptr[uv_size].vf(x->plane[2].src.buf,
|
||||
x->plane[2].src.stride,
|
||||
xd->plane[2].dst.buf,
|
||||
xd->plane[2].dst.stride, &sse_v);
|
||||
|
||||
// V skipping condition checking
|
||||
if ((var_v * 4 <= thresh_ac) && (sse_v - var_v <= thresh_dc)) {
|
||||
x->skip = 1;
|
||||
|
||||
// The cost of skip bit needs to be added.
|
||||
*rate = cpi->inter_mode_cost[mbmi->mode_context[ref_frame]]
|
||||
[INTER_OFFSET(this_mode)];
|
||||
|
||||
// More on this part of rate
|
||||
// rate += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
|
||||
|
||||
// Scaling factor for SSE from spatial domain to frequency
|
||||
// domain is 16. Adjust distortion accordingly.
|
||||
// TODO(yunqingwang): In this function, only y-plane dist is
|
||||
// calculated.
|
||||
*dist = (sse << 4); // + ((sse_u + sse_v) << 4);
|
||||
|
||||
// *disable_skip = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(jingning) placeholder for inter-frame non-RD mode decision.
|
||||
// this needs various further optimizations. to be continued..
|
||||
int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
@@ -391,8 +293,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
struct macroblockd_plane *const pd = &xd->plane[0];
|
||||
PREDICTION_MODE this_mode, best_mode = ZEROMV;
|
||||
MV_REFERENCE_FRAME ref_frame, best_ref_frame = LAST_FRAME;
|
||||
TX_SIZE best_tx_size = MIN(max_txsize_lookup[bsize],
|
||||
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
|
||||
INTERP_FILTER best_pred_filter = EIGHTTAP;
|
||||
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
|
||||
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
|
||||
@@ -420,10 +320,10 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
const int *const rd_thresh_freq_fact = cpi->rd.thresh_freq_fact[bsize];
|
||||
// Mode index conversion form THR_MODES to PREDICTION_MODE for a ref frame.
|
||||
int mode_idx[MB_MODE_COUNT] = {0};
|
||||
INTERP_FILTER filter_ref = cm->interp_filter;
|
||||
INTERP_FILTER filter_ref = SWITCHABLE;
|
||||
int bsl = mi_width_log2_lookup[bsize];
|
||||
const int pred_filter_search = cm->interp_filter == SWITCHABLE ?
|
||||
(((mi_row + mi_col) >> bsl) + get_chessboard_index(cm)) % 2 : 0;
|
||||
const int pred_filter_search = (((mi_row + mi_col) >> bsl) +
|
||||
get_chessboard_index(cm)) % 2;
|
||||
int const_motion[MAX_REF_FRAMES] = { 0 };
|
||||
|
||||
// For speed 6, the result of interp filter is reused later in actual encoding
|
||||
@@ -439,10 +339,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
PRED_BUFFER *this_mode_pred = NULL;
|
||||
int i;
|
||||
|
||||
#if CONFIG_DENOISING
|
||||
vp9_denoiser_reset_frame_stats(&cpi->denoiser);
|
||||
#endif
|
||||
|
||||
if (cpi->sf.reuse_inter_pred_sby) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
tmp[i].data = &pred_buf[pixels_in_block * i];
|
||||
@@ -590,7 +486,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
int64_t pf_dist[3];
|
||||
unsigned int pf_var[3];
|
||||
unsigned int pf_sse[3];
|
||||
TX_SIZE pf_tx_size[3];
|
||||
int64_t best_cost = INT64_MAX;
|
||||
INTERP_FILTER best_filter = SWITCHABLE, filter;
|
||||
PRED_BUFFER *current_pred = this_mode_pred;
|
||||
@@ -604,7 +499,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
cost = RDCOST(x->rdmult, x->rddiv,
|
||||
vp9_get_switchable_rate(cpi) + pf_rate[filter],
|
||||
pf_dist[filter]);
|
||||
pf_tx_size[filter] = mbmi->tx_size;
|
||||
if (cost < best_cost) {
|
||||
best_filter = filter;
|
||||
best_cost = cost;
|
||||
@@ -629,7 +523,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
free_pred_buffer(current_pred);
|
||||
|
||||
mbmi->interp_filter = best_filter;
|
||||
mbmi->tx_size = pf_tx_size[mbmi->interp_filter];
|
||||
rate = pf_rate[mbmi->interp_filter];
|
||||
dist = pf_dist[mbmi->interp_filter];
|
||||
var_y = pf_var[mbmi->interp_filter];
|
||||
@@ -649,16 +542,80 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
// Skipping checking: test to see if this block can be reconstructed by
|
||||
// prediction only.
|
||||
if (cpi->allow_encode_breakout) {
|
||||
encode_breakout_test(cpi, x, bsize, mi_row, mi_col, ref_frame,
|
||||
this_mode, var_y, sse_y, yv12_mb, &rate, &dist);
|
||||
if (x->skip) {
|
||||
rate += rate_mv;
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate, dist);
|
||||
const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
|
||||
unsigned int var = var_y, sse = sse_y;
|
||||
// Skipping threshold for ac.
|
||||
unsigned int thresh_ac;
|
||||
// Skipping threshold for dc.
|
||||
unsigned int thresh_dc;
|
||||
if (x->encode_breakout > 0) {
|
||||
// Set a maximum for threshold to avoid big PSNR loss in low bit rate
|
||||
// case. Use extreme low threshold for static frames to limit
|
||||
// skipping.
|
||||
const unsigned int max_thresh = 36000;
|
||||
// The encode_breakout input
|
||||
const unsigned int min_thresh =
|
||||
MIN(((unsigned int)x->encode_breakout << 4), max_thresh);
|
||||
|
||||
// Calculate threshold according to dequant value.
|
||||
thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
|
||||
thresh_ac = clamp(thresh_ac, min_thresh, max_thresh);
|
||||
|
||||
// Adjust ac threshold according to partition size.
|
||||
thresh_ac >>=
|
||||
8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
|
||||
|
||||
thresh_dc = (xd->plane[0].dequant[0] * xd->plane[0].dequant[0] >> 6);
|
||||
} else {
|
||||
thresh_ac = 0;
|
||||
thresh_dc = 0;
|
||||
}
|
||||
|
||||
// Y skipping condition checking for ac and dc.
|
||||
if (var <= thresh_ac && (sse - var) <= thresh_dc) {
|
||||
unsigned int sse_u, sse_v;
|
||||
unsigned int var_u, var_v;
|
||||
|
||||
// Skip u v prediction for less calculation, that won't affect
|
||||
// result much.
|
||||
var_u = cpi->fn_ptr[uv_size].vf(x->plane[1].src.buf,
|
||||
x->plane[1].src.stride,
|
||||
xd->plane[1].dst.buf,
|
||||
xd->plane[1].dst.stride, &sse_u);
|
||||
|
||||
// U skipping condition checking
|
||||
if ((var_u * 4 <= thresh_ac) && (sse_u - var_u <= thresh_dc)) {
|
||||
var_v = cpi->fn_ptr[uv_size].vf(x->plane[2].src.buf,
|
||||
x->plane[2].src.stride,
|
||||
xd->plane[2].dst.buf,
|
||||
xd->plane[2].dst.stride, &sse_v);
|
||||
|
||||
// V skipping condition checking
|
||||
if ((var_v * 4 <= thresh_ac) && (sse_v - var_v <= thresh_dc)) {
|
||||
x->skip = 1;
|
||||
|
||||
// The cost of skip bit needs to be added.
|
||||
rate = rate_mv;
|
||||
rate += cpi->inter_mode_cost[mbmi->mode_context[ref_frame]]
|
||||
[INTER_OFFSET(this_mode)];
|
||||
|
||||
// More on this part of rate
|
||||
// rate += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
|
||||
|
||||
// Scaling factor for SSE from spatial domain to frequency
|
||||
// domain is 16. Adjust distortion accordingly.
|
||||
// TODO(yunqingwang): In this function, only y-plane dist is
|
||||
// calculated.
|
||||
dist = (sse << 4); // + ((sse_u + sse_v) << 4);
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate, dist);
|
||||
// *disable_skip = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_DENOISING
|
||||
vp9_denoiser_update_frame_stats(&cpi->denoiser, mbmi, sse_y, this_mode);
|
||||
vp9_denoiser_update_frame_stats();
|
||||
#endif
|
||||
|
||||
if (this_rd < best_rd || x->skip) {
|
||||
@@ -667,7 +624,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
*returndistortion = dist;
|
||||
best_mode = this_mode;
|
||||
best_pred_filter = mbmi->interp_filter;
|
||||
best_tx_size = mbmi->tx_size;
|
||||
best_ref_frame = ref_frame;
|
||||
skip_txfm = x->skip_txfm;
|
||||
|
||||
@@ -701,11 +657,10 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
bw, bh);
|
||||
}
|
||||
|
||||
mbmi->mode = best_mode;
|
||||
mbmi->mode = best_mode;
|
||||
mbmi->interp_filter = best_pred_filter;
|
||||
mbmi->tx_size = best_tx_size;
|
||||
mbmi->ref_frame[0] = best_ref_frame;
|
||||
mbmi->mv[0].as_int = frame_mv[best_mode][best_ref_frame].as_int;
|
||||
mbmi->ref_frame[0] = best_ref_frame;
|
||||
mbmi->mv[0].as_int = frame_mv[best_mode][best_ref_frame].as_int;
|
||||
xd->mi[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
|
||||
x->skip_txfm = skip_txfm;
|
||||
|
||||
@@ -714,6 +669,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
if (!x->skip && best_rd > inter_mode_thresh &&
|
||||
bsize <= cpi->sf.max_intra_bsize) {
|
||||
int i, j;
|
||||
const int step = 1 << mbmi->tx_size;
|
||||
const int width = num_4x4_blocks_wide_lookup[bsize];
|
||||
const int height = num_4x4_blocks_high_lookup[bsize];
|
||||
|
||||
@@ -723,10 +679,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
const int src_stride = p->src.stride;
|
||||
int block_idx = 0;
|
||||
|
||||
TX_SIZE tmp_tx_size = MIN(max_txsize_lookup[bsize],
|
||||
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
|
||||
const int step = 1 << tmp_tx_size;
|
||||
|
||||
for (this_mode = DC_PRED; this_mode <= DC_PRED; ++this_mode) {
|
||||
if (cpi->sf.reuse_inter_pred_sby) {
|
||||
pd->dst.buf = tmp[0].data;
|
||||
@@ -736,7 +688,10 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
for (j = 0; j < height; j += step) {
|
||||
for (i = 0; i < width; i += step) {
|
||||
vp9_predict_intra_block(xd, block_idx, b_width_log2(bsize),
|
||||
tmp_tx_size, this_mode,
|
||||
mbmi->tx_size, this_mode,
|
||||
#if CONFIG_FILTERINTRA
|
||||
0,
|
||||
#endif
|
||||
&p->src.buf[4 * (j * dst_stride + i)],
|
||||
src_stride,
|
||||
&pd->dst.buf[4 * (j * dst_stride + i)],
|
||||
@@ -747,7 +702,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
++block_idx;
|
||||
}
|
||||
}
|
||||
|
||||
rate = rate2;
|
||||
dist = dist2;
|
||||
|
||||
@@ -763,7 +717,6 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
*returnrate = rate;
|
||||
*returndistortion = dist;
|
||||
mbmi->mode = this_mode;
|
||||
mbmi->tx_size = tmp_tx_size;
|
||||
mbmi->ref_frame[0] = INTRA_FRAME;
|
||||
mbmi->uv_mode = this_mode;
|
||||
mbmi->mv[0].as_int = INVALID_MV;
|
||||
|
@@ -42,9 +42,9 @@ void vp9_quantize_dc(const int16_t *coeff_ptr, int skip_block,
|
||||
}
|
||||
|
||||
void vp9_quantize_dc_32x32(const int16_t *coeff_ptr, int skip_block,
|
||||
const int16_t *round_ptr, const int16_t quant,
|
||||
int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr,
|
||||
const int16_t dequant_ptr, uint16_t *eob_ptr) {
|
||||
const int16_t *round_ptr, const int16_t quant,
|
||||
int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr,
|
||||
const int16_t dequant_ptr, uint16_t *eob_ptr) {
|
||||
int eob = -1;
|
||||
|
||||
if (!skip_block) {
|
||||
@@ -63,47 +63,6 @@ void vp9_quantize_dc_32x32(const int16_t *coeff_ptr, int skip_block,
|
||||
*eob_ptr = eob + 1;
|
||||
}
|
||||
|
||||
void vp9_quantize_fp_c(const int16_t *coeff_ptr, intptr_t count,
|
||||
int skip_block,
|
||||
const int16_t *zbin_ptr, const int16_t *round_ptr,
|
||||
const int16_t *quant_ptr, const int16_t *quant_shift_ptr,
|
||||
int16_t *qcoeff_ptr, int16_t *dqcoeff_ptr,
|
||||
const int16_t *dequant_ptr,
|
||||
int zbin_oq_value, uint16_t *eob_ptr,
|
||||
const int16_t *scan, const int16_t *iscan) {
|
||||
int i, eob = -1;
|
||||
// TODO(jingning) Decide the need of these arguments after the
|
||||
// quantization process is completed.
|
||||
(void)zbin_ptr;
|
||||
(void)quant_shift_ptr;
|
||||
(void)zbin_oq_value;
|
||||
(void)iscan;
|
||||
|
||||
vpx_memset(qcoeff_ptr, 0, count * sizeof(int16_t));
|
||||
vpx_memset(dqcoeff_ptr, 0, count * sizeof(int16_t));
|
||||
|
||||
if (!skip_block) {
|
||||
// Quantization pass: All coefficients with index >= zero_flag are
|
||||
// skippable. Note: zero_flag can be zero.
|
||||
for (i = 0; i < count; i++) {
|
||||
const int rc = scan[i];
|
||||
const int coeff = coeff_ptr[rc];
|
||||
const int coeff_sign = (coeff >> 31);
|
||||
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
|
||||
|
||||
int tmp = clamp(abs_coeff + round_ptr[rc != 0], INT16_MIN, INT16_MAX);
|
||||
tmp = (tmp * quant_ptr[rc != 0]) >> 16;
|
||||
|
||||
qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
|
||||
dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
|
||||
|
||||
if (tmp)
|
||||
eob = i;
|
||||
}
|
||||
}
|
||||
*eob_ptr = eob + 1;
|
||||
}
|
||||
|
||||
void vp9_quantize_b_c(const int16_t *coeff_ptr, intptr_t count,
|
||||
int skip_block,
|
||||
const int16_t *zbin_ptr, const int16_t *round_ptr,
|
||||
@@ -248,16 +207,11 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
|
||||
const int qrounding_factor = q == 0 ? 64 : 48;
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
int qrounding_factor_fp = i == 0 ? 48 : 42;
|
||||
if (q == 0)
|
||||
qrounding_factor_fp = 64;
|
||||
|
||||
// y
|
||||
quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q)
|
||||
: vp9_ac_quant(q, 0);
|
||||
invert_quant(&quants->y_quant[q][i], &quants->y_quant_shift[q][i], quant);
|
||||
quants->y_quant_fp[q][i] = (1 << 16) / quant;
|
||||
quants->y_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
|
||||
quants->y_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
|
||||
quants->y_round[q][i] = (qrounding_factor * quant) >> 7;
|
||||
cm->y_dequant[q][i] = quant;
|
||||
@@ -268,7 +222,6 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
|
||||
invert_quant(&quants->uv_quant[q][i],
|
||||
&quants->uv_quant_shift[q][i], quant);
|
||||
quants->uv_quant_fp[q][i] = (1 << 16) / quant;
|
||||
quants->uv_round_fp[q][i] = (qrounding_factor_fp * quant) >> 7;
|
||||
quants->uv_zbin[q][i] = ROUND_POWER_OF_TWO(qzbin_factor * quant, 7);
|
||||
quants->uv_round[q][i] = (qrounding_factor * quant) >> 7;
|
||||
cm->uv_dequant[q][i] = quant;
|
||||
@@ -287,7 +240,6 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
|
||||
for (i = 2; i < 8; i++) {
|
||||
quants->y_quant[q][i] = quants->y_quant[q][1];
|
||||
quants->y_quant_fp[q][i] = quants->y_quant_fp[q][1];
|
||||
quants->y_round_fp[q][i] = quants->y_round_fp[q][1];
|
||||
quants->y_quant_shift[q][i] = quants->y_quant_shift[q][1];
|
||||
quants->y_zbin[q][i] = quants->y_zbin[q][1];
|
||||
quants->y_round[q][i] = quants->y_round[q][1];
|
||||
@@ -295,7 +247,6 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
|
||||
|
||||
quants->uv_quant[q][i] = quants->uv_quant[q][1];
|
||||
quants->uv_quant_fp[q][i] = quants->uv_quant_fp[q][1];
|
||||
quants->uv_round_fp[q][i] = quants->uv_round_fp[q][1];
|
||||
quants->uv_quant_shift[q][i] = quants->uv_quant_shift[q][1];
|
||||
quants->uv_zbin[q][i] = quants->uv_zbin[q][1];
|
||||
quants->uv_round[q][i] = quants->uv_round[q][1];
|
||||
@@ -325,7 +276,6 @@ void vp9_init_plane_quantizers(VP9_COMP *cpi, MACROBLOCK *x) {
|
||||
// Y
|
||||
x->plane[0].quant = quants->y_quant[qindex];
|
||||
x->plane[0].quant_fp = quants->y_quant_fp[qindex];
|
||||
x->plane[0].round_fp = quants->y_round_fp[qindex];
|
||||
x->plane[0].quant_shift = quants->y_quant_shift[qindex];
|
||||
x->plane[0].zbin = quants->y_zbin[qindex];
|
||||
x->plane[0].round = quants->y_round[qindex];
|
||||
@@ -336,7 +286,6 @@ void vp9_init_plane_quantizers(VP9_COMP *cpi, MACROBLOCK *x) {
|
||||
for (i = 1; i < 3; i++) {
|
||||
x->plane[i].quant = quants->uv_quant[qindex];
|
||||
x->plane[i].quant_fp = quants->uv_quant_fp[qindex];
|
||||
x->plane[i].round_fp = quants->uv_round_fp[qindex];
|
||||
x->plane[i].quant_shift = quants->uv_quant_shift[qindex];
|
||||
x->plane[i].zbin = quants->uv_zbin[qindex];
|
||||
x->plane[i].round = quants->uv_round[qindex];
|
||||
|
@@ -28,8 +28,6 @@ typedef struct {
|
||||
// if we want to deprecate the current use of y_quant.
|
||||
DECLARE_ALIGNED(16, int16_t, y_quant_fp[QINDEX_RANGE][8]);
|
||||
DECLARE_ALIGNED(16, int16_t, uv_quant_fp[QINDEX_RANGE][8]);
|
||||
DECLARE_ALIGNED(16, int16_t, y_round_fp[QINDEX_RANGE][8]);
|
||||
DECLARE_ALIGNED(16, int16_t, uv_round_fp[QINDEX_RANGE][8]);
|
||||
|
||||
DECLARE_ALIGNED(16, int16_t, uv_quant[QINDEX_RANGE][8]);
|
||||
DECLARE_ALIGNED(16, int16_t, uv_quant_shift[QINDEX_RANGE][8]);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -33,7 +33,11 @@ extern "C" {
|
||||
|
||||
#define INVALID_MV 0x80008000
|
||||
|
||||
#if !CONFIG_INTERINTRA
|
||||
#define MAX_MODES 30
|
||||
#else
|
||||
#define MAX_MODES 42
|
||||
#endif
|
||||
#define MAX_REFS 6
|
||||
|
||||
// This enumerator type needs to be kept aligned with the mode order in
|
||||
@@ -76,6 +80,23 @@ typedef enum {
|
||||
THR_D63_PRED,
|
||||
THR_D117_PRED,
|
||||
THR_D45_PRED,
|
||||
|
||||
#if CONFIG_INTERINTRA
|
||||
THR_COMP_INTERINTRA_ZEROL,
|
||||
THR_COMP_INTERINTRA_NEARESTL,
|
||||
THR_COMP_INTERINTRA_NEARL,
|
||||
THR_COMP_INTERINTRA_NEWL,
|
||||
|
||||
THR_COMP_INTERINTRA_ZEROG,
|
||||
THR_COMP_INTERINTRA_NEARESTG,
|
||||
THR_COMP_INTERINTRA_NEARG,
|
||||
THR_COMP_INTERINTRA_NEWG,
|
||||
|
||||
THR_COMP_INTERINTRA_ZEROA,
|
||||
THR_COMP_INTERINTRA_NEARESTA,
|
||||
THR_COMP_INTERINTRA_NEARA,
|
||||
THR_COMP_INTERINTRA_NEWA,
|
||||
#endif
|
||||
} THR_MODES;
|
||||
|
||||
typedef enum {
|
||||
@@ -150,6 +171,9 @@ int64_t vp9_rd_pick_inter_mode_sb(struct VP9_COMP *cpi, struct macroblock *x,
|
||||
const struct TileInfo *const tile,
|
||||
int mi_row, int mi_col,
|
||||
int *returnrate,
|
||||
#if CONFIG_SUPERTX
|
||||
int *returnrate_nocoef,
|
||||
#endif
|
||||
int64_t *returndistortion,
|
||||
BLOCK_SIZE bsize,
|
||||
PICK_MODE_CONTEXT *ctx,
|
||||
@@ -157,6 +181,8 @@ int64_t vp9_rd_pick_inter_mode_sb(struct VP9_COMP *cpi, struct macroblock *x,
|
||||
|
||||
int64_t vp9_rd_pick_inter_mode_sb_seg_skip(struct VP9_COMP *cpi,
|
||||
struct macroblock *x,
|
||||
const TileInfo *const tile,
|
||||
int mi_row, int mi_col,
|
||||
int *returnrate,
|
||||
int64_t *returndistortion,
|
||||
BLOCK_SIZE bsize,
|
||||
@@ -168,6 +194,9 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(struct VP9_COMP *cpi,
|
||||
const struct TileInfo *const tile,
|
||||
int mi_row, int mi_col,
|
||||
int *returnrate,
|
||||
#if CONFIG_SUPERTX
|
||||
int *returnrate_nocoef,
|
||||
#endif
|
||||
int64_t *returndistortion,
|
||||
BLOCK_SIZE bsize,
|
||||
PICK_MODE_CONTEXT *ctx,
|
||||
@@ -199,6 +228,21 @@ void vp9_setup_pred_block(const MACROBLOCKD *xd,
|
||||
int mi_row, int mi_col,
|
||||
const struct scale_factors *scale,
|
||||
const struct scale_factors *scale_uv);
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
void txfm_rd_in_plane_supertx(MACROBLOCK *x,
|
||||
int *rate, int64_t *distortion,
|
||||
int *skippable, int64_t *sse,
|
||||
int64_t ref_best_rd, int plane,
|
||||
BLOCK_SIZE bsize, TX_SIZE tx_size,
|
||||
int use_fast_coef_casting);
|
||||
void txfm_rd_in_plane(MACROBLOCK *x,
|
||||
int *rate, int64_t *distortion,
|
||||
int *skippable, int64_t *sse,
|
||||
int64_t ref_best_rd, int plane,
|
||||
BLOCK_SIZE bsize, TX_SIZE tx_size,
|
||||
int use_fast_coef_casting);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -131,3 +131,47 @@ sadMxN(4, 4)
|
||||
sadMxNxK(4, 4, 3)
|
||||
sadMxNxK(4, 4, 8)
|
||||
sadMxNx4D(4, 4)
|
||||
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
static INLINE unsigned int masked_sad(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
const uint8_t *m, int m_stride,
|
||||
int width, int height) {
|
||||
int y, x;
|
||||
unsigned int sad = 0;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++)
|
||||
sad += m[x] * abs(a[x] - b[x]);
|
||||
|
||||
a += a_stride;
|
||||
b += b_stride;
|
||||
m += m_stride;
|
||||
}
|
||||
sad = (sad + 31) >> 6;
|
||||
|
||||
return sad;
|
||||
}
|
||||
|
||||
#define MASKSADMxN(m, n) \
|
||||
unsigned int vp9_masked_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
|
||||
const uint8_t *ref, int ref_stride, \
|
||||
const uint8_t *msk, int msk_stride) { \
|
||||
return masked_sad(src, src_stride, ref, ref_stride, msk, msk_stride, m, n); \
|
||||
}
|
||||
|
||||
MASKSADMxN(64, 64)
|
||||
MASKSADMxN(64, 32)
|
||||
MASKSADMxN(32, 64)
|
||||
MASKSADMxN(32, 32)
|
||||
MASKSADMxN(32, 16)
|
||||
MASKSADMxN(16, 32)
|
||||
MASKSADMxN(16, 16)
|
||||
MASKSADMxN(16, 8)
|
||||
MASKSADMxN(8, 16)
|
||||
MASKSADMxN(8, 8)
|
||||
MASKSADMxN(8, 4)
|
||||
MASKSADMxN(4, 8)
|
||||
MASKSADMxN(4, 4)
|
||||
#endif
|
||||
|
@@ -27,8 +27,6 @@ void vp9_enable_segmentation(struct segmentation *seg) {
|
||||
|
||||
void vp9_disable_segmentation(struct segmentation *seg) {
|
||||
seg->enabled = 0;
|
||||
seg->update_map = 0;
|
||||
seg->update_data = 0;
|
||||
}
|
||||
|
||||
void vp9_set_segment_data(struct segmentation *seg,
|
||||
|
@@ -270,25 +270,16 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
|
||||
// Adaptively switch between SOURCE_VAR_BASED_PARTITION and FIXED_PARTITION.
|
||||
sf->partition_search_type = SOURCE_VAR_BASED_PARTITION;
|
||||
sf->search_type_check_frequency = 50;
|
||||
sf->source_var_thresh = 360;
|
||||
|
||||
sf->tx_size_search_method = (cm->frame_type == KEY_FRAME) ?
|
||||
USE_LARGESTALL : USE_TX_8X8;
|
||||
sf->tx_size_search_method = USE_TX_8X8;
|
||||
sf->max_intra_bsize = BLOCK_8X8;
|
||||
|
||||
// This feature is only enabled when partition search is disabled.
|
||||
sf->reuse_inter_pred_sby = 1;
|
||||
}
|
||||
|
||||
// Increase mode checking threshold for NEWMV.
|
||||
sf->elevate_newmv_thresh = 2000;
|
||||
}
|
||||
if (speed >= 7) {
|
||||
sf->use_quant_fp = cm->frame_type == KEY_FRAME ? 0 : 1;
|
||||
sf->lpf_pick = LPF_PICK_MINIMAL_LPF;
|
||||
sf->encode_breakout_thresh = (MIN(cm->width, cm->height) >= 720) ?
|
||||
800 : 300;
|
||||
sf->elevate_newmv_thresh = 2500;
|
||||
}
|
||||
if (speed >= 8) {
|
||||
int i;
|
||||
for (i = 0; i < BLOCK_SIZES; ++i)
|
||||
sf->inter_mode_mask[i] = INTER_NEAREST;
|
||||
@@ -319,7 +310,6 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
||||
sf->use_lp32x32fdct = 0;
|
||||
sf->adaptive_motion_search = 0;
|
||||
sf->adaptive_pred_interp_filter = 0;
|
||||
sf->use_quant_fp = 0;
|
||||
sf->reference_masking = 0;
|
||||
sf->partition_search_type = SEARCH_PARTITION;
|
||||
sf->less_rectangular_check = 0;
|
||||
@@ -357,8 +347,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
||||
// to FIXED_PARTITION.
|
||||
sf->always_this_block_size = BLOCK_16X16;
|
||||
sf->search_type_check_frequency = 50;
|
||||
sf->encode_breakout_thresh = 0;
|
||||
sf->elevate_newmv_thresh = 0;
|
||||
sf->source_var_thresh = 100;
|
||||
|
||||
// Recode loop tolerence %.
|
||||
sf->recode_tolerance = 25;
|
||||
@@ -402,8 +391,4 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
|
||||
if (!cpi->oxcf.frame_periodic_boost) {
|
||||
sf->max_delta_qindex = 0;
|
||||
}
|
||||
|
||||
if (cpi->encode_breakout && oxcf->mode == REALTIME &&
|
||||
sf->encode_breakout_thresh > cpi->encode_breakout)
|
||||
cpi->encode_breakout = sf->encode_breakout_thresh;
|
||||
}
|
||||
|
@@ -73,8 +73,6 @@ typedef enum {
|
||||
LPF_PICK_FROM_SUBIMAGE,
|
||||
// Estimate the level based on quantizer and frame type
|
||||
LPF_PICK_FROM_Q,
|
||||
// Pick 0 to disable LPF if LPF was enabled last frame
|
||||
LPF_PICK_MINIMAL_LPF
|
||||
} LPF_PICK_METHOD;
|
||||
|
||||
typedef enum {
|
||||
@@ -284,9 +282,6 @@ typedef struct SPEED_FEATURES {
|
||||
// was selected, and 2 means we use 8 tap if no 8x8 filter mode was selected.
|
||||
int adaptive_pred_interp_filter;
|
||||
|
||||
// Fast quantization process path
|
||||
int use_quant_fp;
|
||||
|
||||
// Search through variable block partition types in non-RD mode decision
|
||||
// encoding process for RTC.
|
||||
int partition_check;
|
||||
@@ -356,17 +351,13 @@ typedef struct SPEED_FEATURES {
|
||||
// FIXED_PARTITION search type should be used.
|
||||
int search_type_check_frequency;
|
||||
|
||||
// The threshold used in SOURCE_VAR_BASED_PARTITION search type.
|
||||
unsigned int source_var_thresh;
|
||||
|
||||
// When partition is pre-set, the inter prediction result from pick_inter_mode
|
||||
// can be reused in final block encoding process. It is enabled only for real-
|
||||
// time mode speed 6.
|
||||
int reuse_inter_pred_sby;
|
||||
|
||||
// This variable sets the encode_breakout threshold. Currently, it is only
|
||||
// enabled in real time mode.
|
||||
int encode_breakout_thresh;
|
||||
|
||||
// In real time encoding, increase the threshold for NEWMV.
|
||||
int elevate_newmv_thresh;
|
||||
} SPEED_FEATURES;
|
||||
|
||||
struct VP9_COMP;
|
||||
|
@@ -334,3 +334,41 @@ void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
|
||||
*t = t_backup;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
void vp9_tokenize_sb_supertx(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
|
||||
BLOCK_SIZE bsize) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
||||
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
|
||||
TOKENEXTRA *t_backup = *t;
|
||||
const int ctx = vp9_get_skip_context(xd);
|
||||
const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
|
||||
SEG_LVL_SKIP);
|
||||
struct tokenize_b_args arg = {cpi, xd, t};
|
||||
int plane;
|
||||
if (mbmi->skip) {
|
||||
if (!dry_run)
|
||||
cm->counts.skip[ctx][1] += skip_inc;
|
||||
reset_skip_context(xd, bsize);
|
||||
if (dry_run)
|
||||
*t = t_backup;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dry_run) {
|
||||
cm->counts.skip[ctx][0] += skip_inc;
|
||||
for (plane = 0; plane < MAX_MB_PLANE; plane++) {
|
||||
BLOCK_SIZE plane_size = plane ? (bsize - 3) : bsize;
|
||||
tokenize_b(plane, 0, plane_size, b_width_log2(plane_size), &arg);
|
||||
}
|
||||
} else {
|
||||
for (plane = 0; plane < MAX_MB_PLANE; plane++) {
|
||||
BLOCK_SIZE plane_size = plane ? (bsize - 3) : bsize;
|
||||
set_entropy_context_b(plane, 0, plane_size, b_width_log2(plane_size),
|
||||
&arg);
|
||||
}
|
||||
*t = t_backup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -46,6 +46,10 @@ struct VP9_COMP;
|
||||
|
||||
void vp9_tokenize_sb(struct VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
|
||||
BLOCK_SIZE bsize);
|
||||
#if CONFIG_SUPERTX
|
||||
void vp9_tokenize_sb_supertx(struct VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
|
||||
BLOCK_SIZE bsize);
|
||||
#endif
|
||||
|
||||
extern const int16_t *vp9_dct_value_cost_ptr;
|
||||
/* TODO: The Token field should be broken out into a separate char array to
|
||||
|
@@ -266,3 +266,98 @@ void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
|
||||
ref += ref_stride;
|
||||
}
|
||||
}
|
||||
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
void masked_variance(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
const uint8_t *m, int m_stride,
|
||||
int w, int h, unsigned int *sse, int *sum) {
|
||||
int i, j;
|
||||
|
||||
*sum = 0;
|
||||
*sse = 0;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
for (j = 0; j < w; j++) {
|
||||
const int diff = (a[j] - b[j]) * (m[j]);
|
||||
*sum += diff;
|
||||
*sse += diff * diff;
|
||||
}
|
||||
|
||||
a += a_stride;
|
||||
b += b_stride;
|
||||
m += m_stride;
|
||||
}
|
||||
*sum = (*sum >= 0) ? ((*sum + 31) >> 6) : -((-*sum + 31) >> 6);
|
||||
*sse = (*sse + 2047) >> 12;
|
||||
}
|
||||
|
||||
#define MASK_VAR(W, H) \
|
||||
unsigned int vp9_masked_variance##W##x##H##_c(const uint8_t *a, int a_stride, \
|
||||
const uint8_t *b, int b_stride, \
|
||||
const uint8_t *m, int m_stride, \
|
||||
unsigned int *sse) { \
|
||||
int sum; \
|
||||
masked_variance(a, a_stride, b, b_stride, m, m_stride, W, H, sse, &sum); \
|
||||
return *sse - (((int64_t)sum * sum) / (W * H)); \
|
||||
}
|
||||
|
||||
#define MASK_SUBPIX_VAR(W, H) \
|
||||
unsigned int vp9_masked_sub_pixel_variance##W##x##H##_c( \
|
||||
const uint8_t *src, int src_stride, \
|
||||
int xoffset, int yoffset, \
|
||||
const uint8_t *dst, int dst_stride, \
|
||||
const uint8_t *msk, int msk_stride, \
|
||||
unsigned int *sse) { \
|
||||
uint16_t fdata3[(H + 1) * W]; \
|
||||
uint8_t temp2[H * W]; \
|
||||
\
|
||||
var_filter_block2d_bil_first_pass(src, fdata3, src_stride, 1, H + 1, W, \
|
||||
BILINEAR_FILTERS_2TAP(xoffset)); \
|
||||
var_filter_block2d_bil_second_pass(fdata3, temp2, W, W, H, W, \
|
||||
BILINEAR_FILTERS_2TAP(yoffset)); \
|
||||
\
|
||||
return vp9_masked_variance##W##x##H##_c(temp2, W, dst, dst_stride, \
|
||||
msk, msk_stride, sse); \
|
||||
}
|
||||
|
||||
MASK_VAR(4, 4)
|
||||
MASK_SUBPIX_VAR(4, 4)
|
||||
|
||||
MASK_VAR(4, 8)
|
||||
MASK_SUBPIX_VAR(4, 8)
|
||||
|
||||
MASK_VAR(8, 4)
|
||||
MASK_SUBPIX_VAR(8, 4)
|
||||
|
||||
MASK_VAR(8, 8)
|
||||
MASK_SUBPIX_VAR(8, 8)
|
||||
|
||||
MASK_VAR(8, 16)
|
||||
MASK_SUBPIX_VAR(8, 16)
|
||||
|
||||
MASK_VAR(16, 8)
|
||||
MASK_SUBPIX_VAR(16, 8)
|
||||
|
||||
MASK_VAR(16, 16)
|
||||
MASK_SUBPIX_VAR(16, 16)
|
||||
|
||||
MASK_VAR(16, 32)
|
||||
MASK_SUBPIX_VAR(16, 32)
|
||||
|
||||
MASK_VAR(32, 16)
|
||||
MASK_SUBPIX_VAR(32, 16)
|
||||
|
||||
MASK_VAR(32, 32)
|
||||
MASK_SUBPIX_VAR(32, 32)
|
||||
|
||||
MASK_VAR(32, 64)
|
||||
MASK_SUBPIX_VAR(32, 64)
|
||||
|
||||
MASK_VAR(64, 32)
|
||||
MASK_SUBPIX_VAR(64, 32)
|
||||
|
||||
MASK_VAR(64, 64)
|
||||
MASK_SUBPIX_VAR(64, 64)
|
||||
#endif
|
||||
|
@@ -67,6 +67,32 @@ typedef unsigned int (*vp9_subp_avg_variance_fn_t)(const uint8_t *src_ptr,
|
||||
unsigned int *sse,
|
||||
const uint8_t *second_pred);
|
||||
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
typedef unsigned int(*vp9_masked_sad_fn_t)(const uint8_t *src_ptr,
|
||||
int source_stride,
|
||||
const uint8_t *ref_ptr,
|
||||
int ref_stride,
|
||||
const uint8_t *msk_ptr,
|
||||
int msk_stride);
|
||||
typedef unsigned int (*vp9_masked_variance_fn_t)(const uint8_t *src_ptr,
|
||||
int source_stride,
|
||||
const uint8_t *ref_ptr,
|
||||
int ref_stride,
|
||||
const uint8_t *msk_ptr,
|
||||
int msk_stride,
|
||||
unsigned int *sse);
|
||||
typedef unsigned int (*vp9_masked_subpixvariance_fn_t)(const uint8_t *src_ptr,
|
||||
int source_stride,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
const uint8_t *ref_ptr,
|
||||
int Refstride,
|
||||
const uint8_t *msk_ptr,
|
||||
int msk_stride,
|
||||
unsigned int *sse);
|
||||
#endif
|
||||
|
||||
typedef struct vp9_variance_vtable {
|
||||
vp9_sad_fn_t sdf;
|
||||
vp9_sad_avg_fn_t sdaf;
|
||||
@@ -76,6 +102,12 @@ typedef struct vp9_variance_vtable {
|
||||
vp9_sad_multi_fn_t sdx3f;
|
||||
vp9_sad_multi_fn_t sdx8f;
|
||||
vp9_sad_multi_d_fn_t sdx4df;
|
||||
#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
|
||||
CONFIG_MASKED_INTERINTER)
|
||||
vp9_masked_sad_fn_t msdf;
|
||||
vp9_masked_variance_fn_t mvf;
|
||||
vp9_masked_subpixvariance_fn_t msvf;
|
||||
#endif
|
||||
} vp9_variance_fn_ptr_t;
|
||||
|
||||
void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
|
||||
|
@@ -217,185 +217,3 @@ cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, skip, zbin, round, quant, \
|
||||
INIT_XMM ssse3
|
||||
QUANTIZE_FN b, 7
|
||||
QUANTIZE_FN b_32x32, 7
|
||||
|
||||
%macro QUANTIZE_FP 2
|
||||
cglobal quantize_%1, 0, %2, 15, coeff, ncoeff, skip, zbin, round, quant, \
|
||||
shift, qcoeff, dqcoeff, dequant, zbin_oq, \
|
||||
eob, scan, iscan
|
||||
cmp dword skipm, 0
|
||||
jne .blank
|
||||
|
||||
; actual quantize loop - setup pointers, rounders, etc.
|
||||
movifnidn coeffq, coeffmp
|
||||
movifnidn ncoeffq, ncoeffmp
|
||||
mov r2, dequantmp
|
||||
movifnidn zbinq, zbinmp
|
||||
movifnidn roundq, roundmp
|
||||
movifnidn quantq, quantmp
|
||||
mova m1, [roundq] ; m1 = round
|
||||
mova m2, [quantq] ; m2 = quant
|
||||
%ifidn %1, b_32x32
|
||||
; TODO(jingning) to be continued with 32x32 quantization process
|
||||
pcmpeqw m5, m5
|
||||
psrlw m5, 15
|
||||
paddw m0, m5
|
||||
paddw m1, m5
|
||||
psrlw m0, 1 ; m0 = (m0 + 1) / 2
|
||||
psrlw m1, 1 ; m1 = (m1 + 1) / 2
|
||||
%endif
|
||||
mova m3, [r2q] ; m3 = dequant
|
||||
mov r3, qcoeffmp
|
||||
mov r4, dqcoeffmp
|
||||
mov r5, iscanmp
|
||||
%ifidn %1, b_32x32
|
||||
psllw m4, 1
|
||||
%endif
|
||||
pxor m5, m5 ; m5 = dedicated zero
|
||||
DEFINE_ARGS coeff, ncoeff, d1, qcoeff, dqcoeff, iscan, d2, d3, d4, d5, d6, eob
|
||||
lea coeffq, [ coeffq+ncoeffq*2]
|
||||
lea iscanq, [ iscanq+ncoeffq*2]
|
||||
lea qcoeffq, [ qcoeffq+ncoeffq*2]
|
||||
lea dqcoeffq, [dqcoeffq+ncoeffq*2]
|
||||
neg ncoeffq
|
||||
|
||||
; get DC and first 15 AC coeffs
|
||||
mova m9, [ coeffq+ncoeffq*2+ 0] ; m9 = c[i]
|
||||
mova m10, [ coeffq+ncoeffq*2+16] ; m10 = c[i]
|
||||
pabsw m6, m9 ; m6 = abs(m9)
|
||||
pabsw m11, m10 ; m11 = abs(m10)
|
||||
pcmpeqw m7, m7
|
||||
pcmpeqw m12, m12
|
||||
|
||||
paddsw m6, m1 ; m6 += round
|
||||
punpckhqdq m1, m1
|
||||
paddsw m11, m1 ; m11 += round
|
||||
pmulhw m8, m6, m2 ; m8 = m6*q>>16
|
||||
punpckhqdq m2, m2
|
||||
pmulhw m13, m11, m2 ; m13 = m11*q>>16
|
||||
psignw m8, m9 ; m8 = reinsert sign
|
||||
psignw m13, m10 ; m13 = reinsert sign
|
||||
mova [qcoeffq+ncoeffq*2+ 0], m8
|
||||
mova [qcoeffq+ncoeffq*2+16], m13
|
||||
%ifidn %1, b_32x32
|
||||
pabsw m8, m8
|
||||
pabsw m13, m13
|
||||
%endif
|
||||
pmullw m8, m3 ; dqc[i] = qc[i] * q
|
||||
punpckhqdq m3, m3
|
||||
pmullw m13, m3 ; dqc[i] = qc[i] * q
|
||||
%ifidn %1, b_32x32
|
||||
psrlw m8, 1
|
||||
psrlw m13, 1
|
||||
psignw m8, m9
|
||||
psignw m13, m10
|
||||
%endif
|
||||
mova [dqcoeffq+ncoeffq*2+ 0], m8
|
||||
mova [dqcoeffq+ncoeffq*2+16], m13
|
||||
pcmpeqw m8, m5 ; m8 = c[i] == 0
|
||||
pcmpeqw m13, m5 ; m13 = c[i] == 0
|
||||
mova m6, [ iscanq+ncoeffq*2+ 0] ; m6 = scan[i]
|
||||
mova m11, [ iscanq+ncoeffq*2+16] ; m11 = scan[i]
|
||||
psubw m6, m7 ; m6 = scan[i] + 1
|
||||
psubw m11, m12 ; m11 = scan[i] + 1
|
||||
pandn m8, m6 ; m8 = max(eob)
|
||||
pandn m13, m11 ; m13 = max(eob)
|
||||
pmaxsw m8, m13
|
||||
add ncoeffq, mmsize
|
||||
jz .accumulate_eob
|
||||
|
||||
.ac_only_loop:
|
||||
mova m9, [ coeffq+ncoeffq*2+ 0] ; m9 = c[i]
|
||||
mova m10, [ coeffq+ncoeffq*2+16] ; m10 = c[i]
|
||||
pabsw m6, m9 ; m6 = abs(m9)
|
||||
pabsw m11, m10 ; m11 = abs(m10)
|
||||
pcmpeqw m7, m7
|
||||
pcmpeqw m12, m12
|
||||
%ifidn %1, b_32x32
|
||||
pmovmskb r6, m7
|
||||
pmovmskb r2, m12
|
||||
or r6, r2
|
||||
jz .skip_iter
|
||||
%endif
|
||||
paddsw m6, m1 ; m6 += round
|
||||
paddsw m11, m1 ; m11 += round
|
||||
pmulhw m14, m6, m2 ; m14 = m6*q>>16
|
||||
pmulhw m13, m11, m2 ; m13 = m11*q>>16
|
||||
psignw m14, m9 ; m14 = reinsert sign
|
||||
psignw m13, m10 ; m13 = reinsert sign
|
||||
mova [qcoeffq+ncoeffq*2+ 0], m14
|
||||
mova [qcoeffq+ncoeffq*2+16], m13
|
||||
%ifidn %1, b_32x32
|
||||
pabsw m14, m14
|
||||
pabsw m13, m13
|
||||
%endif
|
||||
pmullw m14, m3 ; dqc[i] = qc[i] * q
|
||||
pmullw m13, m3 ; dqc[i] = qc[i] * q
|
||||
%ifidn %1, b_32x32
|
||||
psrlw m14, 1
|
||||
psrlw m13, 1
|
||||
psignw m14, m9
|
||||
psignw m13, m10
|
||||
%endif
|
||||
mova [dqcoeffq+ncoeffq*2+ 0], m14
|
||||
mova [dqcoeffq+ncoeffq*2+16], m13
|
||||
pcmpeqw m14, m5 ; m14 = c[i] == 0
|
||||
pcmpeqw m13, m5 ; m13 = c[i] == 0
|
||||
mova m6, [ iscanq+ncoeffq*2+ 0] ; m6 = scan[i]
|
||||
mova m11, [ iscanq+ncoeffq*2+16] ; m11 = scan[i]
|
||||
psubw m6, m7 ; m6 = scan[i] + 1
|
||||
psubw m11, m12 ; m11 = scan[i] + 1
|
||||
pandn m14, m6 ; m14 = max(eob)
|
||||
pandn m13, m11 ; m13 = max(eob)
|
||||
pmaxsw m8, m14
|
||||
pmaxsw m8, m13
|
||||
add ncoeffq, mmsize
|
||||
jl .ac_only_loop
|
||||
|
||||
%ifidn %1, b_32x32
|
||||
jmp .accumulate_eob
|
||||
.skip_iter:
|
||||
mova [qcoeffq+ncoeffq*2+ 0], m5
|
||||
mova [qcoeffq+ncoeffq*2+16], m5
|
||||
mova [dqcoeffq+ncoeffq*2+ 0], m5
|
||||
mova [dqcoeffq+ncoeffq*2+16], m5
|
||||
add ncoeffq, mmsize
|
||||
jl .ac_only_loop
|
||||
%endif
|
||||
|
||||
.accumulate_eob:
|
||||
; horizontally accumulate/max eobs and write into [eob] memory pointer
|
||||
mov r2, eobmp
|
||||
pshufd m7, m8, 0xe
|
||||
pmaxsw m8, m7
|
||||
pshuflw m7, m8, 0xe
|
||||
pmaxsw m8, m7
|
||||
pshuflw m7, m8, 0x1
|
||||
pmaxsw m8, m7
|
||||
pextrw r6, m8, 0
|
||||
mov [r2], r6
|
||||
RET
|
||||
|
||||
; skip-block, i.e. just write all zeroes
|
||||
.blank:
|
||||
mov r0, dqcoeffmp
|
||||
movifnidn ncoeffq, ncoeffmp
|
||||
mov r2, qcoeffmp
|
||||
mov r3, eobmp
|
||||
DEFINE_ARGS dqcoeff, ncoeff, qcoeff, eob
|
||||
lea dqcoeffq, [dqcoeffq+ncoeffq*2]
|
||||
lea qcoeffq, [ qcoeffq+ncoeffq*2]
|
||||
neg ncoeffq
|
||||
pxor m7, m7
|
||||
.blank_loop:
|
||||
mova [dqcoeffq+ncoeffq*2+ 0], m7
|
||||
mova [dqcoeffq+ncoeffq*2+16], m7
|
||||
mova [qcoeffq+ncoeffq*2+ 0], m7
|
||||
mova [qcoeffq+ncoeffq*2+16], m7
|
||||
add ncoeffq, mmsize
|
||||
jl .blank_loop
|
||||
mov word [eobq], 0
|
||||
RET
|
||||
%endmacro
|
||||
|
||||
INIT_XMM ssse3
|
||||
QUANTIZE_FP fp, 7
|
||||
|
@@ -90,8 +90,6 @@ struct vpx_codec_alg_priv {
|
||||
vp8_postproc_cfg_t preview_ppcfg;
|
||||
vpx_codec_pkt_list_decl(128) pkt_list;
|
||||
unsigned int fixed_kf_cntr;
|
||||
// BufferPool that holds all reference frames.
|
||||
BufferPool *buffer_pool;
|
||||
};
|
||||
|
||||
static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
|
||||
@@ -632,10 +630,6 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
|
||||
ctx->priv->alg_priv = priv;
|
||||
ctx->priv->init_flags = ctx->init_flags;
|
||||
ctx->priv->enc.total_encoders = 1;
|
||||
ctx->priv->alg_priv->buffer_pool =
|
||||
(BufferPool *)vpx_calloc(1, sizeof(BufferPool));
|
||||
if (ctx->priv->alg_priv->buffer_pool == NULL)
|
||||
return VPX_CODEC_MEM_ERROR;
|
||||
|
||||
if (ctx->config.enc) {
|
||||
// Update the reference to the config structure to an internal copy.
|
||||
@@ -673,8 +667,7 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
|
||||
set_encoder_config(&ctx->priv->alg_priv->oxcf,
|
||||
&ctx->priv->alg_priv->cfg,
|
||||
&ctx->priv->alg_priv->extra_cfg);
|
||||
cpi = vp9_create_compressor(&ctx->priv->alg_priv->oxcf,
|
||||
ctx->priv->alg_priv->buffer_pool);
|
||||
cpi = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
|
||||
if (cpi == NULL)
|
||||
res = VPX_CODEC_MEM_ERROR;
|
||||
else
|
||||
@@ -688,7 +681,6 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
|
||||
static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
|
||||
free(ctx->cx_data);
|
||||
vp9_remove_compressor(ctx->cpi);
|
||||
vpx_free(ctx->buffer_pool);
|
||||
free(ctx);
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
|
@@ -46,9 +46,6 @@ struct vpx_codec_alg_priv {
|
||||
int next_submit_thread_id;
|
||||
int next_output_thread_id;
|
||||
|
||||
// BufferPool that holds all reference frames. Shared by all the FrameWorkers.
|
||||
BufferPool *buffer_pool;
|
||||
|
||||
// External frame buffer info to save for VP9 common.
|
||||
void *ext_priv; // Private data associated with the external frame buffers.
|
||||
vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
|
||||
@@ -103,7 +100,6 @@ static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
|
||||
}
|
||||
|
||||
vpx_free(ctx->frame_workers);
|
||||
vpx_free(ctx->buffer_pool);
|
||||
vpx_free(ctx);
|
||||
|
||||
return VPX_CODEC_OK;
|
||||
@@ -222,22 +218,21 @@ static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
|
||||
VP9Worker *const worker = &ctx->frame_workers[i];
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
VP9_COMMON *const cm = &worker_data->pbi->common;
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
|
||||
cm->new_fb_idx = -1;
|
||||
if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
|
||||
pool->get_fb_cb = ctx->get_ext_fb_cb;
|
||||
pool->release_fb_cb = ctx->release_ext_fb_cb;
|
||||
pool->cb_priv = ctx->ext_priv;
|
||||
cm->get_fb_cb = ctx->get_ext_fb_cb;
|
||||
cm->release_fb_cb = ctx->release_ext_fb_cb;
|
||||
cm->cb_priv = ctx->ext_priv;
|
||||
} else {
|
||||
pool->get_fb_cb = vp9_get_frame_buffer;
|
||||
pool->release_fb_cb = vp9_release_frame_buffer;
|
||||
cm->get_fb_cb = vp9_get_frame_buffer;
|
||||
cm->release_fb_cb = vp9_release_frame_buffer;
|
||||
|
||||
if (vp9_alloc_internal_frame_buffers(&pool->int_frame_buffers))
|
||||
if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to initialize internal frame buffers");
|
||||
|
||||
pool->cb_priv = &pool->int_frame_buffers;
|
||||
cm->cb_priv = &cm->int_frame_buffers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,16 +265,12 @@ static int frame_worker_hook(void *arg1, void *arg2) {
|
||||
|
||||
static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) {
|
||||
int i;
|
||||
const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
|
||||
|
||||
ctx->last_show_frame = -1;
|
||||
ctx->next_submit_thread_id = 0;
|
||||
ctx->next_output_thread_id = 0;
|
||||
ctx->num_frame_workers =
|
||||
(ctx->frame_parallel_decode == 1) ? ctx->cfg.threads: 1;
|
||||
ctx->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool));
|
||||
if (ctx->buffer_pool == NULL)
|
||||
return VPX_CODEC_MEM_ERROR;
|
||||
|
||||
ctx->frame_workers = (VP9Worker *)
|
||||
vpx_malloc(ctx->num_frame_workers * sizeof(*ctx->frame_workers));
|
||||
@@ -291,21 +282,19 @@ static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) {
|
||||
for (i = 0; i < ctx->num_frame_workers; ++i) {
|
||||
VP9Worker *const worker = &ctx->frame_workers[i];
|
||||
FrameWorkerData *worker_data = NULL;
|
||||
winterface->init(worker);
|
||||
vp9_worker_init(worker);
|
||||
worker->data1 = vpx_memalign(32, sizeof(FrameWorkerData));
|
||||
if (worker->data1 == NULL) {
|
||||
set_error_detail(ctx, "Failed to allocate worker_data");
|
||||
return VPX_CODEC_MEM_ERROR;
|
||||
}
|
||||
worker_data = (FrameWorkerData *)worker->data1;
|
||||
worker_data->pbi = vp9_decoder_create(ctx->buffer_pool);
|
||||
worker_data->pbi = vp9_decoder_create();
|
||||
if (worker_data->pbi == NULL) {
|
||||
set_error_detail(ctx, "Failed to allocate worker_data");
|
||||
return VPX_CODEC_MEM_ERROR;
|
||||
}
|
||||
worker_data->pbi->owner_frame_worker = worker;
|
||||
worker_data->worker_id = i;
|
||||
worker_data->frame_context_ready = 0;
|
||||
|
||||
// If decoding in serial mode, FrameWorker thread could create tile worker
|
||||
// thread or loopfilter thread.
|
||||
worker_data->pbi->max_threads =
|
||||
@@ -331,7 +320,6 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
|
||||
const uint8_t **data, unsigned int data_sz,
|
||||
void *user_priv, int64_t deadline) {
|
||||
vp9_ppflags_t flags = {0};
|
||||
const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
|
||||
(void)deadline;
|
||||
|
||||
// Determine the stream parameters. Note that we rely on peek_si to
|
||||
@@ -367,14 +355,12 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
|
||||
worker_data->pbi->decrypt_cb = ctx->decrypt_cb;
|
||||
worker_data->pbi->decrypt_state = ctx->decrypt_state;
|
||||
|
||||
worker->had_error = 0;
|
||||
winterface->execute(worker);
|
||||
vp9_worker_execute(worker);
|
||||
if (worker->had_error)
|
||||
return update_error_state(ctx, &worker_data->pbi->common.error);
|
||||
|
||||
// Update data pointer after decode.
|
||||
*data = worker_data->data_end;
|
||||
|
||||
if (worker->had_error)
|
||||
return update_error_state(ctx, &worker_data->pbi->common.error);
|
||||
} else {
|
||||
// TODO(hkuang): Implement frame parallel decode.
|
||||
return VPX_CODEC_INCAPABLE;
|
||||
@@ -573,25 +559,17 @@ static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
if (vp9_get_raw_frame(worker_data->pbi, &sd, &flags) == 0) {
|
||||
VP9_COMMON *const cm = &worker_data->pbi->common;
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
yuvconfig2image(&ctx->img, &sd, worker_data->user_priv);
|
||||
ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
|
||||
ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
|
||||
img = &ctx->img;
|
||||
*iter = img;
|
||||
// Decrease reference count of last output frame in frame parallel mode.
|
||||
if (ctx->frame_parallel_decode && ctx->last_show_frame >= 0) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_lock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
--frame_bufs[ctx->last_show_frame].ref_count;
|
||||
if (frame_bufs[ctx->last_show_frame].ref_count == 0) {
|
||||
pool->release_fb_cb(pool->cb_priv,
|
||||
&frame_bufs[ctx->last_show_frame].raw_frame_buffer);
|
||||
--cm->frame_bufs[ctx->last_show_frame].ref_count;
|
||||
if (cm->frame_bufs[ctx->last_show_frame].ref_count == 0) {
|
||||
cm->release_fb_cb(cm->cb_priv,
|
||||
&cm->frame_bufs[ctx->last_show_frame].raw_frame_buffer);
|
||||
}
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_unlock(&cm->buffer_pool->pool_mutex);
|
||||
#endif
|
||||
}
|
||||
ctx->last_show_frame = worker_data->pbi->common.new_fb_idx;
|
||||
}
|
||||
@@ -679,7 +657,7 @@ static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
|
||||
VP9Worker *const worker = ctx->frame_workers;
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
vp9_get_reference_dec(worker_data->pbi, data->idx, &fb);
|
||||
yuvconfig2image(&data->img, fb, NULL);
|
||||
yuvconfig2image(&data->img, fb, worker_data->user_priv);
|
||||
return VPX_CODEC_OK;
|
||||
} else {
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
|
@@ -31,7 +31,6 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
|
||||
img->fmt = VPX_IMG_FMT_I420;
|
||||
bps = 12;
|
||||
}
|
||||
img->bit_depth = 8;
|
||||
img->w = yv12->y_stride;
|
||||
img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3);
|
||||
img->d_w = yv12->y_crop_width;
|
||||
|
@@ -59,11 +59,14 @@ typedef struct FrameData {
|
||||
typedef struct SvcInternal {
|
||||
char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
|
||||
char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers
|
||||
char quantizers_keyframe[OPTION_BUFFER_SIZE]; // set by
|
||||
// vpx_svc_set_quantizers
|
||||
char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors
|
||||
|
||||
// values extracted from option, quantizers
|
||||
int scaling_factor_num[VPX_SS_MAX_LAYERS];
|
||||
int scaling_factor_den[VPX_SS_MAX_LAYERS];
|
||||
int quantizer_keyframe[VPX_SS_MAX_LAYERS];
|
||||
int quantizer[VPX_SS_MAX_LAYERS];
|
||||
|
||||
// accumulated statistics
|
||||
@@ -194,8 +197,26 @@ static int svc_log(SvcContext *svc_ctx, SVC_LOG_LEVEL level,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static vpx_codec_err_t set_option_encoding_mode(SvcContext *svc_ctx,
|
||||
const char *value_str) {
|
||||
if (strcmp(value_str, "i") == 0) {
|
||||
svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_I;
|
||||
} else if (strcmp(value_str, "alt-ip") == 0) {
|
||||
svc_ctx->encoding_mode = ALT_INTER_LAYER_PREDICTION_IP;
|
||||
} else if (strcmp(value_str, "ip") == 0) {
|
||||
svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_IP;
|
||||
} else if (strcmp(value_str, "gf") == 0) {
|
||||
svc_ctx->encoding_mode = USE_GOLDEN_FRAME;
|
||||
} else {
|
||||
svc_log(svc_ctx, SVC_LOG_ERROR, "invalid encoding mode: %s", value_str);
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
|
||||
static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
|
||||
const char *quantizer_values) {
|
||||
const char *quantizer_values,
|
||||
const int is_keyframe) {
|
||||
char *input_string;
|
||||
char *token;
|
||||
const char *delim = ",";
|
||||
@@ -206,6 +227,11 @@ static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
|
||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
||||
|
||||
if (quantizer_values == NULL || strlen(quantizer_values) == 0) {
|
||||
if (is_keyframe) {
|
||||
// If there non settings for key frame, we will apply settings from
|
||||
// non key frame. So just simply return here.
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
input_string = strdup(DEFAULT_QUANTIZER_VALUES);
|
||||
} else {
|
||||
input_string = strdup(quantizer_values);
|
||||
@@ -226,7 +252,12 @@ static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
|
||||
} else {
|
||||
q = 0;
|
||||
}
|
||||
si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
|
||||
if (is_keyframe) {
|
||||
si->quantizer_keyframe[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers]
|
||||
= q;
|
||||
} else {
|
||||
si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
|
||||
}
|
||||
}
|
||||
if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
|
||||
svc_log(svc_ctx, SVC_LOG_ERROR,
|
||||
@@ -311,6 +342,7 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||
char *option_name;
|
||||
char *option_value;
|
||||
char *input_ptr;
|
||||
int is_keyframe_qaunt_set = 0;
|
||||
vpx_codec_err_t res = VPX_CODEC_OK;
|
||||
|
||||
if (options == NULL) return VPX_CODEC_OK;
|
||||
@@ -327,14 +359,26 @@ static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
|
||||
res = VPX_CODEC_INVALID_PARAM;
|
||||
break;
|
||||
}
|
||||
if (strcmp("layers", option_name) == 0) {
|
||||
if (strcmp("encoding-mode", option_name) == 0) {
|
||||
res = set_option_encoding_mode(svc_ctx, option_value);
|
||||
if (res != VPX_CODEC_OK) break;
|
||||
} else if (strcmp("layers", option_name) == 0) {
|
||||
svc_ctx->spatial_layers = atoi(option_value);
|
||||
} else if (strcmp("scale-factors", option_name) == 0) {
|
||||
res = parse_scale_factors(svc_ctx, option_value);
|
||||
if (res != VPX_CODEC_OK) break;
|
||||
} else if (strcmp("quantizers", option_name) == 0) {
|
||||
res = parse_quantizer_values(svc_ctx, option_value);
|
||||
res = parse_quantizer_values(svc_ctx, option_value, 0);
|
||||
if (res != VPX_CODEC_OK) break;
|
||||
if (!is_keyframe_qaunt_set) {
|
||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
||||
memcpy(get_svc_internal(svc_ctx)->quantizer_keyframe, si->quantizer,
|
||||
sizeof(si->quantizer));
|
||||
}
|
||||
} else if (strcmp("quantizers-keyframe", option_name) == 0) {
|
||||
res = parse_quantizer_values(svc_ctx, option_value, 1);
|
||||
if (res != VPX_CODEC_OK) break;
|
||||
is_keyframe_qaunt_set = 1;
|
||||
} else {
|
||||
svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name);
|
||||
res = VPX_CODEC_INVALID_PARAM;
|
||||
@@ -357,13 +401,19 @@ vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) {
|
||||
}
|
||||
|
||||
vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx,
|
||||
const char *quantizers) {
|
||||
const char *quantizers,
|
||||
const int is_for_keyframe) {
|
||||
SvcInternal *const si = get_svc_internal(svc_ctx);
|
||||
if (svc_ctx == NULL || quantizers == NULL || si == NULL) {
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
strncpy(si->quantizers, quantizers, sizeof(si->quantizers));
|
||||
si->quantizers[sizeof(si->quantizers) - 1] = '\0';
|
||||
if (is_for_keyframe) {
|
||||
strncpy(si->quantizers_keyframe, quantizers, sizeof(si->quantizers));
|
||||
si->quantizers_keyframe[sizeof(si->quantizers_keyframe) - 1] = '\0';
|
||||
} else {
|
||||
strncpy(si->quantizers, quantizers, sizeof(si->quantizers));
|
||||
si->quantizers[sizeof(si->quantizers) - 1] = '\0';
|
||||
}
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
|
||||
@@ -410,9 +460,13 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
|
||||
res = parse_quantizer_values(svc_ctx, si->quantizers);
|
||||
res = parse_quantizer_values(svc_ctx, si->quantizers, 0);
|
||||
if (res != VPX_CODEC_OK) return res;
|
||||
|
||||
res = parse_quantizer_values(svc_ctx, si->quantizers_keyframe, 1);
|
||||
if (res != VPX_CODEC_OK)
|
||||
memcpy(si->quantizer_keyframe, si->quantizer, sizeof(si->quantizer));
|
||||
|
||||
res = parse_scale_factors(svc_ctx, si->scale_factors);
|
||||
if (res != VPX_CODEC_OK) return res;
|
||||
|
||||
@@ -571,14 +625,62 @@ static void calculate_enc_frame_flags(SvcContext *svc_ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (si->layer == 0) {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
} else if (is_keyframe) {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
|
||||
switch (svc_ctx->encoding_mode) {
|
||||
case ALT_INTER_LAYER_PREDICTION_IP:
|
||||
if (si->layer == 0) {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
} else if (is_keyframe) {
|
||||
if (si->layer == si->layers - 1) {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
|
||||
}
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
|
||||
}
|
||||
break;
|
||||
case INTER_LAYER_PREDICTION_I:
|
||||
if (si->layer == 0) {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
} else if (is_keyframe) {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
}
|
||||
break;
|
||||
case INTER_LAYER_PREDICTION_IP:
|
||||
if (si->layer == 0) {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
} else if (is_keyframe) {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
|
||||
}
|
||||
break;
|
||||
case USE_GOLDEN_FRAME:
|
||||
if (2 * si->layers - SVC_REFERENCE_FRAMES <= si->layer) {
|
||||
if (si->layer == 0) {
|
||||
flags = map_vp8_flags(USE_LAST | USE_GF | UPDATE_LAST);
|
||||
} else if (is_keyframe) {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_LAST | USE_ARF | USE_GF | UPDATE_LAST);
|
||||
}
|
||||
} else {
|
||||
if (si->layer == 0) {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
} else if (is_keyframe) {
|
||||
flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
|
||||
} else {
|
||||
flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
svc_log(svc_ctx, SVC_LOG_ERROR, "unexpected encoding mode: %d\n",
|
||||
svc_ctx->encoding_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
si->enc_frame_flags = flags;
|
||||
}
|
||||
|
||||
@@ -624,6 +726,13 @@ static void set_svc_parameters(SvcContext *svc_ctx,
|
||||
svc_params.flags = si->enc_frame_flags;
|
||||
|
||||
layer = si->layer;
|
||||
if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
|
||||
si->frame_within_gop == 0) {
|
||||
// layers 1 & 3 don't exist in this mode, use the higher one
|
||||
if (layer == 0 || layer == 2) {
|
||||
layer += 1;
|
||||
}
|
||||
}
|
||||
if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer,
|
||||
&svc_params.width,
|
||||
&svc_params.height)) {
|
||||
@@ -632,8 +741,13 @@ static void set_svc_parameters(SvcContext *svc_ctx,
|
||||
layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
|
||||
|
||||
if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) {
|
||||
svc_params.min_quantizer = si->quantizer[layer_index];
|
||||
svc_params.max_quantizer = si->quantizer[layer_index];
|
||||
if (vpx_svc_is_keyframe(svc_ctx)) {
|
||||
svc_params.min_quantizer = si->quantizer_keyframe[layer_index];
|
||||
svc_params.max_quantizer = si->quantizer_keyframe[layer_index];
|
||||
} else {
|
||||
svc_params.min_quantizer = si->quantizer[layer_index];
|
||||
svc_params.max_quantizer = si->quantizer[layer_index];
|
||||
}
|
||||
} else {
|
||||
svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer;
|
||||
svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer;
|
||||
@@ -645,8 +759,21 @@ static void set_svc_parameters(SvcContext *svc_ctx,
|
||||
svc_params.lst_fb_idx = si->layer;
|
||||
|
||||
// Use buffer i-1 for layer i Alt (Inter-layer prediction)
|
||||
svc_params.alt_fb_idx = (si->layer > 0) ? si->layer - 1 : 0;
|
||||
svc_params.gld_fb_idx = svc_params.lst_fb_idx;
|
||||
if (si->layer != 0) {
|
||||
const int use_higher_layer =
|
||||
svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
|
||||
si->frame_within_gop == 0;
|
||||
svc_params.alt_fb_idx = use_higher_layer ? si->layer - 2 : si->layer - 1;
|
||||
}
|
||||
|
||||
if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP) {
|
||||
svc_params.gld_fb_idx = si->layer + 1;
|
||||
} else {
|
||||
if (si->layer < 2 * si->layers - SVC_REFERENCE_FRAMES)
|
||||
svc_params.gld_fb_idx = svc_params.lst_fb_idx;
|
||||
else
|
||||
svc_params.gld_fb_idx = 2 * si->layers - 1 - si->layer;
|
||||
}
|
||||
|
||||
svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, layer: %d, %dx%d, q: %d\n",
|
||||
si->encode_frame_count, si->layer, svc_params.width,
|
||||
@@ -705,6 +832,11 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
|
||||
if (rawimg != NULL) {
|
||||
// encode each layer
|
||||
for (si->layer = 0; si->layer < si->layers; ++si->layer) {
|
||||
if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
|
||||
si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
|
||||
svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
|
||||
continue;
|
||||
}
|
||||
calculate_enc_frame_flags(svc_ctx);
|
||||
set_svc_parameters(svc_ctx, codec_ctx);
|
||||
}
|
||||
@@ -843,7 +975,7 @@ static double calc_psnr(double d) {
|
||||
|
||||
// dump accumulated statistics and reset accumulated values
|
||||
const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
|
||||
int number_of_frames, encode_frame_count;
|
||||
int number_of_frames, number_of_keyframes, encode_frame_count;
|
||||
int i, j;
|
||||
uint32_t bytes_total = 0;
|
||||
double scale[COMPONENTS];
|
||||
@@ -860,9 +992,14 @@ const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
|
||||
if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx);
|
||||
|
||||
svc_log(svc_ctx, SVC_LOG_INFO, "\n");
|
||||
number_of_keyframes = encode_frame_count / si->kf_dist + 1;
|
||||
for (i = 0; i < si->layers; ++i) {
|
||||
number_of_frames = encode_frame_count;
|
||||
|
||||
if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
|
||||
(i == 1 || i == 3)) {
|
||||
number_of_frames -= number_of_keyframes;
|
||||
}
|
||||
svc_log(svc_ctx, SVC_LOG_INFO,
|
||||
"Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n",
|
||||
i, (double)si->psnr_sum[i][0] / number_of_frames,
|
||||
|
@@ -40,13 +40,13 @@ static void img_buf_free(void *memblk) {
|
||||
}
|
||||
}
|
||||
|
||||
static vpx_image_t *img_alloc_helper(vpx_image_t *img,
|
||||
vpx_img_fmt_t fmt,
|
||||
unsigned int d_w,
|
||||
unsigned int d_h,
|
||||
unsigned int buf_align,
|
||||
unsigned int stride_align,
|
||||
unsigned char *img_data) {
|
||||
static vpx_image_t *img_alloc_helper(vpx_image_t *img,
|
||||
vpx_img_fmt_t fmt,
|
||||
unsigned int d_w,
|
||||
unsigned int d_h,
|
||||
unsigned int buf_align,
|
||||
unsigned int stride_align,
|
||||
unsigned char *img_data) {
|
||||
|
||||
unsigned int h, w, s, xcs, ycs, bps;
|
||||
int align;
|
||||
@@ -94,21 +94,6 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img,
|
||||
case VPX_IMG_FMT_VPXYV12:
|
||||
bps = 12;
|
||||
break;
|
||||
case VPX_IMG_FMT_I422:
|
||||
bps = 16;
|
||||
break;
|
||||
case VPX_IMG_FMT_I444:
|
||||
bps = 24;
|
||||
break;
|
||||
case VPX_IMG_FMT_I42016:
|
||||
bps = 24;
|
||||
break;
|
||||
case VPX_IMG_FMT_I42216:
|
||||
bps = 32;
|
||||
break;
|
||||
case VPX_IMG_FMT_I44416:
|
||||
bps = 48;
|
||||
break;
|
||||
default:
|
||||
bps = 16;
|
||||
break;
|
||||
@@ -120,9 +105,6 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img,
|
||||
case VPX_IMG_FMT_YV12:
|
||||
case VPX_IMG_FMT_VPXI420:
|
||||
case VPX_IMG_FMT_VPXYV12:
|
||||
case VPX_IMG_FMT_I422:
|
||||
case VPX_IMG_FMT_I42016:
|
||||
case VPX_IMG_FMT_I42216:
|
||||
xcs = 1;
|
||||
break;
|
||||
default:
|
||||
@@ -174,7 +156,6 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img,
|
||||
goto fail;
|
||||
|
||||
img->fmt = fmt;
|
||||
img->bit_depth = (fmt & VPX_IMG_FMT_HIGH) ? 16 : 8;
|
||||
img->w = w;
|
||||
img->h = h;
|
||||
img->x_chroma_shift = xcs;
|
||||
|
@@ -23,6 +23,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum SVC_ENCODING_MODE {
|
||||
INTER_LAYER_PREDICTION_I,
|
||||
ALT_INTER_LAYER_PREDICTION_IP,
|
||||
INTER_LAYER_PREDICTION_IP,
|
||||
USE_GOLDEN_FRAME
|
||||
} SVC_ENCODING_MODE;
|
||||
|
||||
typedef enum SVC_LOG_LEVEL {
|
||||
SVC_LOG_ERROR,
|
||||
SVC_LOG_INFO,
|
||||
@@ -32,6 +39,7 @@ typedef enum SVC_LOG_LEVEL {
|
||||
typedef struct {
|
||||
// public interface to svc_command options
|
||||
int spatial_layers; // number of layers
|
||||
SVC_ENCODING_MODE encoding_mode; // svc encoding strategy
|
||||
SVC_LOG_LEVEL log_level; // amount of information to display
|
||||
int log_print; // when set, printf log messages instead of returning the
|
||||
// message with svc_get_message
|
||||
@@ -56,7 +64,8 @@ vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options);
|
||||
* e.g., "60,53,39,33,27"
|
||||
*/
|
||||
vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx,
|
||||
const char *quantizer_values);
|
||||
const char *quantizer_values,
|
||||
const int is_for_keyframe);
|
||||
|
||||
/**
|
||||
* Set SVC scale factors
|
||||
|
@@ -212,15 +212,6 @@ extern "C" {
|
||||
vpx_codec_priv_t *priv; /**< Algorithm private storage */
|
||||
} vpx_codec_ctx_t;
|
||||
|
||||
/*!\brief Bit depth for codec
|
||||
* *
|
||||
* This enumeration determines the bit depth of the codec.
|
||||
*/
|
||||
typedef enum vpx_bit_depth {
|
||||
VPX_BITS_8, /**< 8 bits */
|
||||
VPX_BITS_10, /**< 10 bits */
|
||||
VPX_BITS_12 /**< 12 bits */
|
||||
} vpx_bit_depth_t;
|
||||
|
||||
/*
|
||||
* Library Version Number Interface
|
||||
|
@@ -103,9 +103,8 @@ extern "C" {
|
||||
vpx_img_fmt_t fmt; /**< Image Format */
|
||||
|
||||
/* Image storage dimensions */
|
||||
unsigned int w; /**< Stored image width */
|
||||
unsigned int h; /**< Stored image height */
|
||||
unsigned int bit_depth; /**< Stored image bit-depth */
|
||||
unsigned int w; /**< Stored image width */
|
||||
unsigned int h; /**< Stored image height */
|
||||
|
||||
/* Image display dimensions */
|
||||
unsigned int d_w; /**< Displayed image width */
|
||||
|
5
vpxdec.c
5
vpxdec.c
@@ -895,8 +895,7 @@ int main_loop(int argc, const char **argv_) {
|
||||
len = y4m_write_file_header(buf, sizeof(buf),
|
||||
vpx_input_ctx.width,
|
||||
vpx_input_ctx.height,
|
||||
&vpx_input_ctx.framerate,
|
||||
img->fmt, 8);
|
||||
&vpx_input_ctx.framerate, img->fmt);
|
||||
if (do_md5) {
|
||||
MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len);
|
||||
} else {
|
||||
@@ -934,6 +933,8 @@ int main_loop(int argc, const char **argv_) {
|
||||
}
|
||||
}
|
||||
|
||||
if (stop_after && frame_in >= stop_after)
|
||||
break;
|
||||
}
|
||||
|
||||
if (summary || progress) {
|
||||
|
2
vpxenc.c
2
vpxenc.c
@@ -756,7 +756,6 @@ void open_input_file(struct VpxInputContext *input) {
|
||||
input->framerate.numerator = input->y4m.fps_n;
|
||||
input->framerate.denominator = input->y4m.fps_d;
|
||||
input->fmt = input->y4m.vpx_fmt;
|
||||
input->bit_depth = input->y4m.bit_depth;
|
||||
} else
|
||||
fatal("Unsupported Y4M stream.");
|
||||
} else if (input->detect.buf_read == 4 && fourcc_is_ivf(input->detect.buf)) {
|
||||
@@ -1534,7 +1533,6 @@ int main(int argc, const char **argv_) {
|
||||
input.framerate.numerator = 30;
|
||||
input.framerate.denominator = 1;
|
||||
input.only_i420 = 1;
|
||||
input.bit_depth = 0;
|
||||
|
||||
/* First parse the global configuration values, because we want to apply
|
||||
* other parameters on top of the default configuration provided by the
|
||||
|
44
y4menc.c
44
y4menc.c
@@ -8,48 +8,16 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "./y4menc.h"
|
||||
|
||||
int y4m_write_file_header(char *buf, size_t len, int width, int height,
|
||||
const struct VpxRational *framerate,
|
||||
vpx_img_fmt_t fmt, unsigned int bit_depth) {
|
||||
const char *color;
|
||||
switch (bit_depth) {
|
||||
case 8:
|
||||
color = fmt == VPX_IMG_FMT_444A ? "C444alpha\n" :
|
||||
fmt == VPX_IMG_FMT_I444 ? "C444\n" :
|
||||
fmt == VPX_IMG_FMT_I422 ? "C422\n" :
|
||||
"C420jpeg\n";
|
||||
break;
|
||||
case 9:
|
||||
color = fmt == VPX_IMG_FMT_I44416 ? "C444p9 XYSCSS=444P9\n" :
|
||||
fmt == VPX_IMG_FMT_I42216 ? "C422p9 XYSCSS=422P9\n" :
|
||||
"C420p9 XYSCSS=420P9\n";
|
||||
break;
|
||||
case 10:
|
||||
color = fmt == VPX_IMG_FMT_I44416 ? "C444p10 XYSCSS=444P10\n" :
|
||||
fmt == VPX_IMG_FMT_I42216 ? "C422p10 XYSCSS=422P10\n" :
|
||||
"C420p10 XYSCSS=420P10\n";
|
||||
break;
|
||||
case 12:
|
||||
color = fmt == VPX_IMG_FMT_I44416 ? "C444p12 XYSCSS=444P12\n" :
|
||||
fmt == VPX_IMG_FMT_I42216 ? "C422p12 XYSCSS=422P12\n" :
|
||||
"C420p12 XYSCSS=420P12\n";
|
||||
break;
|
||||
case 14:
|
||||
color = fmt == VPX_IMG_FMT_I44416 ? "C444p14 XYSCSS=444P14\n" :
|
||||
fmt == VPX_IMG_FMT_I42216 ? "C422p14 XYSCSS=422P14\n" :
|
||||
"C420p14 XYSCSS=420P14\n";
|
||||
break;
|
||||
case 16:
|
||||
color = fmt == VPX_IMG_FMT_I44416 ? "C444p16 XYSCSS=444P16\n" :
|
||||
fmt == VPX_IMG_FMT_I42216 ? "C422p16 XYSCSS=422P16\n" :
|
||||
"C420p16 XYSCSS=420P16\n";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
vpx_img_fmt_t fmt) {
|
||||
const char *const color = fmt == VPX_IMG_FMT_444A ? "C444alpha\n" :
|
||||
fmt == VPX_IMG_FMT_I444 ? "C444\n" :
|
||||
fmt == VPX_IMG_FMT_I422 ? "C422\n" :
|
||||
"C420jpeg\n";
|
||||
|
||||
return snprintf(buf, len, "YUV4MPEG2 W%u H%u F%u:%u I%c %s", width, height,
|
||||
framerate->numerator, framerate->denominator, 'p', color);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user