Compare commits

..

9 Commits

Author SHA1 Message Date
Alex Converse
2898c6728d PRecompute token tab
Change-Id: I85e172352dacf7a990d8d9296e071f9d603fcb7b
2015-10-14 18:03:36 -07:00
Alex Converse
c62859fe76 Write tokens with rans
Change-Id: I3009ec1cf54a36c96b59d8203bc01f4fe82145a0
2015-10-14 17:57:56 -07:00
Alex Converse
365e37193c bar
Change-Id: I5d5acdde6ea98b986d8e0c9247df20a41c56950b
2015-09-14 11:40:34 -07:00
Alex Converse
f2b5185d76 Avoid conflicting with the superframe marker
Change-Id: If77f415380528d388a4bc330ec843dd58fac2f01
2015-09-11 16:57:15 -07:00
Alex Converse
5720143261 fencepost
Change-Id: Ib0f988e11f80d3684d37119f457ca795f0ad16fa
2015-09-11 16:37:01 -07:00
Alex Converse
911f6b036e tmp
Change-Id: I6121c07f4af8065c1f4c4488e50990f3d71cc4c1
2015-09-11 14:17:59 -07:00
Alex Converse
4858f93633 tmp ans
Change-Id: Id5dadc88fccca610fc10495352590782eca4a62f
2015-09-11 13:02:45 -07:00
Alex Converse
e4e605623b WIP reverse tree writing still using the old boolcoder.
Change-Id: I41f056f4a7d360f1085c6435deeea5b3bcf32dbe
2015-09-09 20:36:18 -07:00
Alex Converse
9245a0661d WIP move tokens to end of tile
Change-Id: I220de204642734f68f7bf54ec3d406f8e39f0382
2015-09-09 18:13:51 -07:00
319 changed files with 67871 additions and 6065 deletions

View File

@@ -1,21 +1,14 @@
Adrian Grange <agrange@google.com>
Adrian Grange <agrange@google.com> <agrange@agrange-macbookpro.roam.corp.google.com>
Aex Converse <aconverse@google.com>
Aex Converse <aconverse@google.com> <alex.converse@gmail.com>
Alex Converse <aconverse@google.com> <alex.converse@gmail.com>
Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com>
Alpha Lam <hclam@google.com> <hclam@chromium.org>
Deb Mukherjee <debargha@google.com>
Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com>
Guillaume Martres <gmartres@google.com> <smarter3@gmail.com>
Hangyu Kuang <hkuang@google.com>
Hangyu Kuang <hkuang@google.com> <hkuang@hkuang-macbookpro.roam.corp.google.com>
Hui Su <huisu@google.com>
Jacky Chen <jackychen@google.com>
Jim Bankoski <jimbankoski@google.com>
Johann Koenig <johannkoenig@google.com>
Johann Koenig <johannkoenig@google.com> <johann.koenig@duck.com>
Johann Koenig <johannkoenig@google.com> <johannkoenig@dhcp-172-19-7-52.mtv.corp.google.com>
Johann Koenig <johannkoenig@google.com> <johann.koenig@gmail.com>
John Koleszar <jkoleszar@google.com>
Joshua Litt <joshualitt@google.com> <joshualitt@chromium.org>
Marco Paniconi <marpan@google.com>
@@ -24,13 +17,10 @@ Pascal Massimino <pascal.massimino@gmail.com>
Paul Wilkins <paulwilkins@google.com>
Ralph Giles <giles@xiph.org> <giles@entropywave.com>
Ralph Giles <giles@xiph.org> <giles@mozilla.com>
Ronald S. Bultje <rsbultje@gmail.com> <rbultje@google.com>
Sami Pietilä <samipietila@google.com>
Tamar Levy <tamar.levy@intel.com>
Tamar Levy <tamar.levy@intel.com> <levytamar82@gmail.com>
Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
Timothy B. Terriberry <tterribe@xiph.org> Tim Terriberry <tterriberry@mozilla.com>
Tom Finegan <tomfinegan@google.com>
Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org>
Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com>
Yaowu Xu <yaowu@google.com> <yaowu@YAOWU2-W.ad.corp.google.com>

15
AUTHORS
View File

@@ -5,9 +5,9 @@ Aaron Watry <awatry@gmail.com>
Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
Adam Xu <adam@xuyaowu.com>
Adrian Grange <agrange@google.com>
Aex Converse <aconverse@google.com>
Ahmad Sharif <asharif@google.com>
Alexander Voronov <avoronov@graphics.cs.msu.ru>
Alex Converse <aconverse@google.com>
Alexis Ballier <aballier@gentoo.org>
Alok Ahuja <waveletcoeff@gmail.com>
Alpha Lam <hclam@google.com>
@@ -16,10 +16,8 @@ Ami Fischman <fischman@chromium.org>
Andoni Morales Alastruey <ylatuya@gmail.com>
Andres Mejia <mcitadel@gmail.com>
Andrew Russell <anrussell@google.com>
Angie Chiang <angiebird@google.com>
Aron Rosenberg <arosenberg@logitech.com>
Attila Nagy <attilanagy@google.com>
Brion Vibber <bvibber@wikimedia.org>
changjun.yang <changjun.yang@intel.com>
Charles 'Buck' Krasic <ckrasic@google.com>
chm <chm@rock-chips.com>
@@ -29,7 +27,6 @@ Deb Mukherjee <debargha@google.com>
Dim Temp <dimtemp0@gmail.com>
Dmitry Kovalev <dkovalev@google.com>
Dragan Mrdjan <dmrdjan@mips.com>
Ed Baker <edward.baker@intel.com>
Ehsan Akhgari <ehsan.akhgari@gmail.com>
Erik Niemeyer <erik.a.niemeyer@intel.com>
Fabio Pedretti <fabio.ped@libero.it>
@@ -37,8 +34,6 @@ Frank Galligan <fgalligan@google.com>
Fredrik Söderquist <fs@opera.com>
Fritz Koenig <frkoenig@google.com>
Gaute Strokkenes <gaute.strokkenes@broadcom.com>
Geza Lore <gezalore@gmail.com>
Ghislain MARY <ghislainmary2@gmail.com>
Giuseppe Scrivano <gscrivano@gnu.org>
Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
Guillaume Martres <gmartres@google.com>
@@ -49,7 +44,7 @@ Henrik Lundin <hlundin@google.com>
Hui Su <huisu@google.com>
Ivan Maltz <ivanmaltz@google.com>
Jacek Caban <cjacek@gmail.com>
Jacky Chen <jackychen@google.com>
JackyChen <jackychen@google.com>
James Berry <jamesberry@google.com>
James Yu <james.yu@linaro.org>
James Zern <jzern@google.com>
@@ -65,11 +60,9 @@ Jingning Han <jingning@google.com>
Joey Parrish <joeyparrish@google.com>
Johann Koenig <johannkoenig@google.com>
John Koleszar <jkoleszar@google.com>
Johnny Klonaris <google@jawknee.com>
John Stark <jhnstrk@gmail.com>
Joshua Bleecher Snyder <josh@treelinelabs.com>
Joshua Litt <joshualitt@google.com>
Julia Robson <juliamrobson@gmail.com>
Justin Clift <justin@salasaga.org>
Justin Lebar <justin.lebar@gmail.com>
KO Myung-Hun <komh@chollian.net>
@@ -89,7 +82,6 @@ Mike Hommey <mhommey@mozilla.com>
Mikhal Shemer <mikhal@google.com>
Minghai Shang <minghai@google.com>
Morton Jonuschat <yabawock@gmail.com>
Nico Weber <thakis@chromium.org>
Parag Salasakar <img.mips1@gmail.com>
Pascal Massimino <pascal.massimino@gmail.com>
Patrik Westin <patrik.westin@gmail.com>
@@ -104,7 +96,7 @@ Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
Rafaël Carré <funman@videolan.org>
Ralph Giles <giles@xiph.org>
Rob Bradford <rob@linux.intel.com>
Ronald S. Bultje <rsbultje@gmail.com>
Ronald S. Bultje <rbultje@google.com>
Rui Ueyama <ruiu@google.com>
Sami Pietilä <samipietila@google.com>
Scott Graham <scottmg@chromium.org>
@@ -112,7 +104,6 @@ Scott LaVarnway <slavarnway@google.com>
Sean McGovern <gseanmcg@gmail.com>
Sergey Ulanov <sergeyu@chromium.org>
Shimon Doodkin <helpmepro1@gmail.com>
Shunyao Li <shunyaoli@google.com>
Stefan Holmer <holmer@google.com>
Suman Sunkara <sunkaras@google.com>
Taekhyun Kim <takim@nvidia.com>

View File

@@ -1,19 +1,7 @@
2015-11-09 v1.5.0 "Javan Whistling Duck"
This release improves upon the VP9 encoder and speeds up the encoding and
decoding processes.
- Upgrading:
This release is ABI incompatible with 1.4.0. It drops deprecated VP8
controls and adds a variety of VP9 controls for testing.
The vpxenc utility now prefers VP9 by default.
- Enhancements:
Faster VP9 encoding and decoding
Smaller library size by combining functions used by VP8 and VP9
- Bug Fixes:
A variety of fuzzing issues
xxxx-yy-zz v1.4.0 "Changes for next release"
vpxenc is changed to use VP9 by default.
Encoder controls added for 1 pass SVC.
Decoder control to toggle on/off loopfilter.
2015-04-03 v1.4.0 "Indian Runner Duck"
This release includes significant improvements to the VP9 codec.

View File

@@ -287,7 +287,7 @@ define archive_template
# for creating them.
$(1):
$(if $(quiet),@echo " [AR] $$@")
$(qexec)$$(AR) $$(ARFLAGS) $$@ $$^
$(qexec)$$(AR) $$(ARFLAGS) $$@ $$?
endef
define so_template

View File

@@ -73,7 +73,6 @@ Build options:
--target=TARGET target platform tuple [generic-gnu]
--cpu=CPU optimize for a specific cpu rather than a family
--extra-cflags=ECFLAGS add ECFLAGS to CFLAGS [$CFLAGS]
--extra-cxxflags=ECXXFLAGS add ECXXFLAGS to CXXFLAGS [$CXXFLAGS]
${toggle_extra_warnings} emit harmless warnings (always non-fatal)
${toggle_werror} treat warnings as errors, if possible
(not available with all compilers)
@@ -201,10 +200,6 @@ disabled(){
eval test "x\$$1" = "xno"
}
# Iterates through positional parameters, checks to confirm the parameter has
# not been explicitly (force) disabled, and enables the setting controlled by
# the parameter when the setting is not disabled.
# Note: Does NOT alter RTCD generation options ($RTCD_OPTIONS).
soft_enable() {
for var in $*; do
if ! disabled $var; then
@@ -214,10 +209,6 @@ soft_enable() {
done
}
# Iterates through positional parameters, checks to confirm the parameter has
# not been explicitly (force) enabled, and disables the setting controlled by
# the parameter when the setting is not enabled.
# Note: Does NOT alter RTCD generation options ($RTCD_OPTIONS).
soft_disable() {
for var in $*; do
if ! enabled $var; then
@@ -346,10 +337,6 @@ check_add_cflags() {
check_cflags "$@" && add_cflags_only "$@"
}
check_add_cxxflags() {
check_cxxflags "$@" && add_cxxflags_only "$@"
}
check_add_asflags() {
log add_asflags "$@"
add_asflags "$@"
@@ -441,7 +428,7 @@ NM=${NM}
CFLAGS = ${CFLAGS}
CXXFLAGS = ${CXXFLAGS}
ARFLAGS = -crs\$(if \$(quiet),,v)
ARFLAGS = -rus\$(if \$(quiet),c,v)
LDFLAGS = ${LDFLAGS}
ASFLAGS = ${ASFLAGS}
extralibs = ${extralibs}
@@ -516,9 +503,6 @@ process_common_cmdline() {
--extra-cflags=*)
extra_cflags="${optval}"
;;
--extra-cxxflags=*)
extra_cxxflags="${optval}"
;;
--enable-?*|--disable-?*)
eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
if echo "${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null; then
@@ -633,11 +617,6 @@ show_darwin_sdk_path() {
xcodebuild -sdk $1 -version Path 2>/dev/null
}
# Print the major version number of the Darwin SDK specified by $1.
show_darwin_sdk_major_version() {
xcrun --sdk $1 --show-sdk-version 2>/dev/null | cut -d. -f1
}
process_common_toolchain() {
if [ -z "$toolchain" ]; then
gcctarget="${CHOST:-$(gcc -dumpmachine 2> /dev/null)}"
@@ -750,14 +729,13 @@ process_common_toolchain() {
# platforms, so use the newest one available.
case ${toolchain} in
arm*-darwin*)
add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
iphoneos_sdk_dir="$(show_darwin_sdk_path iphoneos)"
if [ -d "${iphoneos_sdk_dir}" ]; then
add_cflags "-isysroot ${iphoneos_sdk_dir}"
add_ldflags "-isysroot ${iphoneos_sdk_dir}"
ios_sdk_dir="$(show_darwin_sdk_path iphoneos)"
if [ -d "${ios_sdk_dir}" ]; then
add_cflags "-isysroot ${ios_sdk_dir}"
add_ldflags "-isysroot ${ios_sdk_dir}"
fi
;;
x86*-darwin*)
*-darwin*)
osx_sdk_dir="$(show_darwin_sdk_path macosx)"
if [ -d "${osx_sdk_dir}" ]; then
add_cflags "-isysroot ${osx_sdk_dir}"
@@ -833,35 +811,16 @@ process_common_toolchain() {
die "Disabling neon while keeping neon-asm is not supported"
fi
case ${toolchain} in
# Apple iOS SDKs no longer support armv6 as of the version 9
# release (coincides with release of Xcode 7). Only enable media
# when using earlier SDK releases.
*-darwin*)
if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then
soft_enable media
else
soft_disable media
RTCD_OPTIONS="${RTCD_OPTIONS}--disable-media "
fi
# Neon is guaranteed on iOS 6+ devices, while old media extensions
# no longer assemble with iOS 9 SDK
;;
*)
soft_enable media
;;
esac
;;
armv6)
case ${toolchain} in
*-darwin*)
if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then
soft_enable media
else
die "Your iOS SDK does not support armv6."
fi
;;
*)
soft_enable media
;;
esac
soft_enable media
;;
esac
@@ -1044,12 +1003,6 @@ EOF
done
asm_conversion_cmd="${source_path}/build/make/ads2gas_apple.pl"
if [ "$(show_darwin_sdk_major_version iphoneos)" -gt 8 ]; then
check_add_cflags -fembed-bitcode
check_add_asflags -fembed-bitcode
check_add_ldflags -fembed-bitcode
fi
;;
linux*)
@@ -1220,8 +1173,7 @@ EOF
&& AS=""
fi
[ "${AS}" = auto ] || [ -z "${AS}" ] \
&& die "Neither yasm nor nasm have been found." \
"See the prerequisites section in the README for more info."
&& die "Neither yasm nor nasm have been found"
;;
esac
log_echo " using $AS"
@@ -1260,13 +1212,6 @@ EOF
enabled x86 && sim_arch="-arch i386" || sim_arch="-arch x86_64"
add_cflags ${sim_arch}
add_ldflags ${sim_arch}
if [ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then
# yasm v1.3.0 doesn't know what -fembed-bitcode means, so turning it
# on is pointless (unless building a C-only lib). Warn the user, but
# do nothing here.
log "Warning: Bitcode embed disabled for simulator targets."
fi
;;
os2)
add_asflags -f aout

View File

@@ -25,6 +25,7 @@ CONFIGURE_ARGS="--disable-docs
DIST_DIR="_dist"
FRAMEWORK_DIR="VPX.framework"
HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx"
MAKE_JOBS=1
SCRIPT_DIR=$(dirname "$0")
LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd)
LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
@@ -40,24 +41,15 @@ TARGETS="arm64-darwin-gcc
build_target() {
local target="$1"
local old_pwd="$(pwd)"
local target_specific_flags=""
vlog "***Building target: ${target}***"
case "${target}" in
x86-*)
target_specific_flags="--enable-pic"
vlog "Enabled PIC for ${target}"
;;
esac
mkdir "${target}"
cd "${target}"
eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \
${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \
${devnull}
${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${devnull}
export DIST_DIR
eval make dist ${devnull}
eval make -j ${MAKE_JOBS} dist ${devnull}
cd "${old_pwd}"
vlog "***Done building target: ${target}***"
@@ -202,12 +194,11 @@ cat << EOF
Usage: ${0##*/} [arguments]
--help: Display this message and exit.
--extra-configure-args <args>: Extra args to pass when configuring libvpx.
--jobs: Number of make jobs.
--preserve-build-output: Do not delete the build directory.
--show-build-output: Show output from each library build.
--targets <targets>: Override default target list. Defaults:
${TARGETS}
--test-link: Confirms all targets can be linked. Functionally identical to
passing --enable-examples via --extra-configure-args.
--verbose: Output information about the environment and each stage of the
build.
EOF
@@ -236,15 +227,16 @@ while [ -n "$1" ]; do
iosbuild_usage
exit
;;
--jobs)
MAKE_JOBS="$2"
shift
;;
--preserve-build-output)
PRESERVE_BUILD_OUTPUT=yes
;;
--show-build-output)
devnull=
;;
--test-link)
EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples"
;;
--targets)
TARGETS="$2"
shift
@@ -268,11 +260,11 @@ cat << EOF
EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS}
FRAMEWORK_DIR=${FRAMEWORK_DIR}
HEADER_DIR=${HEADER_DIR}
MAKE_JOBS=${MAKE_JOBS}
PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT}
LIBVPX_SOURCE_DIR=${LIBVPX_SOURCE_DIR}
LIPO=${LIPO}
MAKEFLAGS=${MAKEFLAGS}
ORIG_PWD=${ORIG_PWD}
PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT}
TARGETS="${TARGETS}"
EOF
fi

5
configure vendored
View File

@@ -264,7 +264,6 @@ EXPERIMENT_LIST="
spatial_svc
fp_mb_stats
emulate_hardware
misc_fixes
"
CONFIG_LIST="
dependency_tracking
@@ -723,10 +722,6 @@ EOF
check_add_cflags ${extra_cflags} || \
die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler"
fi
if [ -n "${extra_cxxflags}" ]; then
check_add_cxxflags ${extra_cxxflags} || \
die "Requested extra CXXFLAGS '${extra_cxxflags}' not supported by compiler"
fi
}

View File

@@ -36,8 +36,6 @@ LIBYUV_SRCS += third_party/libyuv/include/libyuv/basic_types.h \
third_party/libyuv/source/scale_neon64.cc \
third_party/libyuv/source/scale_win.cc \
LIBWEBM_COMMON_SRCS += third_party/libwebm/webmids.hpp
LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer.cpp \
third_party/libwebm/mkvmuxerutil.cpp \
third_party/libwebm/mkvwriter.cpp \
@@ -45,7 +43,8 @@ LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer.cpp \
third_party/libwebm/mkvmuxertypes.hpp \
third_party/libwebm/mkvmuxerutil.hpp \
third_party/libwebm/mkvparser.hpp \
third_party/libwebm/mkvwriter.hpp
third_party/libwebm/mkvwriter.hpp \
third_party/libwebm/webmids.hpp
LIBWEBM_PARSER_SRCS = third_party/libwebm/mkvparser.cpp \
third_party/libwebm/mkvreader.cpp \
@@ -69,7 +68,6 @@ ifeq ($(CONFIG_LIBYUV),yes)
vpxdec.SRCS += $(LIBYUV_SRCS)
endif
ifeq ($(CONFIG_WEBM_IO),yes)
vpxdec.SRCS += $(LIBWEBM_COMMON_SRCS)
vpxdec.SRCS += $(LIBWEBM_PARSER_SRCS)
vpxdec.SRCS += webmdec.cc webmdec.h
endif
@@ -91,7 +89,6 @@ ifeq ($(CONFIG_LIBYUV),yes)
vpxenc.SRCS += $(LIBYUV_SRCS)
endif
ifeq ($(CONFIG_WEBM_IO),yes)
vpxenc.SRCS += $(LIBWEBM_COMMON_SRCS)
vpxenc.SRCS += $(LIBWEBM_MUXER_SRCS)
vpxenc.SRCS += webmenc.cc webmenc.h
endif

View File

@@ -80,8 +80,6 @@ static const arg_def_t rc_end_usage_arg =
ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
static const arg_def_t speed_arg =
ARG_DEF("sp", "speed", 1, "speed configuration");
static const arg_def_t aqmode_arg =
ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
#if CONFIG_VP9_HIGHBITDEPTH
static const struct arg_enum_list bitdepth_enum[] = {
@@ -103,7 +101,7 @@ static const arg_def_t *svc_args[] = {
&kf_dist_arg, &scale_factors_arg, &passes_arg, &pass_arg,
&fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg,
&max_bitrate_arg, &temporal_layers_arg, &temporal_layering_mode_arg,
&lag_in_frame_arg, &threads_arg, &aqmode_arg,
&lag_in_frame_arg, &threads_arg,
#if OUTPUT_RC_STATS
&output_rc_stats_arg,
#endif
@@ -223,8 +221,6 @@ static void parse_command_line(int argc, const char **argv_,
#endif
} else if (arg_match(&arg, &speed_arg, argi)) {
svc_ctx->speed = arg_parse_uint(&arg);
} else if (arg_match(&arg, &aqmode_arg, argi)) {
svc_ctx->aqmode = arg_parse_uint(&arg);
} else if (arg_match(&arg, &threads_arg, argi)) {
svc_ctx->threads = arg_parse_uint(&arg);
} else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
@@ -544,59 +540,6 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data,
}
#endif
// Example pattern for spatial layers and 2 temporal layers used in the
// bypass/flexible mode. The pattern corresponds to the pattern
// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
// non-flexible mode.
void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers,
int is_key_frame,
vpx_svc_ref_frame_config_t *ref_frame_config) {
for (sl = 0; sl < num_spatial_layers; ++sl) {
if (!tl) {
if (!sl) {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
} else {
if (is_key_frame) {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_LAST |
VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
} else {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
}
}
} else if (tl == 1) {
if (!sl) {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_GF;
} else {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_GF;
}
}
if (tl == 0) {
ref_frame_config->lst_fb_idx[sl] = sl;
if (sl)
ref_frame_config->gld_fb_idx[sl] = sl - 1;
else
ref_frame_config->gld_fb_idx[sl] = 0;
ref_frame_config->alt_fb_idx[sl] = 0;
} else if (tl == 1) {
ref_frame_config->lst_fb_idx[sl] = sl;
ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1;
ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
}
}
}
int main(int argc, const char **argv) {
AppInput app_input = {0};
VpxVideoWriter *writer = NULL;
@@ -617,7 +560,6 @@ int main(int argc, const char **argv) {
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
struct RateControlStats rc;
vpx_svc_layer_id_t layer_id;
vpx_svc_ref_frame_config_t ref_frame_config;
int sl, tl;
double sum_bitrate = 0.0;
double sum_bitrate2 = 0.0;
@@ -693,7 +635,7 @@ int main(int argc, const char **argv) {
vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
if (svc_ctx.threads)
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
if (svc_ctx.speed >= 5)
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
@@ -707,30 +649,6 @@ int main(int argc, const char **argv) {
end_of_stream = 1;
}
// For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates)
// and the buffer indices for each spatial layer of the current
// (super)frame to be encoded. The temporal layer_id for the current frame
// also needs to be set.
// TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS"
// mode to "VP9E_LAYERING_MODE_BYPASS".
if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
// Example for 2 temporal layers.
if (frame_cnt % 2 == 0)
layer_id.temporal_layer_id = 0;
else
layer_id.temporal_layer_id = 1;
// Note that we only set the temporal layer_id, since we are calling
// the encode for the whole superframe. The encoder will internally loop
// over all the spatial layers for the current superframe.
vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id,
svc_ctx.spatial_layers,
frame_cnt == 0,
&ref_frame_config);
vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG,
&ref_frame_config);
}
vpx_usec_timer_start(&timer);
res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
pts, frame_duration, svc_ctx.speed >= 5 ?

View File

@@ -684,14 +684,14 @@ int main(int argc, char **argv) {
if (strncmp(encoder->name, "vp8", 3) == 0) {
vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
} else if (strncmp(encoder->name, "vp9", 3) == 0) {
vpx_svc_extra_cfg_t svc_params;
vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0))

View File

@@ -260,7 +260,7 @@ OBJS-yes += $(LIBVPX_OBJS)
LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
SO_VERSION_MAJOR := 3
SO_VERSION_MAJOR := 2
SO_VERSION_MINOR := 0
SO_VERSION_PATCH := 0
ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS))

View File

@@ -1,127 +0,0 @@
/*
* Copyright (c) 2015 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 <algorithm>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
namespace {
// Check if any pixel in a 16x16 macroblock varies between frames.
int CheckMb(const vpx_image_t &current, const vpx_image_t &previous,
int mb_r, int mb_c) {
for (int plane = 0; plane < 3; plane++) {
int r = 16 * mb_r;
int c0 = 16 * mb_c;
int r_top = std::min(r + 16, static_cast<int>(current.d_h));
int c_top = std::min(c0 + 16, static_cast<int>(current.d_w));
r = std::max(r, 0);
c0 = std::max(c0, 0);
if (plane > 0 && current.x_chroma_shift) {
c_top = (c_top + 1) >> 1;
c0 >>= 1;
}
if (plane > 0 && current.y_chroma_shift) {
r_top = (r_top + 1) >> 1;
r >>= 1;
}
for (; r < r_top; ++r) {
for (int c = c0; c < c_top; ++c) {
if (current.planes[plane][current.stride[plane] * r + c] !=
previous.planes[plane][previous.stride[plane] * r + c])
return 1;
}
}
}
return 0;
}
void GenerateMap(int mb_rows, int mb_cols, const vpx_image_t &current,
const vpx_image_t &previous, uint8_t *map) {
for (int mb_r = 0; mb_r < mb_rows; ++mb_r) {
for (int mb_c = 0; mb_c < mb_cols; ++mb_c) {
map[mb_r * mb_cols + mb_c] = CheckMb(current, previous, mb_r, mb_c);
}
}
}
const int kAqModeCyclicRefresh = 3;
class ActiveMapRefreshTest
: public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
protected:
ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {}
virtual ~ActiveMapRefreshTest() {}
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
cpu_used_ = GET_PARAM(2);
}
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
::libvpx_test::Y4mVideoSource *y4m_video =
static_cast<libvpx_test::Y4mVideoSource *>(video);
if (video->frame() == 1) {
encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
encoder->Control(VP9E_SET_AQ_MODE, kAqModeCyclicRefresh);
} else if (video->frame() >= 2 && video->img()) {
vpx_image_t *current = video->img();
vpx_image_t *previous = y4m_holder_->img();
ASSERT_TRUE(previous != NULL);
vpx_active_map_t map = vpx_active_map_t();
const int width = static_cast<int>(current->d_w);
const int height = static_cast<int>(current->d_h);
const int mb_width = (width + 15) / 16;
const int mb_height = (height + 15) / 16;
uint8_t *active_map = new uint8_t[mb_width * mb_height];
GenerateMap(mb_height, mb_width, *current, *previous, active_map);
map.cols = mb_width;
map.rows = mb_height;
map.active_map = active_map;
encoder->Control(VP8E_SET_ACTIVEMAP, &map);
delete[] active_map;
}
if (video->img()) {
y4m_video->SwapBuffers(y4m_holder_);
}
}
int cpu_used_;
::libvpx_test::Y4mVideoSource *y4m_holder_;
};
TEST_P(ActiveMapRefreshTest, Test) {
cfg_.g_lag_in_frames = 0;
cfg_.g_profile = 1;
cfg_.rc_target_bitrate = 600;
cfg_.rc_resize_allowed = 0;
cfg_.rc_min_quantizer = 8;
cfg_.rc_max_quantizer = 30;
cfg_.g_pass = VPX_RC_ONE_PASS;
cfg_.rc_end_usage = VPX_CBR;
cfg_.kf_max_dist = 90000;
::libvpx_test::Y4mVideoSource video("desktop_credits.y4m", 0, 30);
::libvpx_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 30);
video_holder.Begin();
y4m_holder_ = &video_holder;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
VP9_INSTANTIATE_TEST_CASE(ActiveMapRefreshTest,
::testing::Values(::libvpx_test::kRealTime),
::testing::Range(5, 6));
} // namespace

View File

@@ -960,72 +960,511 @@ TEST_P(ConvolveTest, CheckScalingFiltering) {
using std::tr1::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH
#define WRAP(func, bd) \
void wrap_ ## func ## _ ## bd(const uint8_t *src, ptrdiff_t src_stride, \
uint8_t *dst, ptrdiff_t dst_stride, \
const int16_t *filter_x, \
int filter_x_stride, \
const int16_t *filter_y, \
int filter_y_stride, \
int w, int h) { \
vpx_highbd_ ## func(src, src_stride, dst, dst_stride, filter_x, \
filter_x_stride, filter_y, filter_y_stride, \
w, h, bd); \
}
#if HAVE_SSE2 && ARCH_X86_64
#if CONFIG_USE_X86INC
WRAP(convolve_copy_sse2, 8)
WRAP(convolve_avg_sse2, 8)
WRAP(convolve_copy_sse2, 10)
WRAP(convolve_avg_sse2, 10)
WRAP(convolve_copy_sse2, 12)
WRAP(convolve_avg_sse2, 12)
#endif // CONFIG_USE_X86INC
WRAP(convolve8_horiz_sse2, 8)
WRAP(convolve8_avg_horiz_sse2, 8)
WRAP(convolve8_vert_sse2, 8)
WRAP(convolve8_avg_vert_sse2, 8)
WRAP(convolve8_sse2, 8)
WRAP(convolve8_avg_sse2, 8)
WRAP(convolve8_horiz_sse2, 10)
WRAP(convolve8_avg_horiz_sse2, 10)
WRAP(convolve8_vert_sse2, 10)
WRAP(convolve8_avg_vert_sse2, 10)
WRAP(convolve8_sse2, 10)
WRAP(convolve8_avg_sse2, 10)
WRAP(convolve8_horiz_sse2, 12)
WRAP(convolve8_avg_horiz_sse2, 12)
WRAP(convolve8_vert_sse2, 12)
WRAP(convolve8_avg_vert_sse2, 12)
WRAP(convolve8_sse2, 12)
WRAP(convolve8_avg_sse2, 12)
void wrap_convolve8_horiz_sse2_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_horiz_sse2(src, src_stride, dst, dst_stride, filter_x,
filter_x_stride, filter_y, filter_y_stride,
w, h, 8);
}
void wrap_convolve8_avg_horiz_sse2_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_horiz_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_vert_sse2_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_vert_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_avg_vert_sse2_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_vert_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_sse2_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_avg_sse2_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_horiz_sse2_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_horiz_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_avg_horiz_sse2_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_horiz_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_vert_sse2_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_vert_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_avg_vert_sse2_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_vert_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_sse2_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_avg_sse2_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_horiz_sse2_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_horiz_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_avg_horiz_sse2_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_horiz_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_vert_sse2_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_vert_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_avg_vert_sse2_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_vert_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_sse2_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_avg_sse2_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_sse2(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
#endif // HAVE_SSE2 && ARCH_X86_64
WRAP(convolve_copy_c, 8)
WRAP(convolve_avg_c, 8)
WRAP(convolve8_horiz_c, 8)
WRAP(convolve8_avg_horiz_c, 8)
WRAP(convolve8_vert_c, 8)
WRAP(convolve8_avg_vert_c, 8)
WRAP(convolve8_c, 8)
WRAP(convolve8_avg_c, 8)
WRAP(convolve_copy_c, 10)
WRAP(convolve_avg_c, 10)
WRAP(convolve8_horiz_c, 10)
WRAP(convolve8_avg_horiz_c, 10)
WRAP(convolve8_vert_c, 10)
WRAP(convolve8_avg_vert_c, 10)
WRAP(convolve8_c, 10)
WRAP(convolve8_avg_c, 10)
WRAP(convolve_copy_c, 12)
WRAP(convolve_avg_c, 12)
WRAP(convolve8_horiz_c, 12)
WRAP(convolve8_avg_horiz_c, 12)
WRAP(convolve8_vert_c, 12)
WRAP(convolve8_avg_vert_c, 12)
WRAP(convolve8_c, 12)
WRAP(convolve8_avg_c, 12)
#undef WRAP
void wrap_convolve_copy_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve_copy_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve_avg_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve_avg_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_horiz_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_horiz_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_avg_horiz_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_horiz_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_vert_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_vert_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_avg_vert_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_vert_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve8_avg_c_8(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 8);
}
void wrap_convolve_copy_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve_copy_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve_avg_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve_avg_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_horiz_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_horiz_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_avg_horiz_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_horiz_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_vert_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_vert_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_avg_vert_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_vert_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve8_avg_c_10(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 10);
}
void wrap_convolve_copy_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve_copy_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve_avg_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve_avg_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_horiz_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_horiz_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_avg_horiz_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_horiz_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_vert_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_vert_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_avg_vert_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_vert_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
void wrap_convolve8_avg_c_12(const uint8_t *src, ptrdiff_t src_stride,
uint8_t *dst, ptrdiff_t dst_stride,
const int16_t *filter_x,
int filter_x_stride,
const int16_t *filter_y,
int filter_y_stride,
int w, int h) {
vpx_highbd_convolve8_avg_c(src, src_stride, dst, dst_stride,
filter_x, filter_x_stride,
filter_y, filter_y_stride, w, h, 12);
}
const ConvolveFunctions convolve8_c(
wrap_convolve_copy_c_8, wrap_convolve_avg_c_8,
@@ -1124,11 +1563,7 @@ INSTANTIATE_TEST_CASE_P(C, ConvolveTest, ::testing::Values(
#if HAVE_SSE2 && ARCH_X86_64
#if CONFIG_VP9_HIGHBITDEPTH
const ConvolveFunctions convolve8_sse2(
#if CONFIG_USE_X86INC
wrap_convolve_copy_sse2_8, wrap_convolve_avg_sse2_8,
#else
wrap_convolve_copy_c_8, wrap_convolve_avg_c_8,
#endif // CONFIG_USE_X86INC
wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8,
wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8,
wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8,
@@ -1136,11 +1571,7 @@ const ConvolveFunctions convolve8_sse2(
wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8,
wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8, 8);
const ConvolveFunctions convolve10_sse2(
#if CONFIG_USE_X86INC
wrap_convolve_copy_sse2_10, wrap_convolve_avg_sse2_10,
#else
wrap_convolve_copy_c_10, wrap_convolve_avg_c_10,
#endif // CONFIG_USE_X86INC
wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10,
wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10,
wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10,
@@ -1148,11 +1579,7 @@ const ConvolveFunctions convolve10_sse2(
wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10,
wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10, 10);
const ConvolveFunctions convolve12_sse2(
#if CONFIG_USE_X86INC
wrap_convolve_copy_sse2_12, wrap_convolve_avg_sse2_12,
#else
wrap_convolve_copy_c_12, wrap_convolve_avg_c_12,
#endif // CONFIG_USE_X86INC
wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12,
wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12,
wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12,

View File

@@ -124,11 +124,6 @@ class Encoder {
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
void Control(int ctrl_id, int *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
void Control(int ctrl_id, struct vpx_scaling_mode *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();

406
test/intrapred_test.cc Normal file
View File

@@ -0,0 +1,406 @@
/*
* 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.h>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "./vpx_config.h"
#include "./vp8_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "vp8/common/blockd.h"
#include "vpx_mem/vpx_mem.h"
namespace {
using libvpx_test::ACMRandom;
class IntraPredBase {
public:
virtual ~IntraPredBase() { libvpx_test::ClearSystemState(); }
protected:
void SetupMacroblock(MACROBLOCKD *mbptr,
MODE_INFO *miptr,
uint8_t *data,
int block_size,
int stride,
int num_planes) {
mbptr_ = mbptr;
miptr_ = miptr;
mbptr_->up_available = 1;
mbptr_->left_available = 1;
mbptr_->mode_info_context = miptr_;
stride_ = stride;
block_size_ = block_size;
num_planes_ = num_planes;
for (int p = 0; p < num_planes; p++)
data_ptr_[p] = data + stride * (block_size + 1) * p +
stride + block_size;
}
void FillRandom() {
// Fill edges with random data
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int p = 0; p < num_planes_; p++) {
for (int x = -1 ; x <= block_size_; x++)
data_ptr_[p][x - stride_] = rnd.Rand8();
for (int y = 0; y < block_size_; y++)
data_ptr_[p][y * stride_ - 1] = rnd.Rand8();
}
}
virtual void Predict(MB_PREDICTION_MODE mode) = 0;
void SetLeftUnavailable() {
mbptr_->left_available = 0;
for (int p = 0; p < num_planes_; p++)
for (int i = -1; i < block_size_; ++i)
data_ptr_[p][stride_ * i - 1] = 129;
}
void SetTopUnavailable() {
mbptr_->up_available = 0;
for (int p = 0; p < num_planes_; p++)
memset(&data_ptr_[p][-1 - stride_], 127, block_size_ + 2);
}
void SetTopLeftUnavailable() {
SetLeftUnavailable();
SetTopUnavailable();
}
int BlockSizeLog2Min1() const {
switch (block_size_) {
case 16:
return 3;
case 8:
return 2;
default:
return 0;
}
}
// check DC prediction output against a reference
void CheckDCPrediction() const {
for (int p = 0; p < num_planes_; p++) {
// calculate expected DC
int expected;
if (mbptr_->up_available || mbptr_->left_available) {
int sum = 0, shift = BlockSizeLog2Min1() + mbptr_->up_available +
mbptr_->left_available;
if (mbptr_->up_available)
for (int x = 0; x < block_size_; x++)
sum += data_ptr_[p][x - stride_];
if (mbptr_->left_available)
for (int y = 0; y < block_size_; y++)
sum += data_ptr_[p][y * stride_ - 1];
expected = (sum + (1 << (shift - 1))) >> shift;
} else {
expected = 0x80;
}
// check that all subsequent lines are equal to the first
for (int y = 1; y < block_size_; ++y)
ASSERT_EQ(0, memcmp(data_ptr_[p], &data_ptr_[p][y * stride_],
block_size_));
// within the first line, ensure that each pixel has the same value
for (int x = 1; x < block_size_; ++x)
ASSERT_EQ(data_ptr_[p][0], data_ptr_[p][x]);
// now ensure that that pixel has the expected (DC) value
ASSERT_EQ(expected, data_ptr_[p][0]);
}
}
// check V prediction output against a reference
void CheckVPrediction() const {
// check that all lines equal the top border
for (int p = 0; p < num_planes_; p++)
for (int y = 0; y < block_size_; y++)
ASSERT_EQ(0, memcmp(&data_ptr_[p][-stride_],
&data_ptr_[p][y * stride_], block_size_));
}
// check H prediction output against a reference
void CheckHPrediction() const {
// for each line, ensure that each pixel is equal to the left border
for (int p = 0; p < num_planes_; p++)
for (int y = 0; y < block_size_; y++)
for (int x = 0; x < block_size_; x++)
ASSERT_EQ(data_ptr_[p][-1 + y * stride_],
data_ptr_[p][x + y * stride_]);
}
static int ClipByte(int value) {
if (value > 255)
return 255;
else if (value < 0)
return 0;
return value;
}
// check TM prediction output against a reference
void CheckTMPrediction() const {
for (int p = 0; p < num_planes_; p++)
for (int y = 0; y < block_size_; y++)
for (int x = 0; x < block_size_; x++) {
const int expected = ClipByte(data_ptr_[p][x - stride_]
+ data_ptr_[p][stride_ * y - 1]
- data_ptr_[p][-1 - stride_]);
ASSERT_EQ(expected, data_ptr_[p][y * stride_ + x]);
}
}
// Actual test
void RunTest() {
{
SCOPED_TRACE("DC_PRED");
FillRandom();
Predict(DC_PRED);
CheckDCPrediction();
}
{
SCOPED_TRACE("DC_PRED LEFT");
FillRandom();
SetLeftUnavailable();
Predict(DC_PRED);
CheckDCPrediction();
}
{
SCOPED_TRACE("DC_PRED TOP");
FillRandom();
SetTopUnavailable();
Predict(DC_PRED);
CheckDCPrediction();
}
{
SCOPED_TRACE("DC_PRED TOP_LEFT");
FillRandom();
SetTopLeftUnavailable();
Predict(DC_PRED);
CheckDCPrediction();
}
{
SCOPED_TRACE("H_PRED");
FillRandom();
Predict(H_PRED);
CheckHPrediction();
}
{
SCOPED_TRACE("V_PRED");
FillRandom();
Predict(V_PRED);
CheckVPrediction();
}
{
SCOPED_TRACE("TM_PRED");
FillRandom();
Predict(TM_PRED);
CheckTMPrediction();
}
}
MACROBLOCKD *mbptr_;
MODE_INFO *miptr_;
uint8_t *data_ptr_[2]; // in the case of Y, only [0] is used
int stride_;
int block_size_;
int num_planes_;
};
typedef void (*IntraPredYFunc)(MACROBLOCKD *x,
uint8_t *yabove_row,
uint8_t *yleft,
int left_stride,
uint8_t *ypred_ptr,
int y_stride);
class IntraPredYTest
: public IntraPredBase,
public ::testing::TestWithParam<IntraPredYFunc> {
public:
static void SetUpTestCase() {
mb_ = reinterpret_cast<MACROBLOCKD*>(
vpx_memalign(32, sizeof(MACROBLOCKD)));
mi_ = reinterpret_cast<MODE_INFO*>(
vpx_memalign(32, sizeof(MODE_INFO)));
data_array_ = reinterpret_cast<uint8_t*>(
vpx_memalign(kDataAlignment, kDataBufferSize));
}
static void TearDownTestCase() {
vpx_free(data_array_);
vpx_free(mi_);
vpx_free(mb_);
data_array_ = NULL;
}
protected:
static const int kBlockSize = 16;
static const int kDataAlignment = 16;
static const int kStride = kBlockSize * 3;
// We use 48 so that the data pointer of the first pixel in each row of
// each macroblock is 16-byte aligned, and this gives us access to the
// top-left and top-right corner pixels belonging to the top-left/right
// macroblocks.
// We use 17 lines so we have one line above us for top-prediction.
static const int kDataBufferSize = kStride * (kBlockSize + 1);
virtual void SetUp() {
pred_fn_ = GetParam();
SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 1);
}
virtual void Predict(MB_PREDICTION_MODE mode) {
mbptr_->mode_info_context->mbmi.mode = mode;
ASM_REGISTER_STATE_CHECK(pred_fn_(mbptr_,
data_ptr_[0] - kStride,
data_ptr_[0] - 1, kStride,
data_ptr_[0], kStride));
}
IntraPredYFunc pred_fn_;
static uint8_t* data_array_;
static MACROBLOCKD * mb_;
static MODE_INFO *mi_;
};
MACROBLOCKD* IntraPredYTest::mb_ = NULL;
MODE_INFO* IntraPredYTest::mi_ = NULL;
uint8_t* IntraPredYTest::data_array_ = NULL;
TEST_P(IntraPredYTest, IntraPredTests) {
RunTest();
}
INSTANTIATE_TEST_CASE_P(C, IntraPredYTest,
::testing::Values(
vp8_build_intra_predictors_mby_s_c));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, IntraPredYTest,
::testing::Values(
vp8_build_intra_predictors_mby_s_sse2));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredYTest,
::testing::Values(
vp8_build_intra_predictors_mby_s_ssse3));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, IntraPredYTest,
::testing::Values(
vp8_build_intra_predictors_mby_s_neon));
#endif
#if HAVE_MSA
INSTANTIATE_TEST_CASE_P(MSA, IntraPredYTest,
::testing::Values(
vp8_build_intra_predictors_mby_s_msa));
#endif
typedef void (*IntraPredUvFunc)(MACROBLOCKD *x,
uint8_t *uabove_row,
uint8_t *vabove_row,
uint8_t *uleft,
uint8_t *vleft,
int left_stride,
uint8_t *upred_ptr,
uint8_t *vpred_ptr,
int pred_stride);
class IntraPredUVTest
: public IntraPredBase,
public ::testing::TestWithParam<IntraPredUvFunc> {
public:
static void SetUpTestCase() {
mb_ = reinterpret_cast<MACROBLOCKD*>(
vpx_memalign(32, sizeof(MACROBLOCKD)));
mi_ = reinterpret_cast<MODE_INFO*>(
vpx_memalign(32, sizeof(MODE_INFO)));
data_array_ = reinterpret_cast<uint8_t*>(
vpx_memalign(kDataAlignment, kDataBufferSize));
}
static void TearDownTestCase() {
vpx_free(data_array_);
vpx_free(mi_);
vpx_free(mb_);
data_array_ = NULL;
}
protected:
static const int kBlockSize = 8;
static const int kDataAlignment = 8;
static const int kStride = kBlockSize * 3;
// We use 24 so that the data pointer of the first pixel in each row of
// each macroblock is 8-byte aligned, and this gives us access to the
// top-left and top-right corner pixels belonging to the top-left/right
// macroblocks.
// We use 9 lines so we have one line above us for top-prediction.
// [0] = U, [1] = V
static const int kDataBufferSize = 2 * kStride * (kBlockSize + 1);
virtual void SetUp() {
pred_fn_ = GetParam();
SetupMacroblock(mb_, mi_, data_array_, kBlockSize, kStride, 2);
}
virtual void Predict(MB_PREDICTION_MODE mode) {
mbptr_->mode_info_context->mbmi.uv_mode = mode;
pred_fn_(mbptr_, data_ptr_[0] - kStride, data_ptr_[1] - kStride,
data_ptr_[0] - 1, data_ptr_[1] - 1, kStride,
data_ptr_[0], data_ptr_[1], kStride);
}
IntraPredUvFunc pred_fn_;
// We use 24 so that the data pointer of the first pixel in each row of
// each macroblock is 8-byte aligned, and this gives us access to the
// top-left and top-right corner pixels belonging to the top-left/right
// macroblocks.
// We use 9 lines so we have one line above us for top-prediction.
// [0] = U, [1] = V
static uint8_t* data_array_;
static MACROBLOCKD* mb_;
static MODE_INFO* mi_;
};
MACROBLOCKD* IntraPredUVTest::mb_ = NULL;
MODE_INFO* IntraPredUVTest::mi_ = NULL;
uint8_t* IntraPredUVTest::data_array_ = NULL;
TEST_P(IntraPredUVTest, IntraPredTests) {
RunTest();
}
INSTANTIATE_TEST_CASE_P(C, IntraPredUVTest,
::testing::Values(
vp8_build_intra_predictors_mbuv_s_c));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, IntraPredUVTest,
::testing::Values(
vp8_build_intra_predictors_mbuv_s_sse2));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, IntraPredUVTest,
::testing::Values(
vp8_build_intra_predictors_mbuv_s_ssse3));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, IntraPredUVTest,
::testing::Values(
vp8_build_intra_predictors_mbuv_s_neon));
#endif
#if HAVE_MSA
INSTANTIATE_TEST_CASE_P(MSA, IntraPredUVTest,
::testing::Values(
vp8_build_intra_predictors_mbuv_s_msa));
#endif
} // namespace

View File

@@ -63,22 +63,9 @@ class InvalidFileTest
EXPECT_NE(res, EOF) << "Read result data failed";
// Check results match.
const DecodeParam input = GET_PARAM(1);
if (input.threads > 1) {
// The serial decode check is too strict for tile-threaded decoding as
// there is no guarantee on the decode order nor which specific error
// will take precedence. Currently a tile-level error is not forwarded so
// the frame will simply be marked corrupt.
EXPECT_TRUE(res_dec == expected_res_dec ||
res_dec == VPX_CODEC_CORRUPT_FRAME)
<< "Results don't match: frame number = " << video.frame_number()
<< ". (" << decoder->DecodeError() << "). Expected: "
<< expected_res_dec << " or " << VPX_CODEC_CORRUPT_FRAME;
} else {
EXPECT_EQ(expected_res_dec, res_dec)
<< "Results don't match: frame number = " << video.frame_number()
<< ". (" << decoder->DecodeError() << ")";
}
EXPECT_EQ(expected_res_dec, res_dec)
<< "Results don't match: frame number = " << video.frame_number()
<< ". (" << decoder->DecodeError() << ")";
return !HasFailure();
}

View File

@@ -30,9 +30,7 @@
#if defined(_WIN64)
#undef NOMINMAX
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#define _WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winnt.h>

View File

@@ -81,15 +81,6 @@ static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt,
const unsigned int kInitialWidth = 320;
const unsigned int kInitialHeight = 240;
struct FrameInfo {
FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
: pts(_pts), w(_w), h(_h) {}
vpx_codec_pts_t pts;
unsigned int w;
unsigned int h;
};
unsigned int ScaleForFrameNumber(unsigned int frame, unsigned int val) {
if (frame < 10)
return val;
@@ -129,6 +120,15 @@ class ResizeTest : public ::libvpx_test::EncoderTest,
virtual ~ResizeTest() {}
struct FrameInfo {
FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
: pts(_pts), w(_w), h(_h) {}
vpx_codec_pts_t pts;
unsigned int w;
unsigned int h;
};
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
@@ -196,27 +196,13 @@ class ResizeInternalTest : public ResizeTest {
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
libvpx_test::Encoder *encoder) {
if (change_config_) {
int new_q = 60;
if (video->frame() == 0) {
struct vpx_scaling_mode mode = {VP8E_ONETWO, VP8E_ONETWO};
encoder->Control(VP8E_SET_SCALEMODE, &mode);
}
if (video->frame() == 1) {
struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
encoder->Control(VP8E_SET_SCALEMODE, &mode);
cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
encoder->Config(&cfg_);
}
} else {
if (video->frame() == kStepDownFrame) {
struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE};
encoder->Control(VP8E_SET_SCALEMODE, &mode);
}
if (video->frame() == kStepUpFrame) {
struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
encoder->Control(VP8E_SET_SCALEMODE, &mode);
}
if (video->frame() == kStepDownFrame) {
struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE};
encoder->Control(VP8E_SET_SCALEMODE, &mode);
}
if (video->frame() == kStepUpFrame) {
struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
encoder->Control(VP8E_SET_SCALEMODE, &mode);
}
}
@@ -241,7 +227,6 @@ class ResizeInternalTest : public ResizeTest {
#endif
double frame0_psnr_;
bool change_config_;
#if WRITE_COMPRESSED_STREAM
FILE *outfile_;
unsigned int out_frames_;
@@ -252,7 +237,6 @@ TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 10);
init_flags_ = VPX_CODEC_USE_PSNR;
change_config_ = false;
// q picked such that initial keyframe on this clip is ~30dB PSNR
cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
@@ -277,143 +261,6 @@ TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
}
}
TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) {
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 10);
cfg_.g_w = 352;
cfg_.g_h = 288;
change_config_ = true;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
class ResizeInternalRealtimeTest : public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
protected:
ResizeInternalRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
virtual ~ResizeInternalRealtimeTest() {}
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
libvpx_test::Encoder *encoder) {
if (video->frame() == 0) {
encoder->Control(VP9E_SET_AQ_MODE, 3);
encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
}
if (change_bitrate_ && video->frame() == 120) {
change_bitrate_ = false;
cfg_.rc_target_bitrate = 500;
encoder->Config(&cfg_);
}
}
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
set_cpu_used_ = GET_PARAM(2);
}
virtual void DecompressedFrameHook(const vpx_image_t &img,
vpx_codec_pts_t pts) {
frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
}
void DefaultConfig() {
cfg_.g_w = 352;
cfg_.g_h = 288;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 600;
cfg_.rc_buf_sz = 1000;
cfg_.rc_min_quantizer = 2;
cfg_.rc_max_quantizer = 56;
cfg_.rc_undershoot_pct = 50;
cfg_.rc_overshoot_pct = 50;
cfg_.rc_end_usage = VPX_CBR;
cfg_.kf_mode = VPX_KF_AUTO;
cfg_.g_lag_in_frames = 0;
cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
// Enable dropped frames.
cfg_.rc_dropframe_thresh = 1;
// Enable error_resilience mode.
cfg_.g_error_resilient = 1;
// Enable dynamic resizing.
cfg_.rc_resize_allowed = 1;
// Run at low bitrate.
cfg_.rc_target_bitrate = 200;
}
std::vector< FrameInfo > frame_info_list_;
int set_cpu_used_;
bool change_bitrate_;
};
// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
// Run at low bitrate, with resize_allowed = 1, and verify that we get
// one resize down event.
TEST_P(ResizeInternalRealtimeTest, TestInternalResizeDown) {
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 299);
DefaultConfig();
change_bitrate_ = false;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
unsigned int last_w = cfg_.g_w;
unsigned int last_h = cfg_.g_h;
int resize_count = 0;
for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) {
if (info->w != last_w || info->h != last_h) {
// Verify that resize down occurs.
ASSERT_LT(info->w, last_w);
ASSERT_LT(info->h, last_h);
last_w = info->w;
last_h = info->h;
resize_count++;
}
}
// Verify that we get 1 resize down event in this test.
ASSERT_EQ(1, resize_count) << "Resizing should occur.";
}
// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
// Start at low target bitrate, raise the bitrate in the middle of the clip,
// scaling-up should occur after bitrate changed.
TEST_P(ResizeInternalRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 299);
DefaultConfig();
change_bitrate_ = true;
// Disable dropped frames.
cfg_.rc_dropframe_thresh = 0;
// Starting bitrate low.
cfg_.rc_target_bitrate = 100;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
unsigned int last_w = cfg_.g_w;
unsigned int last_h = cfg_.g_h;
int resize_count = 0;
for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) {
if (info->w != last_w || info->h != last_h) {
resize_count++;
if (resize_count == 1) {
// Verify that resize down occurs.
ASSERT_LT(info->w, last_w);
ASSERT_LT(info->h, last_h);
} else if (resize_count == 2) {
// Verify that resize up occurs.
ASSERT_GT(info->w, last_w);
ASSERT_GT(info->h, last_h);
}
last_w = info->w;
last_h = info->h;
}
}
// Verify that we get 2 resize events in this test.
ASSERT_EQ(2, resize_count) << "Resizing should occur twice.";
}
vpx_img_fmt_t CspForFrameNumber(int frame) {
if (frame < 10)
return VPX_IMG_FMT_I420;
@@ -524,9 +371,6 @@ VP9_INSTANTIATE_TEST_CASE(ResizeTest,
::testing::Values(::libvpx_test::kRealTime));
VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest,
::testing::Values(::libvpx_test::kOnePassBest));
VP9_INSTANTIATE_TEST_CASE(ResizeInternalRealtimeTest,
::testing::Values(::libvpx_test::kRealTime),
::testing::Range(5, 9));
VP9_INSTANTIATE_TEST_CASE(ResizeCspTest,
::testing::Values(::libvpx_test::kRealTime));
} // namespace

View File

@@ -201,7 +201,7 @@ const SixtapPredictFunc sixtap_16x16_neon = vp8_sixtap_predict16x16_neon;
const SixtapPredictFunc sixtap_8x8_neon = vp8_sixtap_predict8x8_neon;
const SixtapPredictFunc sixtap_8x4_neon = vp8_sixtap_predict8x4_neon;
INSTANTIATE_TEST_CASE_P(
NEON, SixtapPredictTest, ::testing::Values(
DISABLED_NEON, SixtapPredictTest, ::testing::Values(
make_tuple(16, 16, sixtap_16x16_neon),
make_tuple(8, 8, sixtap_8x8_neon),
make_tuple(8, 4, sixtap_8x4_neon)));

View File

@@ -16,13 +16,8 @@
namespace {
const int kTestMode = 0;
const int kSuperframeSyntax = 1;
typedef std::tr1::tuple<libvpx_test::TestMode,int> SuperframeTestParam;
class SuperframeTest : public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWithParam<SuperframeTestParam> {
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
protected:
SuperframeTest() : EncoderTest(GET_PARAM(0)), modified_buf_(NULL),
last_sf_pts_(0) {}
@@ -30,13 +25,9 @@ class SuperframeTest : public ::libvpx_test::EncoderTest,
virtual void SetUp() {
InitializeConfig();
const SuperframeTestParam input = GET_PARAM(1);
const libvpx_test::TestMode mode = std::tr1::get<kTestMode>(input);
const int syntax = std::tr1::get<kSuperframeSyntax>(input);
SetMode(mode);
SetMode(GET_PARAM(1));
sf_count_ = 0;
sf_count_max_ = INT_MAX;
is_vp10_style_superframe_ = syntax;
}
virtual void TearDown() {
@@ -59,8 +50,7 @@ class SuperframeTest : public ::libvpx_test::EncoderTest,
const uint8_t marker = buffer[pkt->data.frame.sz - 1];
const int frames = (marker & 0x7) + 1;
const int mag = ((marker >> 3) & 3) + 1;
const unsigned int index_sz =
2 + mag * (frames - is_vp10_style_superframe_);
const unsigned int index_sz = 2 + mag * frames;
if ((marker & 0xe0) == 0xc0 &&
pkt->data.frame.sz >= index_sz &&
buffer[pkt->data.frame.sz - index_sz] == marker) {
@@ -85,7 +75,6 @@ class SuperframeTest : public ::libvpx_test::EncoderTest,
return pkt;
}
int is_vp10_style_superframe_;
int sf_count_;
int sf_count_max_;
vpx_codec_cx_pkt_t modified_pkt_;
@@ -103,11 +92,9 @@ TEST_P(SuperframeTest, TestSuperframeIndexIsOptional) {
EXPECT_EQ(sf_count_, 1);
}
VP9_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Combine(
::testing::Values(::libvpx_test::kTwoPassGood),
::testing::Values(0)));
VP9_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Values(
::libvpx_test::kTwoPassGood));
VP10_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Combine(
::testing::Values(::libvpx_test::kTwoPassGood),
::testing::Values(CONFIG_MISC_FIXES)));
VP10_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Values(
::libvpx_test::kTwoPassGood));
} // namespace

View File

@@ -18,7 +18,6 @@ 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_ENCODERS) += park_joy_90p_8_440.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_credits.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m

View File

@@ -743,4 +743,3 @@ d06285d109ecbaef63b0cbcc44d70a129186f51c *invalid-vp90-2-03-size-224x196.webm.iv
e60d859b0ef2b331b21740cf6cb83fabe469b079 *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf
0ae808dca4d3c1152a9576e14830b6faa39f1b4a *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res
9cfc855459e7549fd015c79e8eca512b2f2cb7e3 *niklas_1280_720_30.y4m
5b5763b388b1b52a81bb82b39f7ec25c4bd3d0e1 *desktop_credits.y4m

View File

@@ -36,7 +36,6 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += invalid_file_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += user_priv_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_frame_parallel_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_refresh_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += borders_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += cpu_speed_test.cc
@@ -111,6 +110,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += quantize_test.cc
LIBVPX_TEST_SRCS-yes += idct_test.cc
LIBVPX_TEST_SRCS-yes += intrapred_test.cc
LIBVPX_TEST_SRCS-yes += sixtap_predict_test.cc
LIBVPX_TEST_SRCS-yes += vpx_scale_test.cc
@@ -167,10 +167,6 @@ LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sad_test.cc
TEST_INTRA_PRED_SPEED_SRCS-$(CONFIG_VP9) := test_intra_pred_speed.cc
TEST_INTRA_PRED_SPEED_SRCS-$(CONFIG_VP9) += ../md5_utils.h ../md5_utils.c
## VP10
LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += vp10_dct_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP10) += vp10_inv_txfm_test.cc
endif # CONFIG_SHARED
include $(SRC_PATH_BARE)/test/test-data.mk

View File

@@ -11,9 +11,6 @@
#define TEST_VIDEO_SOURCE_H_
#if defined(_WIN32)
#undef NOMINMAX
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <cstdio>

View File

@@ -1,111 +0,0 @@
/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include <stdlib.h>
#include <new>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "./vpx_config.h"
#include "vpx_ports/msvc.h"
#undef CONFIG_COEFFICIENT_RANGE_CHECKING
#define CONFIG_COEFFICIENT_RANGE_CHECKING 1
#include "vp10/encoder/dct.c"
using libvpx_test::ACMRandom;
namespace {
void reference_dct_1d(const double *in, double *out, int size) {
const double PI = 3.141592653589793238462643383279502884;
const double kInvSqrt2 = 0.707106781186547524400844362104;
for (int k = 0; k < size; ++k) {
out[k] = 0;
for (int n = 0; n < size; ++n) {
out[k] += in[n] * cos(PI * (2 * n + 1) * k / (2 * size));
}
if (k == 0)
out[k] = out[k] * kInvSqrt2;
}
}
typedef void (*FdctFuncRef)(const double *in, double *out, int size);
typedef void (*IdctFuncRef)(const double *in, double *out, int size);
typedef void (*FdctFunc)(const tran_low_t *in, tran_low_t *out);
typedef void (*IdctFunc)(const tran_low_t *in, tran_low_t *out);
class TransTestBase {
public:
virtual ~TransTestBase() {}
protected:
void RunFwdAccuracyCheck() {
tran_low_t *input = new tran_low_t[txfm_size_];
tran_low_t *output = new tran_low_t[txfm_size_];
double *ref_input = new double[txfm_size_];
double *ref_output = new double[txfm_size_];
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int count_test_block = 5000;
for (int ti = 0; ti < count_test_block; ++ti) {
for (int ni = 0; ni < txfm_size_; ++ni) {
input[ni] = rnd.Rand8() - rnd.Rand8();
ref_input[ni] = static_cast<double>(input[ni]);
}
fwd_txfm_(input, output);
fwd_txfm_ref_(ref_input, ref_output, txfm_size_);
for (int ni = 0; ni < txfm_size_; ++ni) {
EXPECT_LE(
abs(output[ni] - static_cast<tran_low_t>(round(ref_output[ni]))),
max_error_);
}
}
delete[] input;
delete[] output;
delete[] ref_input;
delete[] ref_output;
}
double max_error_;
int txfm_size_;
FdctFunc fwd_txfm_;
FdctFuncRef fwd_txfm_ref_;
};
typedef std::tr1::tuple<FdctFunc, FdctFuncRef, int, int> FdctParam;
class Vp10FwdTxfm
: public TransTestBase,
public ::testing::TestWithParam<FdctParam> {
public:
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = GET_PARAM(1);
txfm_size_ = GET_PARAM(2);
max_error_ = GET_PARAM(3);
}
virtual void TearDown() {}
};
TEST_P(Vp10FwdTxfm, RunFwdAccuracyCheck) {
RunFwdAccuracyCheck();
}
INSTANTIATE_TEST_CASE_P(
C, Vp10FwdTxfm,
::testing::Values(
FdctParam(&fdct4, &reference_dct_1d, 4, 1),
FdctParam(&fdct8, &reference_dct_1d, 8, 1),
FdctParam(&fdct16, &reference_dct_1d, 16, 2)));
} // namespace

View File

@@ -1,321 +0,0 @@
/*
* Copyright (c) 2013 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "./vp10_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "vp10/common/blockd.h"
#include "vp10/common/scan.h"
#include "vpx/vpx_integer.h"
#include "vp10/common/vp10_inv_txfm.h"
using libvpx_test::ACMRandom;
namespace {
const double PI = 3.141592653589793238462643383279502884;
const double kInvSqrt2 = 0.707106781186547524400844362104;
void reference_idct_1d(const double *in, double *out, int size) {
for (int n = 0; n < size; ++n) {
out[n] = 0;
for (int k = 0; k < size; ++k) {
if (k == 0)
out[n] += kInvSqrt2 * in[k] * cos(PI * (2 * n + 1) * k / (2 * size));
else
out[n] += in[k] * cos(PI * (2 * n + 1) * k / (2 * size));
}
}
}
typedef void (*IdctFuncRef)(const double *in, double *out, int size);
typedef void (*IdctFunc)(const tran_low_t *in, tran_low_t *out);
class TransTestBase {
public:
virtual ~TransTestBase() {}
protected:
void RunInvAccuracyCheck() {
tran_low_t *input = new tran_low_t[txfm_size_];
tran_low_t *output = new tran_low_t[txfm_size_];
double *ref_input = new double[txfm_size_];
double *ref_output = new double[txfm_size_];
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int count_test_block = 5000;
for (int ti = 0; ti < count_test_block; ++ti) {
for (int ni = 0; ni < txfm_size_; ++ni) {
input[ni] = rnd.Rand8() - rnd.Rand8();
ref_input[ni] = static_cast<double>(input[ni]);
}
fwd_txfm_(input, output);
fwd_txfm_ref_(ref_input, ref_output, txfm_size_);
for (int ni = 0; ni < txfm_size_; ++ni) {
EXPECT_LE(
abs(output[ni] - static_cast<tran_low_t>(round(ref_output[ni]))),
max_error_);
}
}
delete[] input;
delete[] output;
delete[] ref_input;
delete[] ref_output;
}
double max_error_;
int txfm_size_;
IdctFunc fwd_txfm_;
IdctFuncRef fwd_txfm_ref_;
};
typedef std::tr1::tuple<IdctFunc, IdctFuncRef, int, int> IdctParam;
class Vp10InvTxfm
: public TransTestBase,
public ::testing::TestWithParam<IdctParam> {
public:
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = GET_PARAM(1);
txfm_size_ = GET_PARAM(2);
max_error_ = GET_PARAM(3);
}
virtual void TearDown() {}
};
TEST_P(Vp10InvTxfm, RunInvAccuracyCheck) {
RunInvAccuracyCheck();
}
INSTANTIATE_TEST_CASE_P(
C, Vp10InvTxfm,
::testing::Values(
IdctParam(&vp10_idct4_c, &reference_idct_1d, 4, 1),
IdctParam(&vp10_idct8_c, &reference_idct_1d, 8, 2),
IdctParam(&vp10_idct16_c, &reference_idct_1d, 16, 4),
IdctParam(&vp10_idct32_c, &reference_idct_1d, 32, 6))
);
typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
typedef std::tr1::tuple<FwdTxfmFunc,
InvTxfmFunc,
InvTxfmFunc,
TX_SIZE, int> PartialInvTxfmParam;
const int kMaxNumCoeffs = 1024;
class Vp10PartialIDctTest
: public ::testing::TestWithParam<PartialInvTxfmParam> {
public:
virtual ~Vp10PartialIDctTest() {}
virtual void SetUp() {
ftxfm_ = GET_PARAM(0);
full_itxfm_ = GET_PARAM(1);
partial_itxfm_ = GET_PARAM(2);
tx_size_ = GET_PARAM(3);
last_nonzero_ = GET_PARAM(4);
}
virtual void TearDown() { libvpx_test::ClearSystemState(); }
protected:
int last_nonzero_;
TX_SIZE tx_size_;
FwdTxfmFunc ftxfm_;
InvTxfmFunc full_itxfm_;
InvTxfmFunc partial_itxfm_;
};
TEST_P(Vp10PartialIDctTest, RunQuantCheck) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int size;
switch (tx_size_) {
case TX_4X4:
size = 4;
break;
case TX_8X8:
size = 8;
break;
case TX_16X16:
size = 16;
break;
case TX_32X32:
size = 32;
break;
default:
FAIL() << "Wrong Size!";
break;
}
DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]);
const int count_test_block = 1000;
const int block_size = size * size;
DECLARE_ALIGNED(16, int16_t, input_extreme_block[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kMaxNumCoeffs]);
int max_error = 0;
for (int i = 0; i < count_test_block; ++i) {
// clear out destination buffer
memset(dst1, 0, sizeof(*dst1) * block_size);
memset(dst2, 0, sizeof(*dst2) * block_size);
memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int i = 0; i < count_test_block; ++i) {
// Initialize a test block with input range [-255, 255].
if (i == 0) {
for (int j = 0; j < block_size; ++j)
input_extreme_block[j] = 255;
} else if (i == 1) {
for (int j = 0; j < block_size; ++j)
input_extreme_block[j] = -255;
} else {
for (int j = 0; j < block_size; ++j) {
input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
}
}
ftxfm_(input_extreme_block, output_ref_block, size);
// quantization with maximum allowed step sizes
test_coef_block1[0] = (output_ref_block[0] / 1336) * 1336;
for (int j = 1; j < last_nonzero_; ++j)
test_coef_block1[vp10_default_scan_orders[tx_size_].scan[j]]
= (output_ref_block[j] / 1828) * 1828;
}
ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block1, dst2, size));
for (int j = 0; j < block_size; ++j) {
const int diff = dst1[j] - dst2[j];
const int error = diff * diff;
if (max_error < error)
max_error = error;
}
}
EXPECT_EQ(0, max_error)
<< "Error: partial inverse transform produces different results";
}
TEST_P(Vp10PartialIDctTest, ResultsMatch) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int size;
switch (tx_size_) {
case TX_4X4:
size = 4;
break;
case TX_8X8:
size = 8;
break;
case TX_16X16:
size = 16;
break;
case TX_32X32:
size = 32;
break;
default:
FAIL() << "Wrong Size!";
break;
}
DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]);
const int count_test_block = 1000;
const int max_coeff = 32766 / 4;
const int block_size = size * size;
int max_error = 0;
for (int i = 0; i < count_test_block; ++i) {
// clear out destination buffer
memset(dst1, 0, sizeof(*dst1) * block_size);
memset(dst2, 0, sizeof(*dst2) * block_size);
memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
int max_energy_leftover = max_coeff * max_coeff;
for (int j = 0; j < last_nonzero_; ++j) {
int16_t coef = static_cast<int16_t>(sqrt(1.0 * max_energy_leftover) *
(rnd.Rand16() - 32768) / 65536);
max_energy_leftover -= coef * coef;
if (max_energy_leftover < 0) {
max_energy_leftover = 0;
coef = 0;
}
test_coef_block1[vp10_default_scan_orders[tx_size_].scan[j]] = coef;
}
memcpy(test_coef_block2, test_coef_block1,
sizeof(*test_coef_block2) * block_size);
ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block2, dst2, size));
for (int j = 0; j < block_size; ++j) {
const int diff = dst1[j] - dst2[j];
const int error = diff * diff;
if (max_error < error)
max_error = error;
}
}
EXPECT_EQ(0, max_error)
<< "Error: partial inverse transform produces different results";
}
using std::tr1::make_tuple;
INSTANTIATE_TEST_CASE_P(
C, Vp10PartialIDctTest,
::testing::Values(
make_tuple(&vpx_fdct32x32_c,
&vp10_idct32x32_1024_add_c,
&vp10_idct32x32_34_add_c,
TX_32X32, 34),
make_tuple(&vpx_fdct32x32_c,
&vp10_idct32x32_1024_add_c,
&vp10_idct32x32_1_add_c,
TX_32X32, 1),
make_tuple(&vpx_fdct16x16_c,
&vp10_idct16x16_256_add_c,
&vp10_idct16x16_10_add_c,
TX_16X16, 10),
make_tuple(&vpx_fdct16x16_c,
&vp10_idct16x16_256_add_c,
&vp10_idct16x16_1_add_c,
TX_16X16, 1),
make_tuple(&vpx_fdct8x8_c,
&vp10_idct8x8_64_add_c,
&vp10_idct8x8_12_add_c,
TX_8X8, 12),
make_tuple(&vpx_fdct8x8_c,
&vp10_idct8x8_64_add_c,
&vp10_idct8x8_1_add_c,
TX_8X8, 1),
make_tuple(&vpx_fdct4x4_c,
&vp10_idct4x4_16_add_c,
&vp10_idct4x4_1_add_c,
TX_4X4, 1)));
} // namespace

View File

@@ -230,23 +230,9 @@ VP9_INSTANTIATE_TEST_CASE(
::testing::ValuesIn(kEncodeVectors),
::testing::ValuesIn(kMinArfVectors));
#if CONFIG_VP9_HIGHBITDEPTH
# if CONFIG_VP10_ENCODER
// TODO(angiebird): 25-29 fail in high bitdepth mode.
INSTANTIATE_TEST_CASE_P(
DISABLED_VP10, ArfFreqTest,
::testing::Combine(
::testing::Values(static_cast<const libvpx_test::CodecFactory *>(
&libvpx_test::kVP10)),
::testing::ValuesIn(kTestVectors),
::testing::ValuesIn(kEncodeVectors),
::testing::ValuesIn(kMinArfVectors)));
# endif // CONFIG_VP10_ENCODER
#else
VP10_INSTANTIATE_TEST_CASE(
ArfFreqTest,
::testing::ValuesIn(kTestVectors),
::testing::ValuesIn(kEncodeVectors),
::testing::ValuesIn(kMinArfVectors));
#endif // CONFIG_VP9_HIGHBITDEPTH
} // namespace

View File

@@ -14,10 +14,38 @@
#include "test/encode_test_driver.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "vp9/vp9_dx_iface.h"
#include "test/yuv_video_source.h"
#include "vp9/decoder/vp9_decoder.h"
typedef vpx_codec_stream_info_t vp9_stream_info_t;
struct vpx_codec_alg_priv {
vpx_codec_priv_t base;
vpx_codec_dec_cfg_t cfg;
vp9_stream_info_t si;
struct VP9Decoder *pbi;
int postproc_cfg_set;
vp8_postproc_cfg_t postproc_cfg;
vpx_decrypt_cb decrypt_cb;
void *decrypt_state;
vpx_image_t img;
int img_avail;
int flushed;
int invert_tile_order;
int frame_parallel_decode;
// 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;
vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
};
static vpx_codec_alg_priv_t *get_alg_priv(vpx_codec_ctx_t *ctx) {
return (vpx_codec_alg_priv_t *)ctx->priv;
}
namespace {
const unsigned int kFramerate = 50;
const int kCpuUsed = 2;
struct EncodePerfTestVideo {
@@ -38,27 +66,35 @@ struct EncodeParameters {
int32_t lossless;
int32_t error_resilient;
int32_t frame_parallel;
vpx_color_range_t color_range;
vpx_color_space_t cs;
int render_size[2];
// TODO(JBB): quantizers / bitrate
};
const EncodeParameters kVP9EncodeParameterSet[] = {
{0, 0, 0, 1, 0, VPX_CR_STUDIO_RANGE, VPX_CS_BT_601},
{0, 0, 0, 0, 0, VPX_CR_FULL_RANGE, VPX_CS_BT_709},
{0, 0, 1, 0, 0, VPX_CR_FULL_RANGE, VPX_CS_BT_2020},
{0, 2, 0, 0, 1, VPX_CR_STUDIO_RANGE, VPX_CS_UNKNOWN, { 640, 480 }},
// TODO(JBB): Test profiles (requires more work).
{0, 0, 0, 1, 0, VPX_CS_BT_601},
{0, 0, 0, 0, 0, VPX_CS_BT_709},
{0, 0, 1, 0, 0, VPX_CS_BT_2020},
{0, 2, 0, 0, 1, VPX_CS_UNKNOWN},
// TODO(JBB): Test profiles (requires more work).
};
int is_extension_y4m(const char *filename) {
const char *dot = strrchr(filename, '.');
if (!dot || dot == filename)
return 0;
else
return !strcmp(dot, ".y4m");
}
class VpxEncoderParmsGetToDecoder
: public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<EncodeParameters,
public ::libvpx_test::CodecTestWith2Params<EncodeParameters, \
EncodePerfTestVideo> {
protected:
VpxEncoderParmsGetToDecoder()
: EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {}
: EncoderTest(GET_PARAM(0)),
encode_parms(GET_PARAM(1)) {
}
virtual ~VpxEncoderParmsGetToDecoder() {}
@@ -76,7 +112,6 @@ class VpxEncoderParmsGetToDecoder
::libvpx_test::Encoder *encoder) {
if (video->frame() == 1) {
encoder->Control(VP9E_SET_COLOR_SPACE, encode_parms.cs);
encoder->Control(VP9E_SET_COLOR_RANGE, encode_parms.color_range);
encoder->Control(VP9E_SET_LOSSLESS, encode_parms.lossless);
encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
encode_parms.frame_parallel);
@@ -87,44 +122,37 @@ class VpxEncoderParmsGetToDecoder
encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
encoder->Control(VP8E_SET_ARNR_TYPE, 3);
if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0)
encoder->Control(VP9E_SET_RENDER_SIZE, encode_parms.render_size);
}
}
virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
const libvpx_test::VideoSource &video,
const libvpx_test::VideoSource& video,
libvpx_test::Decoder *decoder) {
vpx_codec_ctx_t *const vp9_decoder = decoder->GetDecoder();
vpx_codec_alg_priv_t *const priv =
reinterpret_cast<vpx_codec_alg_priv_t *>(vp9_decoder->priv);
FrameWorkerData *const worker_data =
reinterpret_cast<FrameWorkerData *>(priv->frame_workers[0].data1);
VP9_COMMON *const common = &worker_data->pbi->common;
vpx_codec_ctx_t* vp9_decoder = decoder->GetDecoder();
vpx_codec_alg_priv_t* priv =
(vpx_codec_alg_priv_t*) get_alg_priv(vp9_decoder);
VP9Decoder* pbi = priv->pbi;
VP9_COMMON* common = &pbi->common;
if (encode_parms.lossless) {
EXPECT_EQ(0, common->base_qindex);
EXPECT_EQ(0, common->y_dc_delta_q);
EXPECT_EQ(0, common->uv_dc_delta_q);
EXPECT_EQ(0, common->uv_ac_delta_q);
EXPECT_EQ(ONLY_4X4, common->tx_mode);
EXPECT_EQ(common->base_qindex, 0);
EXPECT_EQ(common->y_dc_delta_q, 0);
EXPECT_EQ(common->uv_dc_delta_q, 0);
EXPECT_EQ(common->uv_ac_delta_q, 0);
EXPECT_EQ(common->tx_mode, ONLY_4X4);
}
EXPECT_EQ(encode_parms.error_resilient, common->error_resilient_mode);
EXPECT_EQ(common->error_resilient_mode, encode_parms.error_resilient);
if (encode_parms.error_resilient) {
EXPECT_EQ(1, common->frame_parallel_decoding_mode);
EXPECT_EQ(0, common->use_prev_frame_mvs);
EXPECT_EQ(common->frame_parallel_decoding_mode, 1);
EXPECT_EQ(common->use_prev_frame_mvs, 0);
} else {
EXPECT_EQ(encode_parms.frame_parallel,
common->frame_parallel_decoding_mode);
EXPECT_EQ(common->frame_parallel_decoding_mode,
encode_parms.frame_parallel);
}
EXPECT_EQ(encode_parms.color_range, common->color_range);
EXPECT_EQ(encode_parms.cs, common->color_space);
if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) {
EXPECT_EQ(encode_parms.render_size[0], common->render_width);
EXPECT_EQ(encode_parms.render_size[1], common->render_height);
}
EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols);
EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows);
EXPECT_EQ(common->color_space, encode_parms.cs);
EXPECT_EQ(common->log2_tile_cols, encode_parms.tile_cols);
EXPECT_EQ(common->log2_tile_rows, encode_parms.tile_rows);
EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
return VPX_CODEC_OK == res_dec;
@@ -136,18 +164,35 @@ class VpxEncoderParmsGetToDecoder
EncodeParameters encode_parms;
};
TEST_P(VpxEncoderParmsGetToDecoder, BitstreamParms) {
// TODO(hkuang): This test conflicts with frame parallel decode. So disable it
// for now until fix.
TEST_P(VpxEncoderParmsGetToDecoder, DISABLED_BitstreamParms) {
init_flags_ = VPX_CODEC_USE_PSNR;
libvpx_test::VideoSource *const video =
new libvpx_test::Y4mVideoSource(test_video_.name, 0, test_video_.frames);
ASSERT_TRUE(video != NULL);
libvpx_test::VideoSource *video;
if (is_extension_y4m(test_video_.name)) {
video = new libvpx_test::Y4mVideoSource(test_video_.name,
0, test_video_.frames);
} else {
video = new libvpx_test::YUVVideoSource(test_video_.name,
VPX_IMG_FMT_I420,
test_video_.width,
test_video_.height,
kFramerate, 1, 0,
test_video_.frames);
}
ASSERT_NO_FATAL_FAILURE(RunLoop(video));
delete video;
delete(video);
}
VP9_INSTANTIATE_TEST_CASE(VpxEncoderParmsGetToDecoder,
::testing::ValuesIn(kVP9EncodeParameterSet),
::testing::ValuesIn(kVP9EncodePerfTestVectors));
VP9_INSTANTIATE_TEST_CASE(
VpxEncoderParmsGetToDecoder,
::testing::ValuesIn(kVP9EncodeParameterSet),
::testing::ValuesIn(kVP9EncodePerfTestVectors));
VP10_INSTANTIATE_TEST_CASE(
VpxEncoderParmsGetToDecoder,
::testing::ValuesIn(kVP9EncodeParameterSet),
::testing::ValuesIn(kVP9EncodePerfTestVectors));
} // namespace

View File

@@ -187,23 +187,9 @@ VP9_INSTANTIATE_TEST_CASE(
::testing::ValuesIn(kTestVectors),
::testing::ValuesIn(kCpuUsedVectors));
#if CONFIG_VP9_HIGHBITDEPTH
# if CONFIG_VP10_ENCODER
// TODO(angiebird): many fail in high bitdepth mode.
INSTANTIATE_TEST_CASE_P(
DISABLED_VP10, EndToEndTestLarge,
::testing::Combine(
::testing::Values(static_cast<const libvpx_test::CodecFactory *>(
&libvpx_test::kVP10)),
::testing::ValuesIn(kEncodingModeVectors),
::testing::ValuesIn(kTestVectors),
::testing::ValuesIn(kCpuUsedVectors)));
# endif // CONFIG_VP10_ENCODER
#else
VP10_INSTANTIATE_TEST_CASE(
EndToEndTestLarge,
::testing::ValuesIn(kEncodingModeVectors),
::testing::ValuesIn(kTestVectors),
::testing::ValuesIn(kCpuUsedVectors));
#endif // CONFIG_VP9_HIGHBITDEPTH
} // namespace

View File

@@ -67,22 +67,12 @@ TEST_P(ErrorBlockTest, OperationCheck) {
int64_t ret;
int64_t ref_ssz;
int64_t ref_ret;
const int msb = bit_depth_ + 8 - 1;
for (int i = 0; i < kNumIterations; ++i) {
int err_count = 0;
block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
for (int j = 0; j < block_size; j++) {
// coeff and dqcoeff will always have at least the same sign, and this
// can be used for optimization, so generate test input precisely.
if (rnd(2)) {
// Positive number
coeff[j] = rnd(1 << msb);
dqcoeff[j] = rnd(1 << msb);
} else {
// Negative number
coeff[j] = -rnd(1 << msb);
dqcoeff[j] = -rnd(1 << msb);
}
coeff[j] = rnd(2 << 20) - (1 << 20);
dqcoeff[j] = rnd(2 << 20) - (1 << 20);
}
ref_ret = ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz,
bit_depth_);
@@ -95,7 +85,7 @@ TEST_P(ErrorBlockTest, OperationCheck) {
err_count_total += err_count;
}
EXPECT_EQ(0, err_count_total)
<< "Error: Error Block Test, C output doesn't match optimized output. "
<< "Error: Error Block Test, C output doesn't match SSE2 output. "
<< "First failed at test case " << first_failure;
}
@@ -110,36 +100,23 @@ TEST_P(ErrorBlockTest, ExtremeValues) {
int64_t ret;
int64_t ref_ssz;
int64_t ref_ret;
const int msb = bit_depth_ + 8 - 1;
int max_val = ((1 << msb) - 1);
int max_val = ((1 << 20) - 1);
for (int i = 0; i < kNumIterations; ++i) {
int err_count = 0;
int k = (i / 9) % 9;
int k = (i / 9) % 5;
// Change the maximum coeff value, to test different bit boundaries
if ( k == 8 && (i % 9) == 0 ) {
if ( k == 4 && (i % 9) == 0 ) {
max_val >>= 1;
}
block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
for (int j = 0; j < block_size; j++) {
if (k < 4) {
// Test at positive maximum values
coeff[j] = k % 2 ? max_val : 0;
dqcoeff[j] = (k >> 1) % 2 ? max_val : 0;
} else if (k < 8) {
// Test at negative maximum values
coeff[j] = k % 2 ? -max_val : 0;
dqcoeff[j] = (k >> 1) % 2 ? -max_val : 0;
if (k < 4) { // Test at maximum values
coeff[j] = k % 2 ? max_val : -max_val;
dqcoeff[j] = (k >> 1) % 2 ? max_val : -max_val;
} else {
if (rnd(2)) {
// Positive number
coeff[j] = rnd(1 << 14);
dqcoeff[j] = rnd(1 << 14);
} else {
// Negative number
coeff[j] = -rnd(1 << 14);
dqcoeff[j] = -rnd(1 << 14);
}
coeff[j] = rnd(2 << 14) - (1 << 14);
dqcoeff[j] = rnd(2 << 14) - (1 << 14);
}
}
ref_ret = ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz,
@@ -153,30 +130,13 @@ TEST_P(ErrorBlockTest, ExtremeValues) {
err_count_total += err_count;
}
EXPECT_EQ(0, err_count_total)
<< "Error: Error Block Test, C output doesn't match optimized output. "
<< "Error: Error Block Test, C output doesn't match SSE2 output. "
<< "First failed at test case " << first_failure;
}
using std::tr1::make_tuple;
#if CONFIG_USE_X86INC
int64_t wrap_vp9_highbd_block_error_8bit_c(const tran_low_t *coeff,
const tran_low_t *dqcoeff,
intptr_t block_size,
int64_t *ssz, int bps) {
assert(bps == 8);
return vp9_highbd_block_error_8bit_c(coeff, dqcoeff, block_size, ssz);
}
#if HAVE_SSE2
int64_t wrap_vp9_highbd_block_error_8bit_sse2(const tran_low_t *coeff,
const tran_low_t *dqcoeff,
intptr_t block_size,
int64_t *ssz, int bps) {
assert(bps == 8);
return vp9_highbd_block_error_8bit_sse2(coeff, dqcoeff, block_size, ssz);
}
INSTANTIATE_TEST_CASE_P(
SSE2, ErrorBlockTest,
::testing::Values(
@@ -185,27 +145,7 @@ INSTANTIATE_TEST_CASE_P(
make_tuple(&vp9_highbd_block_error_sse2,
&vp9_highbd_block_error_c, VPX_BITS_12),
make_tuple(&vp9_highbd_block_error_sse2,
&vp9_highbd_block_error_c, VPX_BITS_8),
make_tuple(&wrap_vp9_highbd_block_error_8bit_sse2,
&wrap_vp9_highbd_block_error_8bit_c, VPX_BITS_8)));
&vp9_highbd_block_error_c, VPX_BITS_8)));
#endif // HAVE_SSE2
#if HAVE_AVX
int64_t wrap_vp9_highbd_block_error_8bit_avx(const tran_low_t *coeff,
const tran_low_t *dqcoeff,
intptr_t block_size,
int64_t *ssz, int bps) {
assert(bps == 8);
return vp9_highbd_block_error_8bit_avx(coeff, dqcoeff, block_size, ssz);
}
INSTANTIATE_TEST_CASE_P(
AVX, ErrorBlockTest,
::testing::Values(
make_tuple(&wrap_vp9_highbd_block_error_8bit_avx,
&wrap_vp9_highbd_block_error_8bit_c, VPX_BITS_8)));
#endif // HAVE_AVX
#endif // CONFIG_USE_X86INC
#endif // CONFIG_VP9_HIGHBITDEPTH
} // namespace

View File

@@ -190,7 +190,7 @@ string DecodeFile(const string& filename, int num_threads) {
void DecodeFiles(const FileList files[]) {
for (const FileList *iter = files; iter->name != NULL; ++iter) {
SCOPED_TRACE(iter->name);
for (int t = 1; t <= 8; ++t) {
for (int t = 2; t <= 8; ++t) {
EXPECT_EQ(iter->expected_md5, DecodeFile(iter->name, t))
<< "threads = " << t;
}
@@ -235,13 +235,13 @@ TEST(VPxWorkerThreadTest, TestSerialInterface) {
EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
}
TEST(VP9DecodeMultiThreadedTest, NoTilesNonFrameParallel) {
TEST(VP9DecodeMultiThreadedTest, Decode) {
// no tiles or frame parallel; this exercises loop filter threading.
EXPECT_EQ("b35a1b707b28e82be025d960aba039bc",
DecodeFile("vp90-2-03-size-226x226.webm", 2));
}
TEST(VP9DecodeMultiThreadedTest, FrameParallel) {
TEST(VP9DecodeMultiThreadedTest, Decode2) {
static const FileList files[] = {
{ "vp90-2-08-tile_1x2_frame_parallel.webm",
"68ede6abd66bae0a2edf2eb9232241b6" },
@@ -255,7 +255,8 @@ TEST(VP9DecodeMultiThreadedTest, FrameParallel) {
DecodeFiles(files);
}
TEST(VP9DecodeMultiThreadedTest, FrameParallelResize) {
// Test tile quantity changes within one file.
TEST(VP9DecodeMultiThreadedTest, Decode3) {
static const FileList files[] = {
{ "vp90-2-14-resize-fp-tiles-1-16.webm",
"0cd5e632c326297e975f38949c31ea94" },
@@ -306,19 +307,6 @@ TEST(VP9DecodeMultiThreadedTest, FrameParallelResize) {
DecodeFiles(files);
}
TEST(VP9DecodeMultiThreadedTest, NonFrameParallel) {
static const FileList files[] = {
{ "vp90-2-08-tile_1x2.webm", "570b4a5d5a70d58b5359671668328a16" },
{ "vp90-2-08-tile_1x4.webm", "988d86049e884c66909d2d163a09841a" },
{ "vp90-2-08-tile_1x8.webm", "0941902a52e9092cb010905eab16364c" },
{ "vp90-2-08-tile-4x1.webm", "06505aade6647c583c8e00a2f582266f" },
{ "vp90-2-08-tile-4x4.webm", "85c2299892460d76e2c600502d52bfe2" },
{ NULL, NULL }
};
DecodeFiles(files);
}
#endif // CONFIG_WEBM_IO
INSTANTIATE_TEST_CASE_P(Synchronous, VPxWorkerThreadTest, ::testing::Bool());

View File

@@ -9,7 +9,6 @@
*/
#ifndef TEST_Y4M_VIDEO_SOURCE_H_
#define TEST_Y4M_VIDEO_SOURCE_H_
#include <algorithm>
#include <string>
#include "test/video_source.h"
@@ -92,18 +91,6 @@ class Y4mVideoSource : public VideoSource {
y4m_input_fetch_frame(&y4m_, input_file_, img_.get());
}
// Swap buffers with another y4m source. This allows reading a new frame
// while keeping the old frame around. A whole Y4mSource is required and
// not just a vpx_image_t because of how the y4m reader manipulates
// vpx_image_t internals,
void SwapBuffers(Y4mVideoSource *other) {
std::swap(other->y4m_.dst_buf, y4m_.dst_buf);
vpx_image_t *tmp;
tmp = other->img_.release();
other->img_.reset(img_.release());
img_.reset(tmp);
}
protected:
void CloseSource() {
y4m_input_close(&y4m_);

View File

@@ -1,10 +1,7 @@
URL: https://chromium.googlesource.com/webm/libwebm
Version: 476366249e1fda7710a389cd41c57db42305e0d4
Version: 2dec09426ab62b794464cc9971bd135b4d313e65
License: BSD
License File: LICENSE.txt
Description:
libwebm is used to handle WebM container I/O.
Local Changes:
* <none>

View File

@@ -528,7 +528,7 @@ class Tracks {
public:
// Audio and video type defined by the Matroska specs.
enum { kVideo = 0x1, kAudio = 0x2 };
// Opus, Vorbis, VP8, and VP9 codec ids defined by the Matroska specs.
static const char kOpusCodecId[];
static const char kVorbisCodecId[];
static const char kVp8CodecId[];

File diff suppressed because it is too large Load Diff

View File

@@ -9,13 +9,12 @@
#ifndef MKVPARSER_HPP
#define MKVPARSER_HPP
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstdio>
#include <cstddef>
namespace mkvparser {
const int E_PARSE_FAILED = -1;
const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3;
@@ -28,11 +27,8 @@ class IMkvReader {
virtual ~IMkvReader();
};
template<typename Type> Type* SafeArrayAlloc(unsigned long long num_elements,
unsigned long long element_size);
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&);
long long ReadID(IMkvReader* pReader, long long pos, long& len);
long long UnserializeUInt(IMkvReader*, long long pos, long long size);
long UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
@@ -837,7 +833,7 @@ class Cues {
private:
bool Init() const;
bool PreloadCuePoint(long&, long long) const;
void PreloadCuePoint(long&, long long) const;
mutable CuePoint** m_cue_points;
mutable long m_count;
@@ -1003,8 +999,8 @@ class Segment {
long DoLoadClusterUnknownSize(long long&, long&);
long DoParseNext(const Cluster*&, long long&, long&);
bool AppendCluster(Cluster*);
bool PreloadCluster(Cluster*, ptrdiff_t);
void AppendCluster(Cluster*);
void PreloadCluster(Cluster*, ptrdiff_t);
// void ParseSeekHead(long long pos, long long size);
// void ParseSeekEntry(long long pos, long long size);

View File

@@ -41,7 +41,6 @@ enum MkvId {
kMkvTimecodeScale = 0x2AD7B1,
kMkvDuration = 0x4489,
kMkvDateUTC = 0x4461,
kMkvTitle = 0x7BA9,
kMkvMuxingApp = 0x4D80,
kMkvWritingApp = 0x5741,
// Cluster
@@ -108,16 +107,9 @@ enum MkvId {
kMkvContentEncodingOrder = 0x5031,
kMkvContentEncodingScope = 0x5032,
kMkvContentEncodingType = 0x5033,
kMkvContentCompression = 0x5034,
kMkvContentCompAlgo = 0x4254,
kMkvContentCompSettings = 0x4255,
kMkvContentEncryption = 0x5035,
kMkvContentEncAlgo = 0x47E1,
kMkvContentEncKeyID = 0x47E2,
kMkvContentSignature = 0x47E3,
kMkvContentSigKeyID = 0x47E4,
kMkvContentSigAlgo = 0x47E5,
kMkvContentSigHashAlgo = 0x47E6,
kMkvContentEncAESSettings = 0x47E7,
kMkvAESSettingsCipherMode = 0x47E8,
kMkvAESSettingsCipherInitData = 0x47E9,

164
vp10/common/alloccommon.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_config.h"
#include "vpx_mem/vpx_mem.h"
#include "vp10/common/alloccommon.h"
#include "vp10/common/blockd.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/entropymv.h"
#include "vp10/common/onyxc_int.h"
void vp10_set_mb_mi(VP10_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);
cm->mi_cols = aligned_width >> MI_SIZE_LOG2;
cm->mi_rows = aligned_height >> MI_SIZE_LOG2;
cm->mi_stride = calc_mi_size(cm->mi_cols);
cm->mb_cols = (cm->mi_cols + 1) >> 1;
cm->mb_rows = (cm->mi_rows + 1) >> 1;
cm->MBs = cm->mb_rows * cm->mb_cols;
}
static int alloc_seg_map(VP10_COMMON *cm, int seg_map_size) {
int i;
for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
cm->seg_map_array[i] = (uint8_t *)vpx_calloc(seg_map_size, 1);
if (cm->seg_map_array[i] == NULL)
return 1;
}
cm->seg_map_alloc_size = seg_map_size;
// Init the index.
cm->seg_map_idx = 0;
cm->prev_seg_map_idx = 1;
cm->current_frame_seg_map = cm->seg_map_array[cm->seg_map_idx];
if (!cm->frame_parallel_decode)
cm->last_frame_seg_map = cm->seg_map_array[cm->prev_seg_map_idx];
return 0;
}
static void free_seg_map(VP10_COMMON *cm) {
int i;
for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
vpx_free(cm->seg_map_array[i]);
cm->seg_map_array[i] = NULL;
}
cm->current_frame_seg_map = NULL;
if (!cm->frame_parallel_decode) {
cm->last_frame_seg_map = NULL;
}
}
void vp10_free_ref_frame_buffers(BufferPool *pool) {
int i;
for (i = 0; i < FRAME_BUFFERS; ++i) {
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;
}
vpx_free(pool->frame_bufs[i].mvs);
pool->frame_bufs[i].mvs = NULL;
vpx_free_frame_buffer(&pool->frame_bufs[i].buf);
}
}
void vp10_free_postproc_buffers(VP10_COMMON *cm) {
#if CONFIG_VP9_POSTPROC
vpx_free_frame_buffer(&cm->post_proc_buffer);
vpx_free_frame_buffer(&cm->post_proc_buffer_int);
#else
(void)cm;
#endif
}
void vp10_free_context_buffers(VP10_COMMON *cm) {
cm->free_mi(cm);
free_seg_map(cm);
vpx_free(cm->above_context);
cm->above_context = NULL;
vpx_free(cm->above_seg_context);
cm->above_seg_context = NULL;
}
int vp10_alloc_context_buffers(VP10_COMMON *cm, int width, int height) {
int new_mi_size;
vp10_set_mb_mi(cm, width, height);
new_mi_size = cm->mi_stride * calc_mi_size(cm->mi_rows);
if (cm->mi_alloc_size < new_mi_size) {
cm->free_mi(cm);
if (cm->alloc_mi(cm, new_mi_size))
goto fail;
}
if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
// Create the segmentation map structure and set to 0.
free_seg_map(cm);
if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols))
goto fail;
}
if (cm->above_context_alloc_cols < cm->mi_cols) {
vpx_free(cm->above_context);
cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc(
2 * mi_cols_aligned_to_sb(cm->mi_cols) * MAX_MB_PLANE,
sizeof(*cm->above_context));
if (!cm->above_context) goto fail;
vpx_free(cm->above_seg_context);
cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc(
mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context));
if (!cm->above_seg_context) goto fail;
cm->above_context_alloc_cols = cm->mi_cols;
}
return 0;
fail:
vp10_free_context_buffers(cm);
return 1;
}
void vp10_remove_common(VP10_COMMON *cm) {
vp10_free_context_buffers(cm);
vpx_free(cm->fc);
cm->fc = NULL;
vpx_free(cm->frame_contexts);
cm->frame_contexts = NULL;
}
void vp10_init_context_buffers(VP10_COMMON *cm) {
cm->setup_mi(cm);
if (cm->last_frame_seg_map && !cm->frame_parallel_decode)
memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols);
}
void vp10_swap_current_and_last_seg_map(VP10_COMMON *cm) {
// Swap indices.
const int tmp = cm->seg_map_idx;
cm->seg_map_idx = cm->prev_seg_map_idx;
cm->prev_seg_map_idx = tmp;
cm->current_frame_seg_map = cm->seg_map_array[cm->seg_map_idx];
cm->last_frame_seg_map = cm->seg_map_array[cm->prev_seg_map_idx];
}

44
vp10/common/alloccommon.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_ALLOCCOMMON_H_
#define VP10_COMMON_ALLOCCOMMON_H_
#define INVALID_IDX -1 // Invalid buffer index.
#ifdef __cplusplus
extern "C" {
#endif
struct VP10Common;
struct BufferPool;
void vp10_remove_common(struct VP10Common *cm);
int vp10_alloc_context_buffers(struct VP10Common *cm, int width, int height);
void vp10_init_context_buffers(struct VP10Common *cm);
void vp10_free_context_buffers(struct VP10Common *cm);
void vp10_free_ref_frame_buffers(struct BufferPool *pool);
void vp10_free_postproc_buffers(struct VP10Common *cm);
int vp10_alloc_state_buffers(struct VP10Common *cm, int width, int height);
void vp10_free_state_buffers(struct VP10Common *cm);
void vp10_set_mb_mi(struct VP10Common *cm, int width, int height);
void vp10_swap_current_and_last_seg_map(struct VP10Common *cm);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_ALLOCCOMMON_H_

201
vp10/common/ans.h Normal file
View File

@@ -0,0 +1,201 @@
#ifndef VP10_COMMON_ANS_H_
#define VP10_COMMON_ANS_H_
// An implementation of Asymmetric Numeral Systems
// http://arxiv.org/abs/1311.2540v2
#include <stdint.h>
#include "vpx_ports/mem_ops.h"
#define ANS_DIVIDE_BY_MULTIPLY 0
#if ANS_DIVIDE_BY_MULTIPLY
#include "divide.h"
#define ANS_INIT_DIVIDE init_fastdiv()
#define ANS_DIVREM(quotient, remainder, dividend, divisor) \
do { \
quotient = FASTDIV(dividend, divisor); \
remainder = dividend - quotient * divisor; \
} while (0)
#else
#define ANS_INIT_DIVIDE
#define ANS_DIVREM(quotient, remainder, dividend, divisor) \
do { \
quotient = dividend / divisor; \
remainder = dividend % divisor; \
} while (0)
#endif
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct AnsCoder {
uint8_t *buf;
int buf_offset;
uint32_t state;
};
struct AnsDecoder {
const uint8_t *buf;
int buf_offset;
uint32_t state;
};
typedef uint8_t AnsP8;
#define ans_p8_precision 256
#define ans_p8_shift 8
#define l_base (ans_p8_precision * 4) // l_base % precision must be 0
#define io_base 256
// Range I = { l_base, l_base + 1, ..., l_base * io_base - 1 }
static inline void ans_write_init(struct AnsCoder *const ans,
uint8_t *const buf) {
ans->buf = buf;
ans->buf_offset = 0;
ans->state = l_base;
}
static inline int ans_write_end(struct AnsCoder *const ans) {
mem_put_le24(ans->buf + ans->buf_offset, ans->state);
return ans->buf_offset + 3;
}
// rABS with normalization
// p or p0 takes the place of l_s from the paper
// ans_p8_precision is m
static inline void rabs_write(struct AnsCoder *ans, int val, AnsP8 p0) {
const AnsP8 p = ans_p8_precision - p0;
const unsigned l_s = val ? p : p0;
unsigned quot, rem;
if ((!val && ans->state >= l_base / ans_p8_precision * io_base * p0) ||
(val && ans->state >= l_base / ans_p8_precision * io_base * p)) {
ans->buf[ans->buf_offset++] = ans->state % io_base;
ans->state /= io_base;
}
ANS_DIVREM(quot, rem, ans->state, l_s);
ans->state = quot * ans_p8_precision + rem + (val ? 0 : p);
}
#define ANS_IMPL1 0
#define UNPREDICTABLE(x) x
static inline int rabs_read(struct AnsDecoder *ans, AnsP8 p0) {
int val;
#if ANS_IMPL1
unsigned l_s;
#else
unsigned quot, rem, x, xn;
#endif
const AnsP8 p = ans_p8_precision - p0;
if (ans->state < l_base) {
ans->state = ans->state * io_base + ans->buf[--ans->buf_offset];
}
#if ANS_IMPL1
val = ans->state % ans_p8_precision < p;
l_s = val ? p : p0;
ans->state = (ans->state / ans_p8_precision) * l_s +
ans->state % ans_p8_precision - (!val * p);
#else
x = ans->state;
quot = x / ans_p8_precision;
rem = x % ans_p8_precision;
xn = quot * p;
val = rem < p;
if (UNPREDICTABLE(val)) {
ans->state = xn + rem;
} else {
//ans->state = quot * p0 + rem - p;
ans->state = x - xn - p;
}
#endif
return val;
}
struct rans_sym {
AnsP8 prob;
AnsP8 cum_prob; // not-inclusive
};
struct rans_dec_sym {
uint8_t val;
AnsP8 prob;
AnsP8 cum_prob; // not-inclusive
};
static inline void rans_build_dec_tab(const AnsP8 token_probs[], struct rans_dec_sym dec_tab[]) {
int val = 0;
int cum_prob = 0;
int sym_end = token_probs[0];
int i;
for (i = 0; i < 256; ++i) {
if (i == sym_end) {
++val;
cum_prob = sym_end;
sym_end += token_probs[val];
}
dec_tab[i].val = val;
dec_tab[i].prob = token_probs[val];
dec_tab[i].cum_prob = cum_prob;
}
}
#define DBG_RANS 0
// rANS with normalization
// sym->prob takes the place of l_s from the paper
// ans_p8_precision is m
static inline void rans_stream_encode(struct AnsCoder *ans, const struct rans_sym *const sym) {
const AnsP8 p = sym->prob;
// const unsigned int s0 = ans->state;
while (ans->state >= l_base / ans_p8_precision * io_base * p) {
ans->buf[ans->buf_offset++] = ans->state % io_base;
ans->state /= io_base;
}
#if DBG_RANS
unsigned state0 = ans->state;
#endif
ans->state = (ans->state / p) * ans_p8_precision + ans->state % p + sym->cum_prob;
#if DBG_RANS
fprintf(stderr, "C(val = [%02x %02x], %x) = %x\n", sym->cum_prob, sym->prob, state0, ans->state);
#endif
}
static inline int rans_stream_decode(struct AnsDecoder *ans,
const struct rans_dec_sym tab[]) {
unsigned rem;
unsigned quo;
int val;
// const unsigned int s0 = ans->state;
if (ans->state < l_base) {
ans->state = ans->state * io_base + ans->buf[--ans->buf_offset];
}
#if DBG_RANS
unsigned state0 = ans->state;
#endif
quo = ans->state / ans_p8_precision;
rem = ans->state % ans_p8_precision;
val = tab[rem].val;
ans->state = quo * tab[rem].prob + rem - tab[rem].cum_prob;
#if DBG_RANS
fprintf(stderr, "D(%x) = (%d = [%02x %02x], %x)\n", state0, val, tab[rem].cum_prob, tab[rem].prob, ans->state);
#endif
return val;
}
static inline int ans_read_init(struct AnsDecoder *const ans,
const uint8_t *const buf,
int offset) {
if (offset < 3)
return 1;
ans->buf = buf;
ans->buf_offset = offset - 3;
ans->state = mem_get_le24(buf + offset - 3);
return 0;
}
static inline int ans_read_end(struct AnsDecoder *const ans) {
return ans->state == l_base;
}
#undef ANS_DIVREM
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // VP10_COMMON_ANS_H_

View File

@@ -0,0 +1,248 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <arm_neon.h>
#include <assert.h>
#include "./vp10_rtcd.h"
#include "./vpx_config.h"
#include "vp10/common/common.h"
static int16_t sinpi_1_9 = 0x14a3;
static int16_t sinpi_2_9 = 0x26c9;
static int16_t sinpi_3_9 = 0x3441;
static int16_t sinpi_4_9 = 0x3b6c;
static int16_t cospi_8_64 = 0x3b21;
static int16_t cospi_16_64 = 0x2d41;
static int16_t cospi_24_64 = 0x187e;
static INLINE void TRANSPOSE4X4(
int16x8_t *q8s16,
int16x8_t *q9s16) {
int32x4_t q8s32, q9s32;
int16x4x2_t d0x2s16, d1x2s16;
int32x4x2_t q0x2s32;
d0x2s16 = vtrn_s16(vget_low_s16(*q8s16), vget_high_s16(*q8s16));
d1x2s16 = vtrn_s16(vget_low_s16(*q9s16), vget_high_s16(*q9s16));
q8s32 = vreinterpretq_s32_s16(vcombine_s16(d0x2s16.val[0], d0x2s16.val[1]));
q9s32 = vreinterpretq_s32_s16(vcombine_s16(d1x2s16.val[0], d1x2s16.val[1]));
q0x2s32 = vtrnq_s32(q8s32, q9s32);
*q8s16 = vreinterpretq_s16_s32(q0x2s32.val[0]);
*q9s16 = vreinterpretq_s16_s32(q0x2s32.val[1]);
return;
}
static INLINE void GENERATE_COSINE_CONSTANTS(
int16x4_t *d0s16,
int16x4_t *d1s16,
int16x4_t *d2s16) {
*d0s16 = vdup_n_s16(cospi_8_64);
*d1s16 = vdup_n_s16(cospi_16_64);
*d2s16 = vdup_n_s16(cospi_24_64);
return;
}
static INLINE void GENERATE_SINE_CONSTANTS(
int16x4_t *d3s16,
int16x4_t *d4s16,
int16x4_t *d5s16,
int16x8_t *q3s16) {
*d3s16 = vdup_n_s16(sinpi_1_9);
*d4s16 = vdup_n_s16(sinpi_2_9);
*q3s16 = vdupq_n_s16(sinpi_3_9);
*d5s16 = vdup_n_s16(sinpi_4_9);
return;
}
static INLINE void IDCT4x4_1D(
int16x4_t *d0s16,
int16x4_t *d1s16,
int16x4_t *d2s16,
int16x8_t *q8s16,
int16x8_t *q9s16) {
int16x4_t d16s16, d17s16, d18s16, d19s16, d23s16, d24s16;
int16x4_t d26s16, d27s16, d28s16, d29s16;
int32x4_t q10s32, q13s32, q14s32, q15s32;
int16x8_t q13s16, q14s16;
d16s16 = vget_low_s16(*q8s16);
d17s16 = vget_high_s16(*q8s16);
d18s16 = vget_low_s16(*q9s16);
d19s16 = vget_high_s16(*q9s16);
d23s16 = vadd_s16(d16s16, d18s16);
d24s16 = vsub_s16(d16s16, d18s16);
q15s32 = vmull_s16(d17s16, *d2s16);
q10s32 = vmull_s16(d17s16, *d0s16);
q13s32 = vmull_s16(d23s16, *d1s16);
q14s32 = vmull_s16(d24s16, *d1s16);
q15s32 = vmlsl_s16(q15s32, d19s16, *d0s16);
q10s32 = vmlal_s16(q10s32, d19s16, *d2s16);
d26s16 = vqrshrn_n_s32(q13s32, 14);
d27s16 = vqrshrn_n_s32(q14s32, 14);
d29s16 = vqrshrn_n_s32(q15s32, 14);
d28s16 = vqrshrn_n_s32(q10s32, 14);
q13s16 = vcombine_s16(d26s16, d27s16);
q14s16 = vcombine_s16(d28s16, d29s16);
*q8s16 = vaddq_s16(q13s16, q14s16);
*q9s16 = vsubq_s16(q13s16, q14s16);
*q9s16 = vcombine_s16(vget_high_s16(*q9s16),
vget_low_s16(*q9s16)); // vswp
return;
}
static INLINE void IADST4x4_1D(
int16x4_t *d3s16,
int16x4_t *d4s16,
int16x4_t *d5s16,
int16x8_t *q3s16,
int16x8_t *q8s16,
int16x8_t *q9s16) {
int16x4_t d6s16, d16s16, d17s16, d18s16, d19s16;
int32x4_t q8s32, q9s32, q10s32, q11s32, q12s32, q13s32, q14s32, q15s32;
d6s16 = vget_low_s16(*q3s16);
d16s16 = vget_low_s16(*q8s16);
d17s16 = vget_high_s16(*q8s16);
d18s16 = vget_low_s16(*q9s16);
d19s16 = vget_high_s16(*q9s16);
q10s32 = vmull_s16(*d3s16, d16s16);
q11s32 = vmull_s16(*d4s16, d16s16);
q12s32 = vmull_s16(d6s16, d17s16);
q13s32 = vmull_s16(*d5s16, d18s16);
q14s32 = vmull_s16(*d3s16, d18s16);
q15s32 = vmovl_s16(d16s16);
q15s32 = vaddw_s16(q15s32, d19s16);
q8s32 = vmull_s16(*d4s16, d19s16);
q15s32 = vsubw_s16(q15s32, d18s16);
q9s32 = vmull_s16(*d5s16, d19s16);
q10s32 = vaddq_s32(q10s32, q13s32);
q10s32 = vaddq_s32(q10s32, q8s32);
q11s32 = vsubq_s32(q11s32, q14s32);
q8s32 = vdupq_n_s32(sinpi_3_9);
q11s32 = vsubq_s32(q11s32, q9s32);
q15s32 = vmulq_s32(q15s32, q8s32);
q13s32 = vaddq_s32(q10s32, q12s32);
q10s32 = vaddq_s32(q10s32, q11s32);
q14s32 = vaddq_s32(q11s32, q12s32);
q10s32 = vsubq_s32(q10s32, q12s32);
d16s16 = vqrshrn_n_s32(q13s32, 14);
d17s16 = vqrshrn_n_s32(q14s32, 14);
d18s16 = vqrshrn_n_s32(q15s32, 14);
d19s16 = vqrshrn_n_s32(q10s32, 14);
*q8s16 = vcombine_s16(d16s16, d17s16);
*q9s16 = vcombine_s16(d18s16, d19s16);
return;
}
void vp10_iht4x4_16_add_neon(const tran_low_t *input, uint8_t *dest,
int dest_stride, int tx_type) {
uint8x8_t d26u8, d27u8;
int16x4_t d0s16, d1s16, d2s16, d3s16, d4s16, d5s16;
uint32x2_t d26u32, d27u32;
int16x8_t q3s16, q8s16, q9s16;
uint16x8_t q8u16, q9u16;
d26u32 = d27u32 = vdup_n_u32(0);
q8s16 = vld1q_s16(input);
q9s16 = vld1q_s16(input + 8);
TRANSPOSE4X4(&q8s16, &q9s16);
switch (tx_type) {
case 0: // idct_idct is not supported. Fall back to C
vp10_iht4x4_16_add_c(input, dest, dest_stride, tx_type);
return;
break;
case 1: // iadst_idct
// generate constants
GENERATE_COSINE_CONSTANTS(&d0s16, &d1s16, &d2s16);
GENERATE_SINE_CONSTANTS(&d3s16, &d4s16, &d5s16, &q3s16);
// first transform rows
IDCT4x4_1D(&d0s16, &d1s16, &d2s16, &q8s16, &q9s16);
// transpose the matrix
TRANSPOSE4X4(&q8s16, &q9s16);
// then transform columns
IADST4x4_1D(&d3s16, &d4s16, &d5s16, &q3s16, &q8s16, &q9s16);
break;
case 2: // idct_iadst
// generate constantsyy
GENERATE_COSINE_CONSTANTS(&d0s16, &d1s16, &d2s16);
GENERATE_SINE_CONSTANTS(&d3s16, &d4s16, &d5s16, &q3s16);
// first transform rows
IADST4x4_1D(&d3s16, &d4s16, &d5s16, &q3s16, &q8s16, &q9s16);
// transpose the matrix
TRANSPOSE4X4(&q8s16, &q9s16);
// then transform columns
IDCT4x4_1D(&d0s16, &d1s16, &d2s16, &q8s16, &q9s16);
break;
case 3: // iadst_iadst
// generate constants
GENERATE_SINE_CONSTANTS(&d3s16, &d4s16, &d5s16, &q3s16);
// first transform rows
IADST4x4_1D(&d3s16, &d4s16, &d5s16, &q3s16, &q8s16, &q9s16);
// transpose the matrix
TRANSPOSE4X4(&q8s16, &q9s16);
// then transform columns
IADST4x4_1D(&d3s16, &d4s16, &d5s16, &q3s16, &q8s16, &q9s16);
break;
default: // iadst_idct
assert(0);
break;
}
q8s16 = vrshrq_n_s16(q8s16, 4);
q9s16 = vrshrq_n_s16(q9s16, 4);
d26u32 = vld1_lane_u32((const uint32_t *)dest, d26u32, 0);
dest += dest_stride;
d26u32 = vld1_lane_u32((const uint32_t *)dest, d26u32, 1);
dest += dest_stride;
d27u32 = vld1_lane_u32((const uint32_t *)dest, d27u32, 0);
dest += dest_stride;
d27u32 = vld1_lane_u32((const uint32_t *)dest, d27u32, 1);
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_u32(d26u32));
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_u32(d27u32));
d26u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
d27u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
vst1_lane_u32((uint32_t *)dest, vreinterpret_u32_u8(d27u8), 1);
dest -= dest_stride;
vst1_lane_u32((uint32_t *)dest, vreinterpret_u32_u8(d27u8), 0);
dest -= dest_stride;
vst1_lane_u32((uint32_t *)dest, vreinterpret_u32_u8(d26u8), 1);
dest -= dest_stride;
vst1_lane_u32((uint32_t *)dest, vreinterpret_u32_u8(d26u8), 0);
return;
}

View File

@@ -0,0 +1,624 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <arm_neon.h>
#include <assert.h>
#include "./vp10_rtcd.h"
#include "./vpx_config.h"
#include "vp10/common/common.h"
static int16_t cospi_2_64 = 16305;
static int16_t cospi_4_64 = 16069;
static int16_t cospi_6_64 = 15679;
static int16_t cospi_8_64 = 15137;
static int16_t cospi_10_64 = 14449;
static int16_t cospi_12_64 = 13623;
static int16_t cospi_14_64 = 12665;
static int16_t cospi_16_64 = 11585;
static int16_t cospi_18_64 = 10394;
static int16_t cospi_20_64 = 9102;
static int16_t cospi_22_64 = 7723;
static int16_t cospi_24_64 = 6270;
static int16_t cospi_26_64 = 4756;
static int16_t cospi_28_64 = 3196;
static int16_t cospi_30_64 = 1606;
static INLINE void TRANSPOSE8X8(
int16x8_t *q8s16,
int16x8_t *q9s16,
int16x8_t *q10s16,
int16x8_t *q11s16,
int16x8_t *q12s16,
int16x8_t *q13s16,
int16x8_t *q14s16,
int16x8_t *q15s16) {
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16, d23s16;
int16x4_t d24s16, d25s16, d26s16, d27s16, d28s16, d29s16, d30s16, d31s16;
int32x4x2_t q0x2s32, q1x2s32, q2x2s32, q3x2s32;
int16x8x2_t q0x2s16, q1x2s16, q2x2s16, q3x2s16;
d16s16 = vget_low_s16(*q8s16);
d17s16 = vget_high_s16(*q8s16);
d18s16 = vget_low_s16(*q9s16);
d19s16 = vget_high_s16(*q9s16);
d20s16 = vget_low_s16(*q10s16);
d21s16 = vget_high_s16(*q10s16);
d22s16 = vget_low_s16(*q11s16);
d23s16 = vget_high_s16(*q11s16);
d24s16 = vget_low_s16(*q12s16);
d25s16 = vget_high_s16(*q12s16);
d26s16 = vget_low_s16(*q13s16);
d27s16 = vget_high_s16(*q13s16);
d28s16 = vget_low_s16(*q14s16);
d29s16 = vget_high_s16(*q14s16);
d30s16 = vget_low_s16(*q15s16);
d31s16 = vget_high_s16(*q15s16);
*q8s16 = vcombine_s16(d16s16, d24s16); // vswp d17, d24
*q9s16 = vcombine_s16(d18s16, d26s16); // vswp d19, d26
*q10s16 = vcombine_s16(d20s16, d28s16); // vswp d21, d28
*q11s16 = vcombine_s16(d22s16, d30s16); // vswp d23, d30
*q12s16 = vcombine_s16(d17s16, d25s16);
*q13s16 = vcombine_s16(d19s16, d27s16);
*q14s16 = vcombine_s16(d21s16, d29s16);
*q15s16 = vcombine_s16(d23s16, d31s16);
q0x2s32 = vtrnq_s32(vreinterpretq_s32_s16(*q8s16),
vreinterpretq_s32_s16(*q10s16));
q1x2s32 = vtrnq_s32(vreinterpretq_s32_s16(*q9s16),
vreinterpretq_s32_s16(*q11s16));
q2x2s32 = vtrnq_s32(vreinterpretq_s32_s16(*q12s16),
vreinterpretq_s32_s16(*q14s16));
q3x2s32 = vtrnq_s32(vreinterpretq_s32_s16(*q13s16),
vreinterpretq_s32_s16(*q15s16));
q0x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q0x2s32.val[0]), // q8
vreinterpretq_s16_s32(q1x2s32.val[0])); // q9
q1x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q0x2s32.val[1]), // q10
vreinterpretq_s16_s32(q1x2s32.val[1])); // q11
q2x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q2x2s32.val[0]), // q12
vreinterpretq_s16_s32(q3x2s32.val[0])); // q13
q3x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q2x2s32.val[1]), // q14
vreinterpretq_s16_s32(q3x2s32.val[1])); // q15
*q8s16 = q0x2s16.val[0];
*q9s16 = q0x2s16.val[1];
*q10s16 = q1x2s16.val[0];
*q11s16 = q1x2s16.val[1];
*q12s16 = q2x2s16.val[0];
*q13s16 = q2x2s16.val[1];
*q14s16 = q3x2s16.val[0];
*q15s16 = q3x2s16.val[1];
return;
}
static INLINE void IDCT8x8_1D(
int16x8_t *q8s16,
int16x8_t *q9s16,
int16x8_t *q10s16,
int16x8_t *q11s16,
int16x8_t *q12s16,
int16x8_t *q13s16,
int16x8_t *q14s16,
int16x8_t *q15s16) {
int16x4_t d0s16, d1s16, d2s16, d3s16;
int16x4_t d8s16, d9s16, d10s16, d11s16, d12s16, d13s16, d14s16, d15s16;
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16, d23s16;
int16x4_t d24s16, d25s16, d26s16, d27s16, d28s16, d29s16, d30s16, d31s16;
int16x8_t q0s16, q1s16, q2s16, q3s16, q4s16, q5s16, q6s16, q7s16;
int32x4_t q2s32, q3s32, q5s32, q6s32, q8s32, q9s32;
int32x4_t q10s32, q11s32, q12s32, q13s32, q15s32;
d0s16 = vdup_n_s16(cospi_28_64);
d1s16 = vdup_n_s16(cospi_4_64);
d2s16 = vdup_n_s16(cospi_12_64);
d3s16 = vdup_n_s16(cospi_20_64);
d16s16 = vget_low_s16(*q8s16);
d17s16 = vget_high_s16(*q8s16);
d18s16 = vget_low_s16(*q9s16);
d19s16 = vget_high_s16(*q9s16);
d20s16 = vget_low_s16(*q10s16);
d21s16 = vget_high_s16(*q10s16);
d22s16 = vget_low_s16(*q11s16);
d23s16 = vget_high_s16(*q11s16);
d24s16 = vget_low_s16(*q12s16);
d25s16 = vget_high_s16(*q12s16);
d26s16 = vget_low_s16(*q13s16);
d27s16 = vget_high_s16(*q13s16);
d28s16 = vget_low_s16(*q14s16);
d29s16 = vget_high_s16(*q14s16);
d30s16 = vget_low_s16(*q15s16);
d31s16 = vget_high_s16(*q15s16);
q2s32 = vmull_s16(d18s16, d0s16);
q3s32 = vmull_s16(d19s16, d0s16);
q5s32 = vmull_s16(d26s16, d2s16);
q6s32 = vmull_s16(d27s16, d2s16);
q2s32 = vmlsl_s16(q2s32, d30s16, d1s16);
q3s32 = vmlsl_s16(q3s32, d31s16, d1s16);
q5s32 = vmlsl_s16(q5s32, d22s16, d3s16);
q6s32 = vmlsl_s16(q6s32, d23s16, d3s16);
d8s16 = vqrshrn_n_s32(q2s32, 14);
d9s16 = vqrshrn_n_s32(q3s32, 14);
d10s16 = vqrshrn_n_s32(q5s32, 14);
d11s16 = vqrshrn_n_s32(q6s32, 14);
q4s16 = vcombine_s16(d8s16, d9s16);
q5s16 = vcombine_s16(d10s16, d11s16);
q2s32 = vmull_s16(d18s16, d1s16);
q3s32 = vmull_s16(d19s16, d1s16);
q9s32 = vmull_s16(d26s16, d3s16);
q13s32 = vmull_s16(d27s16, d3s16);
q2s32 = vmlal_s16(q2s32, d30s16, d0s16);
q3s32 = vmlal_s16(q3s32, d31s16, d0s16);
q9s32 = vmlal_s16(q9s32, d22s16, d2s16);
q13s32 = vmlal_s16(q13s32, d23s16, d2s16);
d14s16 = vqrshrn_n_s32(q2s32, 14);
d15s16 = vqrshrn_n_s32(q3s32, 14);
d12s16 = vqrshrn_n_s32(q9s32, 14);
d13s16 = vqrshrn_n_s32(q13s32, 14);
q6s16 = vcombine_s16(d12s16, d13s16);
q7s16 = vcombine_s16(d14s16, d15s16);
d0s16 = vdup_n_s16(cospi_16_64);
q2s32 = vmull_s16(d16s16, d0s16);
q3s32 = vmull_s16(d17s16, d0s16);
q13s32 = vmull_s16(d16s16, d0s16);
q15s32 = vmull_s16(d17s16, d0s16);
q2s32 = vmlal_s16(q2s32, d24s16, d0s16);
q3s32 = vmlal_s16(q3s32, d25s16, d0s16);
q13s32 = vmlsl_s16(q13s32, d24s16, d0s16);
q15s32 = vmlsl_s16(q15s32, d25s16, d0s16);
d0s16 = vdup_n_s16(cospi_24_64);
d1s16 = vdup_n_s16(cospi_8_64);
d18s16 = vqrshrn_n_s32(q2s32, 14);
d19s16 = vqrshrn_n_s32(q3s32, 14);
d22s16 = vqrshrn_n_s32(q13s32, 14);
d23s16 = vqrshrn_n_s32(q15s32, 14);
*q9s16 = vcombine_s16(d18s16, d19s16);
*q11s16 = vcombine_s16(d22s16, d23s16);
q2s32 = vmull_s16(d20s16, d0s16);
q3s32 = vmull_s16(d21s16, d0s16);
q8s32 = vmull_s16(d20s16, d1s16);
q12s32 = vmull_s16(d21s16, d1s16);
q2s32 = vmlsl_s16(q2s32, d28s16, d1s16);
q3s32 = vmlsl_s16(q3s32, d29s16, d1s16);
q8s32 = vmlal_s16(q8s32, d28s16, d0s16);
q12s32 = vmlal_s16(q12s32, d29s16, d0s16);
d26s16 = vqrshrn_n_s32(q2s32, 14);
d27s16 = vqrshrn_n_s32(q3s32, 14);
d30s16 = vqrshrn_n_s32(q8s32, 14);
d31s16 = vqrshrn_n_s32(q12s32, 14);
*q13s16 = vcombine_s16(d26s16, d27s16);
*q15s16 = vcombine_s16(d30s16, d31s16);
q0s16 = vaddq_s16(*q9s16, *q15s16);
q1s16 = vaddq_s16(*q11s16, *q13s16);
q2s16 = vsubq_s16(*q11s16, *q13s16);
q3s16 = vsubq_s16(*q9s16, *q15s16);
*q13s16 = vsubq_s16(q4s16, q5s16);
q4s16 = vaddq_s16(q4s16, q5s16);
*q14s16 = vsubq_s16(q7s16, q6s16);
q7s16 = vaddq_s16(q7s16, q6s16);
d26s16 = vget_low_s16(*q13s16);
d27s16 = vget_high_s16(*q13s16);
d28s16 = vget_low_s16(*q14s16);
d29s16 = vget_high_s16(*q14s16);
d16s16 = vdup_n_s16(cospi_16_64);
q9s32 = vmull_s16(d28s16, d16s16);
q10s32 = vmull_s16(d29s16, d16s16);
q11s32 = vmull_s16(d28s16, d16s16);
q12s32 = vmull_s16(d29s16, d16s16);
q9s32 = vmlsl_s16(q9s32, d26s16, d16s16);
q10s32 = vmlsl_s16(q10s32, d27s16, d16s16);
q11s32 = vmlal_s16(q11s32, d26s16, d16s16);
q12s32 = vmlal_s16(q12s32, d27s16, d16s16);
d10s16 = vqrshrn_n_s32(q9s32, 14);
d11s16 = vqrshrn_n_s32(q10s32, 14);
d12s16 = vqrshrn_n_s32(q11s32, 14);
d13s16 = vqrshrn_n_s32(q12s32, 14);
q5s16 = vcombine_s16(d10s16, d11s16);
q6s16 = vcombine_s16(d12s16, d13s16);
*q8s16 = vaddq_s16(q0s16, q7s16);
*q9s16 = vaddq_s16(q1s16, q6s16);
*q10s16 = vaddq_s16(q2s16, q5s16);
*q11s16 = vaddq_s16(q3s16, q4s16);
*q12s16 = vsubq_s16(q3s16, q4s16);
*q13s16 = vsubq_s16(q2s16, q5s16);
*q14s16 = vsubq_s16(q1s16, q6s16);
*q15s16 = vsubq_s16(q0s16, q7s16);
return;
}
static INLINE void IADST8X8_1D(
int16x8_t *q8s16,
int16x8_t *q9s16,
int16x8_t *q10s16,
int16x8_t *q11s16,
int16x8_t *q12s16,
int16x8_t *q13s16,
int16x8_t *q14s16,
int16x8_t *q15s16) {
int16x4_t d0s16, d1s16, d2s16, d3s16, d4s16, d5s16, d6s16, d7s16;
int16x4_t d8s16, d9s16, d10s16, d11s16, d12s16, d13s16, d14s16, d15s16;
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16, d23s16;
int16x4_t d24s16, d25s16, d26s16, d27s16, d28s16, d29s16, d30s16, d31s16;
int16x8_t q2s16, q4s16, q5s16, q6s16;
int32x4_t q0s32, q1s32, q2s32, q3s32, q4s32, q5s32, q6s32, q7s32, q8s32;
int32x4_t q9s32, q10s32, q11s32, q12s32, q13s32, q14s32, q15s32;
d16s16 = vget_low_s16(*q8s16);
d17s16 = vget_high_s16(*q8s16);
d18s16 = vget_low_s16(*q9s16);
d19s16 = vget_high_s16(*q9s16);
d20s16 = vget_low_s16(*q10s16);
d21s16 = vget_high_s16(*q10s16);
d22s16 = vget_low_s16(*q11s16);
d23s16 = vget_high_s16(*q11s16);
d24s16 = vget_low_s16(*q12s16);
d25s16 = vget_high_s16(*q12s16);
d26s16 = vget_low_s16(*q13s16);
d27s16 = vget_high_s16(*q13s16);
d28s16 = vget_low_s16(*q14s16);
d29s16 = vget_high_s16(*q14s16);
d30s16 = vget_low_s16(*q15s16);
d31s16 = vget_high_s16(*q15s16);
d14s16 = vdup_n_s16(cospi_2_64);
d15s16 = vdup_n_s16(cospi_30_64);
q1s32 = vmull_s16(d30s16, d14s16);
q2s32 = vmull_s16(d31s16, d14s16);
q3s32 = vmull_s16(d30s16, d15s16);
q4s32 = vmull_s16(d31s16, d15s16);
d30s16 = vdup_n_s16(cospi_18_64);
d31s16 = vdup_n_s16(cospi_14_64);
q1s32 = vmlal_s16(q1s32, d16s16, d15s16);
q2s32 = vmlal_s16(q2s32, d17s16, d15s16);
q3s32 = vmlsl_s16(q3s32, d16s16, d14s16);
q4s32 = vmlsl_s16(q4s32, d17s16, d14s16);
q5s32 = vmull_s16(d22s16, d30s16);
q6s32 = vmull_s16(d23s16, d30s16);
q7s32 = vmull_s16(d22s16, d31s16);
q8s32 = vmull_s16(d23s16, d31s16);
q5s32 = vmlal_s16(q5s32, d24s16, d31s16);
q6s32 = vmlal_s16(q6s32, d25s16, d31s16);
q7s32 = vmlsl_s16(q7s32, d24s16, d30s16);
q8s32 = vmlsl_s16(q8s32, d25s16, d30s16);
q11s32 = vaddq_s32(q1s32, q5s32);
q12s32 = vaddq_s32(q2s32, q6s32);
q1s32 = vsubq_s32(q1s32, q5s32);
q2s32 = vsubq_s32(q2s32, q6s32);
d22s16 = vqrshrn_n_s32(q11s32, 14);
d23s16 = vqrshrn_n_s32(q12s32, 14);
*q11s16 = vcombine_s16(d22s16, d23s16);
q12s32 = vaddq_s32(q3s32, q7s32);
q15s32 = vaddq_s32(q4s32, q8s32);
q3s32 = vsubq_s32(q3s32, q7s32);
q4s32 = vsubq_s32(q4s32, q8s32);
d2s16 = vqrshrn_n_s32(q1s32, 14);
d3s16 = vqrshrn_n_s32(q2s32, 14);
d24s16 = vqrshrn_n_s32(q12s32, 14);
d25s16 = vqrshrn_n_s32(q15s32, 14);
d6s16 = vqrshrn_n_s32(q3s32, 14);
d7s16 = vqrshrn_n_s32(q4s32, 14);
*q12s16 = vcombine_s16(d24s16, d25s16);
d0s16 = vdup_n_s16(cospi_10_64);
d1s16 = vdup_n_s16(cospi_22_64);
q4s32 = vmull_s16(d26s16, d0s16);
q5s32 = vmull_s16(d27s16, d0s16);
q2s32 = vmull_s16(d26s16, d1s16);
q6s32 = vmull_s16(d27s16, d1s16);
d30s16 = vdup_n_s16(cospi_26_64);
d31s16 = vdup_n_s16(cospi_6_64);
q4s32 = vmlal_s16(q4s32, d20s16, d1s16);
q5s32 = vmlal_s16(q5s32, d21s16, d1s16);
q2s32 = vmlsl_s16(q2s32, d20s16, d0s16);
q6s32 = vmlsl_s16(q6s32, d21s16, d0s16);
q0s32 = vmull_s16(d18s16, d30s16);
q13s32 = vmull_s16(d19s16, d30s16);
q0s32 = vmlal_s16(q0s32, d28s16, d31s16);
q13s32 = vmlal_s16(q13s32, d29s16, d31s16);
q10s32 = vmull_s16(d18s16, d31s16);
q9s32 = vmull_s16(d19s16, d31s16);
q10s32 = vmlsl_s16(q10s32, d28s16, d30s16);
q9s32 = vmlsl_s16(q9s32, d29s16, d30s16);
q14s32 = vaddq_s32(q2s32, q10s32);
q15s32 = vaddq_s32(q6s32, q9s32);
q2s32 = vsubq_s32(q2s32, q10s32);
q6s32 = vsubq_s32(q6s32, q9s32);
d28s16 = vqrshrn_n_s32(q14s32, 14);
d29s16 = vqrshrn_n_s32(q15s32, 14);
d4s16 = vqrshrn_n_s32(q2s32, 14);
d5s16 = vqrshrn_n_s32(q6s32, 14);
*q14s16 = vcombine_s16(d28s16, d29s16);
q9s32 = vaddq_s32(q4s32, q0s32);
q10s32 = vaddq_s32(q5s32, q13s32);
q4s32 = vsubq_s32(q4s32, q0s32);
q5s32 = vsubq_s32(q5s32, q13s32);
d30s16 = vdup_n_s16(cospi_8_64);
d31s16 = vdup_n_s16(cospi_24_64);
d18s16 = vqrshrn_n_s32(q9s32, 14);
d19s16 = vqrshrn_n_s32(q10s32, 14);
d8s16 = vqrshrn_n_s32(q4s32, 14);
d9s16 = vqrshrn_n_s32(q5s32, 14);
*q9s16 = vcombine_s16(d18s16, d19s16);
q5s32 = vmull_s16(d2s16, d30s16);
q6s32 = vmull_s16(d3s16, d30s16);
q7s32 = vmull_s16(d2s16, d31s16);
q0s32 = vmull_s16(d3s16, d31s16);
q5s32 = vmlal_s16(q5s32, d6s16, d31s16);
q6s32 = vmlal_s16(q6s32, d7s16, d31s16);
q7s32 = vmlsl_s16(q7s32, d6s16, d30s16);
q0s32 = vmlsl_s16(q0s32, d7s16, d30s16);
q1s32 = vmull_s16(d4s16, d30s16);
q3s32 = vmull_s16(d5s16, d30s16);
q10s32 = vmull_s16(d4s16, d31s16);
q2s32 = vmull_s16(d5s16, d31s16);
q1s32 = vmlsl_s16(q1s32, d8s16, d31s16);
q3s32 = vmlsl_s16(q3s32, d9s16, d31s16);
q10s32 = vmlal_s16(q10s32, d8s16, d30s16);
q2s32 = vmlal_s16(q2s32, d9s16, d30s16);
*q8s16 = vaddq_s16(*q11s16, *q9s16);
*q11s16 = vsubq_s16(*q11s16, *q9s16);
q4s16 = vaddq_s16(*q12s16, *q14s16);
*q12s16 = vsubq_s16(*q12s16, *q14s16);
q14s32 = vaddq_s32(q5s32, q1s32);
q15s32 = vaddq_s32(q6s32, q3s32);
q5s32 = vsubq_s32(q5s32, q1s32);
q6s32 = vsubq_s32(q6s32, q3s32);
d18s16 = vqrshrn_n_s32(q14s32, 14);
d19s16 = vqrshrn_n_s32(q15s32, 14);
d10s16 = vqrshrn_n_s32(q5s32, 14);
d11s16 = vqrshrn_n_s32(q6s32, 14);
*q9s16 = vcombine_s16(d18s16, d19s16);
q1s32 = vaddq_s32(q7s32, q10s32);
q3s32 = vaddq_s32(q0s32, q2s32);
q7s32 = vsubq_s32(q7s32, q10s32);
q0s32 = vsubq_s32(q0s32, q2s32);
d28s16 = vqrshrn_n_s32(q1s32, 14);
d29s16 = vqrshrn_n_s32(q3s32, 14);
d14s16 = vqrshrn_n_s32(q7s32, 14);
d15s16 = vqrshrn_n_s32(q0s32, 14);
*q14s16 = vcombine_s16(d28s16, d29s16);
d30s16 = vdup_n_s16(cospi_16_64);
d22s16 = vget_low_s16(*q11s16);
d23s16 = vget_high_s16(*q11s16);
q2s32 = vmull_s16(d22s16, d30s16);
q3s32 = vmull_s16(d23s16, d30s16);
q13s32 = vmull_s16(d22s16, d30s16);
q1s32 = vmull_s16(d23s16, d30s16);
d24s16 = vget_low_s16(*q12s16);
d25s16 = vget_high_s16(*q12s16);
q2s32 = vmlal_s16(q2s32, d24s16, d30s16);
q3s32 = vmlal_s16(q3s32, d25s16, d30s16);
q13s32 = vmlsl_s16(q13s32, d24s16, d30s16);
q1s32 = vmlsl_s16(q1s32, d25s16, d30s16);
d4s16 = vqrshrn_n_s32(q2s32, 14);
d5s16 = vqrshrn_n_s32(q3s32, 14);
d24s16 = vqrshrn_n_s32(q13s32, 14);
d25s16 = vqrshrn_n_s32(q1s32, 14);
q2s16 = vcombine_s16(d4s16, d5s16);
*q12s16 = vcombine_s16(d24s16, d25s16);
q13s32 = vmull_s16(d10s16, d30s16);
q1s32 = vmull_s16(d11s16, d30s16);
q11s32 = vmull_s16(d10s16, d30s16);
q0s32 = vmull_s16(d11s16, d30s16);
q13s32 = vmlal_s16(q13s32, d14s16, d30s16);
q1s32 = vmlal_s16(q1s32, d15s16, d30s16);
q11s32 = vmlsl_s16(q11s32, d14s16, d30s16);
q0s32 = vmlsl_s16(q0s32, d15s16, d30s16);
d20s16 = vqrshrn_n_s32(q13s32, 14);
d21s16 = vqrshrn_n_s32(q1s32, 14);
d12s16 = vqrshrn_n_s32(q11s32, 14);
d13s16 = vqrshrn_n_s32(q0s32, 14);
*q10s16 = vcombine_s16(d20s16, d21s16);
q6s16 = vcombine_s16(d12s16, d13s16);
q5s16 = vdupq_n_s16(0);
*q9s16 = vsubq_s16(q5s16, *q9s16);
*q11s16 = vsubq_s16(q5s16, q2s16);
*q13s16 = vsubq_s16(q5s16, q6s16);
*q15s16 = vsubq_s16(q5s16, q4s16);
return;
}
void vp10_iht8x8_64_add_neon(const tran_low_t *input, uint8_t *dest,
int dest_stride, int tx_type) {
int i;
uint8_t *d1, *d2;
uint8x8_t d0u8, d1u8, d2u8, d3u8;
uint64x1_t d0u64, d1u64, d2u64, d3u64;
int16x8_t q8s16, q9s16, q10s16, q11s16, q12s16, q13s16, q14s16, q15s16;
uint16x8_t q8u16, q9u16, q10u16, q11u16;
q8s16 = vld1q_s16(input);
q9s16 = vld1q_s16(input + 8);
q10s16 = vld1q_s16(input + 8 * 2);
q11s16 = vld1q_s16(input + 8 * 3);
q12s16 = vld1q_s16(input + 8 * 4);
q13s16 = vld1q_s16(input + 8 * 5);
q14s16 = vld1q_s16(input + 8 * 6);
q15s16 = vld1q_s16(input + 8 * 7);
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
switch (tx_type) {
case 0: // idct_idct is not supported. Fall back to C
vp10_iht8x8_64_add_c(input, dest, dest_stride, tx_type);
return;
break;
case 1: // iadst_idct
// generate IDCT constants
// GENERATE_IDCT_CONSTANTS
// first transform rows
IDCT8x8_1D(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
// transpose the matrix
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
// generate IADST constants
// GENERATE_IADST_CONSTANTS
// then transform columns
IADST8X8_1D(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
break;
case 2: // idct_iadst
// generate IADST constants
// GENERATE_IADST_CONSTANTS
// first transform rows
IADST8X8_1D(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
// transpose the matrix
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
// generate IDCT constants
// GENERATE_IDCT_CONSTANTS
// then transform columns
IDCT8x8_1D(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
break;
case 3: // iadst_iadst
// generate IADST constants
// GENERATE_IADST_CONSTANTS
// first transform rows
IADST8X8_1D(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
// transpose the matrix
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
// then transform columns
IADST8X8_1D(&q8s16, &q9s16, &q10s16, &q11s16,
&q12s16, &q13s16, &q14s16, &q15s16);
break;
default: // iadst_idct
assert(0);
break;
}
q8s16 = vrshrq_n_s16(q8s16, 5);
q9s16 = vrshrq_n_s16(q9s16, 5);
q10s16 = vrshrq_n_s16(q10s16, 5);
q11s16 = vrshrq_n_s16(q11s16, 5);
q12s16 = vrshrq_n_s16(q12s16, 5);
q13s16 = vrshrq_n_s16(q13s16, 5);
q14s16 = vrshrq_n_s16(q14s16, 5);
q15s16 = vrshrq_n_s16(q15s16, 5);
for (d1 = d2 = dest, i = 0; i < 2; i++) {
if (i != 0) {
q8s16 = q12s16;
q9s16 = q13s16;
q10s16 = q14s16;
q11s16 = q15s16;
}
d0u64 = vld1_u64((uint64_t *)d1);
d1 += dest_stride;
d1u64 = vld1_u64((uint64_t *)d1);
d1 += dest_stride;
d2u64 = vld1_u64((uint64_t *)d1);
d1 += dest_stride;
d3u64 = vld1_u64((uint64_t *)d1);
d1 += dest_stride;
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16),
vreinterpret_u8_u64(d0u64));
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16),
vreinterpret_u8_u64(d1u64));
q10u16 = vaddw_u8(vreinterpretq_u16_s16(q10s16),
vreinterpret_u8_u64(d2u64));
q11u16 = vaddw_u8(vreinterpretq_u16_s16(q11s16),
vreinterpret_u8_u64(d3u64));
d0u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
d1u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d0u8));
d2 += dest_stride;
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d1u8));
d2 += dest_stride;
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
d2 += dest_stride;
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d3u8));
d2 += dest_stride;
}
return;
}

136
vp10/common/blockd.c Normal file
View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp10/common/blockd.h"
PREDICTION_MODE vp10_left_block_mode(const MODE_INFO *cur_mi,
const MODE_INFO *left_mi, int b) {
if (b == 0 || b == 2) {
if (!left_mi || is_inter_block(&left_mi->mbmi))
return DC_PRED;
return get_y_mode(left_mi, b + 1);
} else {
assert(b == 1 || b == 3);
return cur_mi->bmi[b - 1].as_mode;
}
}
PREDICTION_MODE vp10_above_block_mode(const MODE_INFO *cur_mi,
const MODE_INFO *above_mi, int b) {
if (b == 0 || b == 1) {
if (!above_mi || is_inter_block(&above_mi->mbmi))
return DC_PRED;
return get_y_mode(above_mi, b + 2);
} else {
assert(b == 2 || b == 3);
return cur_mi->bmi[b - 2].as_mode;
}
}
void vp10_foreach_transformed_block_in_plane(
const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
foreach_transformed_block_visitor visit, void *arg) {
const struct macroblockd_plane *const pd = &xd->plane[plane];
const MB_MODE_INFO* mbmi = &xd->mi[0]->mbmi;
// 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)
: 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];
const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
const int step = 1 << (tx_size << 1);
int i = 0, r, c;
// If mb_to_right_edge is < 0 we are in a situation in which
// the current block size extends into the UMV and we won't
// visit the sub blocks that are wholly within the UMV.
const int max_blocks_wide = num_4x4_w + (xd->mb_to_right_edge >= 0 ? 0 :
xd->mb_to_right_edge >> (5 + pd->subsampling_x));
const int max_blocks_high = num_4x4_h + (xd->mb_to_bottom_edge >= 0 ? 0 :
xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
const int extra_step = ((num_4x4_w - max_blocks_wide) >> tx_size) * step;
// Keep track of the row and column of the blocks we use so that we know
// if we are in the unrestricted motion border.
for (r = 0; r < max_blocks_high; r += (1 << tx_size)) {
// Skip visiting the sub blocks that are wholly within the UMV.
for (c = 0; c < max_blocks_wide; c += (1 << tx_size)) {
visit(plane, i, plane_bsize, tx_size, arg);
i += step;
}
i += extra_step;
}
}
void vp10_foreach_transformed_block(const MACROBLOCKD* const xd,
BLOCK_SIZE bsize,
foreach_transformed_block_visitor visit,
void *arg) {
int plane;
for (plane = 0; plane < MAX_MB_PLANE; ++plane)
vp10_foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
}
void vp10_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int has_eob,
int aoff, int loff) {
ENTROPY_CONTEXT *const a = pd->above_context + aoff;
ENTROPY_CONTEXT *const l = pd->left_context + loff;
const int tx_size_in_blocks = 1 << tx_size;
// above
if (has_eob && xd->mb_to_right_edge < 0) {
int i;
const int blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize] +
(xd->mb_to_right_edge >> (5 + pd->subsampling_x));
int above_contexts = tx_size_in_blocks;
if (above_contexts + aoff > blocks_wide)
above_contexts = blocks_wide - aoff;
for (i = 0; i < above_contexts; ++i)
a[i] = has_eob;
for (i = above_contexts; i < tx_size_in_blocks; ++i)
a[i] = 0;
} else {
memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
}
// left
if (has_eob && xd->mb_to_bottom_edge < 0) {
int i;
const int blocks_high = num_4x4_blocks_high_lookup[plane_bsize] +
(xd->mb_to_bottom_edge >> (5 + pd->subsampling_y));
int left_contexts = tx_size_in_blocks;
if (left_contexts + loff > blocks_high)
left_contexts = blocks_high - loff;
for (i = 0; i < left_contexts; ++i)
l[i] = has_eob;
for (i = left_contexts; i < tx_size_in_blocks; ++i)
l[i] = 0;
} else {
memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * tx_size_in_blocks);
}
}
void vp10_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y) {
int i;
for (i = 0; i < MAX_MB_PLANE; i++) {
xd->plane[i].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y;
xd->plane[i].subsampling_x = i ? ss_x : 0;
xd->plane[i].subsampling_y = i ? ss_y : 0;
}
}

311
vp10/common/blockd.h Normal file
View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_BLOCKD_H_
#define VP10_COMMON_BLOCKD_H_
#include "./vpx_config.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_ports/mem.h"
#include "vpx_scale/yv12config.h"
#include "vp10/common/common_data.h"
#include "vp10/common/entropy.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/mv.h"
#include "vp10/common/scale.h"
#include "vp10/common/seg_common.h"
#include "vp10/common/tile_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_MB_PLANE 3
typedef enum {
KEY_FRAME = 0,
INTER_FRAME = 1,
FRAME_TYPES,
} FRAME_TYPE;
static INLINE int is_inter_mode(PREDICTION_MODE mode) {
return mode >= NEARESTMV && mode <= NEWMV;
}
/* For keyframes, intra block modes are predicted by the (already decoded)
modes for the Y blocks to the left and above us; for interframes, there
is a single probability table. */
typedef struct {
PREDICTION_MODE as_mode;
int_mv as_mv[2]; // first, second inter predictor motion vectors
} b_mode_info;
// Note that the rate-distortion optimization loop, bit-stream writer, and
// decoder implementation modules critically rely on the defined entry values
// specified herein. They should be refactored concurrently.
#define NONE -1
#define INTRA_FRAME 0
#define LAST_FRAME 1
#define GOLDEN_FRAME 2
#define ALTREF_FRAME 3
#define MAX_REF_FRAMES 4
typedef int8_t MV_REFERENCE_FRAME;
// This structure now relates to 8x8 block regions.
typedef struct {
// Common for both INTER and INTRA blocks
BLOCK_SIZE sb_type;
PREDICTION_MODE mode;
TX_SIZE tx_size;
int8_t skip;
int8_t segment_id;
int8_t seg_id_predicted; // valid only when temporal_update is enabled
// Only for INTRA blocks
PREDICTION_MODE uv_mode;
// Only for INTER blocks
INTERP_FILTER interp_filter;
MV_REFERENCE_FRAME ref_frame[2];
// TODO(slavarnway): Delete and use bmi[3].as_mv[] instead.
int_mv mv[2];
} MB_MODE_INFO;
typedef struct MODE_INFO {
MB_MODE_INFO mbmi;
b_mode_info bmi[4];
} MODE_INFO;
static INLINE PREDICTION_MODE get_y_mode(const MODE_INFO *mi, int block) {
return mi->mbmi.sb_type < BLOCK_8X8 ? mi->bmi[block].as_mode
: mi->mbmi.mode;
}
static INLINE int is_inter_block(const MB_MODE_INFO *mbmi) {
return mbmi->ref_frame[0] > INTRA_FRAME;
}
static INLINE int has_second_ref(const MB_MODE_INFO *mbmi) {
return mbmi->ref_frame[1] > INTRA_FRAME;
}
PREDICTION_MODE vp10_left_block_mode(const MODE_INFO *cur_mi,
const MODE_INFO *left_mi, int b);
PREDICTION_MODE vp10_above_block_mode(const MODE_INFO *cur_mi,
const MODE_INFO *above_mi, int b);
enum mv_precision {
MV_PRECISION_Q3,
MV_PRECISION_Q4
};
struct buf_2d {
uint8_t *buf;
int stride;
};
struct macroblockd_plane {
tran_low_t *dqcoeff;
PLANE_TYPE plane_type;
int subsampling_x;
int subsampling_y;
struct buf_2d dst;
struct buf_2d pre[2];
ENTROPY_CONTEXT *above_context;
ENTROPY_CONTEXT *left_context;
int16_t seg_dequant[MAX_SEGMENTS][2];
// number of 4x4s in current block
uint16_t n4_w, n4_h;
// log2 of n4_w, n4_h
uint8_t n4_wl, n4_hl;
// encoder
const int16_t *dequant;
};
#define BLOCK_OFFSET(x, i) ((x) + (i) * 16)
typedef struct RefBuffer {
// TODO(dkovalev): idx is not really required and should be removed, now it
// is used in vp10_onyxd_if.c
int idx;
YV12_BUFFER_CONFIG *buf;
struct scale_factors sf;
} RefBuffer;
typedef struct macroblockd {
struct macroblockd_plane plane[MAX_MB_PLANE];
uint8_t bmode_blocks_wl;
uint8_t bmode_blocks_hl;
FRAME_COUNTS *counts;
TileInfo tile;
int mi_stride;
MODE_INFO **mi;
MODE_INFO *left_mi;
MODE_INFO *above_mi;
MB_MODE_INFO *left_mbmi;
MB_MODE_INFO *above_mbmi;
int up_available;
int left_available;
const vpx_prob (*partition_probs)[PARTITION_TYPES - 1];
/* Distance of MB away from frame edges */
int mb_to_left_edge;
int mb_to_right_edge;
int mb_to_top_edge;
int mb_to_bottom_edge;
FRAME_CONTEXT *fc;
int frame_parallel_decoding_mode;
/* pointers to reference frames */
RefBuffer *block_refs[2];
/* pointer to current frame */
const YV12_BUFFER_CONFIG *cur_buf;
ENTROPY_CONTEXT *above_context[MAX_MB_PLANE];
ENTROPY_CONTEXT left_context[MAX_MB_PLANE][16];
PARTITION_CONTEXT *above_seg_context;
PARTITION_CONTEXT left_seg_context[8];
#if CONFIG_VP9_HIGHBITDEPTH
/* Bit depth: 8, 10, 12 */
int bd;
#endif
int lossless;
int corrupted;
struct vpx_internal_error_info *error_info;
} MACROBLOCKD;
static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
PARTITION_TYPE partition) {
return subsize_lookup[partition][bsize];
}
static const TX_TYPE intra_mode_to_tx_type_lookup[INTRA_MODES] = {
DCT_DCT, // DC
ADST_DCT, // V
DCT_ADST, // H
DCT_DCT, // D45
ADST_ADST, // D135
ADST_DCT, // D117
DCT_ADST, // D153
DCT_ADST, // D207
ADST_DCT, // D63
ADST_ADST, // TM
};
static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type, const MACROBLOCKD *xd,
int block_idx) {
const MODE_INFO *const mi = xd->mi[0];
const MB_MODE_INFO *const mbmi = &mi->mbmi;
if (plane_type != PLANE_TYPE_Y || xd->lossless || is_inter_block(mbmi) ||
mbmi->tx_size >= TX_32X32)
return DCT_DCT;
return intra_mode_to_tx_type_lookup[get_y_mode(mi, block_idx)];
}
void vp10_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) {
if (bsize < BLOCK_8X8) {
return TX_4X4;
} else {
const BLOCK_SIZE plane_bsize = ss_size_lookup[bsize][xss][yss];
return VPXMIN(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 BLOCK_SIZE get_plane_block_size(BLOCK_SIZE bsize,
const struct macroblockd_plane *pd) {
return ss_size_lookup[bsize][pd->subsampling_x][pd->subsampling_y];
}
static INLINE void reset_skip_context(MACROBLOCKD *xd, BLOCK_SIZE bsize) {
int i;
for (i = 0; i < MAX_MB_PLANE; i++) {
struct macroblockd_plane *const pd = &xd->plane[i];
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
memset(pd->above_context, 0,
sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide_lookup[plane_bsize]);
memset(pd->left_context, 0,
sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high_lookup[plane_bsize]);
}
}
static INLINE const vpx_prob *get_y_mode_probs(const MODE_INFO *mi,
const MODE_INFO *above_mi,
const MODE_INFO *left_mi,
int block) {
const PREDICTION_MODE above = vp10_above_block_mode(mi, above_mi, block);
const PREDICTION_MODE left = vp10_left_block_mode(mi, left_mi, block);
return vp10_kf_y_mode_prob[above][left];
}
typedef void (*foreach_transformed_block_visitor)(int plane, int block,
BLOCK_SIZE plane_bsize,
TX_SIZE tx_size,
void *arg);
void vp10_foreach_transformed_block_in_plane(
const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
foreach_transformed_block_visitor visit, void *arg);
void vp10_foreach_transformed_block(
const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
foreach_transformed_block_visitor visit, void *arg);
static INLINE void txfrm_block_to_raster_xy(BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, int block,
int *x, int *y) {
const int bwl = b_width_log2_lookup[plane_bsize];
const int tx_cols_log2 = bwl - tx_size;
const int tx_cols = 1 << tx_cols_log2;
const int raster_mb = block >> (tx_size << 1);
*x = (raster_mb & (tx_cols - 1)) << tx_size;
*y = (raster_mb >> tx_cols_log2) << tx_size;
}
void vp10_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int has_eob,
int aoff, int loff);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_BLOCKD_H_

75
vp10/common/common.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_COMMON_H_
#define VP10_COMMON_COMMON_H_
/* Interface header for common constant data structures and lookup tables */
#include <assert.h>
#include "./vpx_config.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx/vpx_integer.h"
#include "vpx_ports/bitops.h"
#ifdef __cplusplus
extern "C" {
#endif
// Only need this for fixed-size arrays, for structs just assign.
#define vp10_copy(dest, src) { \
assert(sizeof(dest) == sizeof(src)); \
memcpy(dest, src, sizeof(src)); \
}
// Use this for variably-sized arrays.
#define vp10_copy_array(dest, src, n) { \
assert(sizeof(*dest) == sizeof(*src)); \
memcpy(dest, src, n * sizeof(*src)); \
}
#define vp10_zero(dest) memset(&(dest), 0, sizeof(dest))
#define vp10_zero_array(dest, n) memset(dest, 0, n * sizeof(*dest))
static INLINE int get_unsigned_bits(unsigned int num_values) {
return num_values > 0 ? get_msb(num_values) + 1 : 0;
}
#if CONFIG_DEBUG
#define CHECK_MEM_ERROR(cm, lval, expr) do { \
lval = (expr); \
if (!lval) \
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, \
"Failed to allocate "#lval" at %s:%d", \
__FILE__, __LINE__); \
} while (0)
#else
#define CHECK_MEM_ERROR(cm, lval, expr) do { \
lval = (expr); \
if (!lval) \
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, \
"Failed to allocate "#lval); \
} while (0)
#endif
// TODO(yaowu: validate the usage of these codes or develop new ones.)
#define VP10_SYNC_CODE_0 0x49
#define VP10_SYNC_CODE_1 0x83
#define VP10_SYNC_CODE_2 0x43
#define VP9_FRAME_MARKER 0x2
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_COMMON_H_

175
vp10/common/common_data.h Normal file
View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_COMMON_DATA_H_
#define VP10_COMMON_COMMON_DATA_H_
#include "vp10/common/enums.h"
#include "vpx/vpx_integer.h"
#include "vpx_dsp/vpx_dsp_common.h"
#ifdef __cplusplus
extern "C" {
#endif
// Log 2 conversion lookup tables for block width and height
static const uint8_t b_width_log2_lookup[BLOCK_SIZES] =
{0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4};
static const uint8_t b_height_log2_lookup[BLOCK_SIZES] =
{0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4};
static const uint8_t num_4x4_blocks_wide_lookup[BLOCK_SIZES] =
{1, 1, 2, 2, 2, 4, 4, 4, 8, 8, 8, 16, 16};
static const uint8_t num_4x4_blocks_high_lookup[BLOCK_SIZES] =
{1, 2, 1, 2, 4, 2, 4, 8, 4, 8, 16, 8, 16};
// Log 2 conversion lookup tables for modeinfo width and height
static const uint8_t mi_width_log2_lookup[BLOCK_SIZES] =
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3};
static const uint8_t num_8x8_blocks_wide_lookup[BLOCK_SIZES] =
{1, 1, 1, 1, 1, 2, 2, 2, 4, 4, 4, 8, 8};
static const uint8_t num_8x8_blocks_high_lookup[BLOCK_SIZES] =
{1, 1, 1, 1, 2, 1, 2, 4, 2, 4, 8, 4, 8};
// VPXMIN(3, VPXMIN(b_width_log2(bsize), b_height_log2(bsize)))
static const uint8_t size_group_lookup[BLOCK_SIZES] =
{0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3};
static const uint8_t num_pels_log2_lookup[BLOCK_SIZES] =
{4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12};
static const PARTITION_TYPE partition_lookup[][BLOCK_SIZES] = {
{ // 4X4
// 4X4, 4X8,8X4,8X8,8X16,16X8,16X16,16X32,32X16,32X32,32X64,64X32,64X64
PARTITION_NONE, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID
}, { // 8X8
// 4X4, 4X8,8X4,8X8,8X16,16X8,16X16,16X32,32X16,32X32,32X64,64X32,64X64
PARTITION_SPLIT, PARTITION_VERT, PARTITION_HORZ, PARTITION_NONE,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID
}, { // 16X16
// 4X4, 4X8,8X4,8X8,8X16,16X8,16X16,16X32,32X16,32X32,32X64,64X32,64X64
PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT,
PARTITION_VERT, PARTITION_HORZ, PARTITION_NONE, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID
}, { // 32X32
// 4X4, 4X8,8X4,8X8,8X16,16X8,16X16,16X32,32X16,32X32,32X64,64X32,64X64
PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT,
PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_VERT,
PARTITION_HORZ, PARTITION_NONE, PARTITION_INVALID,
PARTITION_INVALID, PARTITION_INVALID
}, { // 64X64
// 4X4, 4X8,8X4,8X8,8X16,16X8,16X16,16X32,32X16,32X32,32X64,64X32,64X64
PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT,
PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_SPLIT,
PARTITION_SPLIT, PARTITION_SPLIT, PARTITION_VERT, PARTITION_HORZ,
PARTITION_NONE
}
};
static const BLOCK_SIZE subsize_lookup[PARTITION_TYPES][BLOCK_SIZES] = {
{ // PARTITION_NONE
BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8, BLOCK_8X16, BLOCK_16X8,
BLOCK_16X16, BLOCK_16X32, BLOCK_32X16,
BLOCK_32X32, BLOCK_32X64, BLOCK_64X32,
BLOCK_64X64,
}, { // PARTITION_HORZ
BLOCK_INVALID, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_8X4, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_16X8, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_32X16, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_64X32,
}, { // PARTITION_VERT
BLOCK_INVALID, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_4X8, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_8X16, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_16X32, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_32X64,
}, { // PARTITION_SPLIT
BLOCK_INVALID, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_4X4, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_8X8, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_16X16, BLOCK_INVALID, BLOCK_INVALID,
BLOCK_32X32,
}
};
static const TX_SIZE max_txsize_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
};
static const BLOCK_SIZE txsize_to_bsize[TX_SIZES] = {
BLOCK_4X4, // TX_4X4
BLOCK_8X8, // TX_8X8
BLOCK_16X16, // TX_16X16
BLOCK_32X32, // TX_32X32
};
static const TX_SIZE tx_mode_to_biggest_tx_size[TX_MODES] = {
TX_4X4, // ONLY_4X4
TX_8X8, // ALLOW_8X8
TX_16X16, // ALLOW_16X16
TX_32X32, // ALLOW_32X32
TX_32X32, // TX_MODE_SELECT
};
static const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2] = {
// ss_x == 0 ss_x == 0 ss_x == 1 ss_x == 1
// ss_y == 0 ss_y == 1 ss_y == 0 ss_y == 1
{{BLOCK_4X4, BLOCK_INVALID}, {BLOCK_INVALID, BLOCK_INVALID}},
{{BLOCK_4X8, BLOCK_4X4}, {BLOCK_INVALID, BLOCK_INVALID}},
{{BLOCK_8X4, BLOCK_INVALID}, {BLOCK_4X4, BLOCK_INVALID}},
{{BLOCK_8X8, BLOCK_8X4}, {BLOCK_4X8, BLOCK_4X4}},
{{BLOCK_8X16, BLOCK_8X8}, {BLOCK_INVALID, BLOCK_4X8}},
{{BLOCK_16X8, BLOCK_INVALID}, {BLOCK_8X8, BLOCK_8X4}},
{{BLOCK_16X16, BLOCK_16X8}, {BLOCK_8X16, BLOCK_8X8}},
{{BLOCK_16X32, BLOCK_16X16}, {BLOCK_INVALID, BLOCK_8X16}},
{{BLOCK_32X16, BLOCK_INVALID}, {BLOCK_16X16, BLOCK_16X8}},
{{BLOCK_32X32, BLOCK_32X16}, {BLOCK_16X32, BLOCK_16X16}},
{{BLOCK_32X64, BLOCK_32X32}, {BLOCK_INVALID, BLOCK_16X32}},
{{BLOCK_64X32, BLOCK_INVALID}, {BLOCK_32X32, BLOCK_32X16}},
{{BLOCK_64X64, BLOCK_64X32}, {BLOCK_32X64, BLOCK_32X32}},
};
// 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
static const struct {
PARTITION_CONTEXT above;
PARTITION_CONTEXT left;
} partition_context_lookup[BLOCK_SIZES]= {
{15, 15}, // 4X4 - {0b1111, 0b1111}
{15, 14}, // 4X8 - {0b1111, 0b1110}
{14, 15}, // 8X4 - {0b1110, 0b1111}
{14, 14}, // 8X8 - {0b1110, 0b1110}
{14, 12}, // 8X16 - {0b1110, 0b1100}
{12, 14}, // 16X8 - {0b1100, 0b1110}
{12, 12}, // 16X16 - {0b1100, 0b1100}
{12, 8 }, // 16X32 - {0b1100, 0b1000}
{8, 12}, // 32X16 - {0b1000, 0b1100}
{8, 8 }, // 32X32 - {0b1000, 0b1000}
{8, 0 }, // 32X64 - {0b1000, 0b0000}
{0, 8 }, // 64X32 - {0b0000, 0b1000}
{0, 0 }, // 64X64 - {0b0000, 0b0000}
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_COMMON_DATA_H_

91
vp10/common/debugmodes.c Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdio.h>
#include "vp10/common/blockd.h"
#include "vp10/common/onyxc_int.h"
static void log_frame_info(VP10_COMMON *cm, const char *str, FILE *f) {
fprintf(f, "%s", str);
fprintf(f, "(Frame %d, Show:%d, Q:%d): \n", cm->current_video_frame,
cm->show_frame, cm->base_qindex);
}
/* This function dereferences a pointer to the mbmi structure
* and uses the passed in member offset to print out the value of an integer
* for each mbmi member value in the mi structure.
*/
static void print_mi_data(VP10_COMMON *cm, FILE *file, const char *descriptor,
size_t member_offset) {
int mi_row, mi_col;
MODE_INFO **mi = cm->mi_grid_visible;
int rows = cm->mi_rows;
int cols = cm->mi_cols;
char prefix = descriptor[0];
log_frame_info(cm, descriptor, file);
for (mi_row = 0; mi_row < rows; mi_row++) {
fprintf(file, "%c ", prefix);
for (mi_col = 0; mi_col < cols; mi_col++) {
fprintf(file, "%2d ",
*((int*) ((char *) (&mi[0]->mbmi) +
member_offset)));
mi++;
}
fprintf(file, "\n");
mi += 8;
}
fprintf(file, "\n");
}
void vp10_print_modes_and_motion_vectors(VP10_COMMON *cm, const char *file) {
int mi_row;
int mi_col;
FILE *mvs = fopen(file, "a");
MODE_INFO **mi = cm->mi_grid_visible;
int rows = cm->mi_rows;
int cols = cm->mi_cols;
print_mi_data(cm, mvs, "Partitions:", offsetof(MB_MODE_INFO, sb_type));
print_mi_data(cm, mvs, "Modes:", offsetof(MB_MODE_INFO, mode));
print_mi_data(cm, mvs, "Ref frame:", offsetof(MB_MODE_INFO, ref_frame[0]));
print_mi_data(cm, mvs, "Transform:", offsetof(MB_MODE_INFO, tx_size));
print_mi_data(cm, mvs, "UV Modes:", offsetof(MB_MODE_INFO, uv_mode));
// output skip infomation.
log_frame_info(cm, "Skips:", mvs);
for (mi_row = 0; mi_row < rows; mi_row++) {
fprintf(mvs, "S ");
for (mi_col = 0; mi_col < cols; mi_col++) {
fprintf(mvs, "%2d ", mi[0]->mbmi.skip);
mi++;
}
fprintf(mvs, "\n");
mi += 8;
}
fprintf(mvs, "\n");
// output motion vectors.
log_frame_info(cm, "Vectors ", mvs);
mi = cm->mi_grid_visible;
for (mi_row = 0; mi_row < rows; mi_row++) {
fprintf(mvs, "V ");
for (mi_col = 0; mi_col < cols; mi_col++) {
fprintf(mvs, "%4d:%4d ", mi[0]->mbmi.mv[0].as_mv.row,
mi[0]->mbmi.mv[0].as_mv.col);
mi++;
}
fprintf(mvs, "\n");
mi += 8;
}
fprintf(mvs, "\n");
fclose(mvs);
}

1095
vp10/common/entropy.c Normal file

File diff suppressed because it is too large Load Diff

221
vp10/common/entropy.h Normal file
View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_ENTROPY_H_
#define VP10_COMMON_ENTROPY_H_
#include "vpx/vpx_integer.h"
#include "vpx_dsp/prob.h"
#include "vp10/common/ans.h"
#include "vp10/common/common.h"
#include "vp10/common/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DIFF_UPDATE_PROB 252
// Coefficient token alphabet
#define ZERO_TOKEN 0 // 0 Extra Bits 0+0
#define ONE_TOKEN 1 // 1 Extra Bits 0+1
#define TWO_TOKEN 2 // 2 Extra Bits 0+1
#define THREE_TOKEN 3 // 3 Extra Bits 0+1
#define FOUR_TOKEN 4 // 4 Extra Bits 0+1
#define CATEGORY1_TOKEN 5 // 5-6 Extra Bits 1+1
#define CATEGORY2_TOKEN 6 // 7-10 Extra Bits 2+1
#define CATEGORY3_TOKEN 7 // 11-18 Extra Bits 3+1
#define CATEGORY4_TOKEN 8 // 19-34 Extra Bits 4+1
#define CATEGORY5_TOKEN 9 // 35-66 Extra Bits 5+1
#define CATEGORY6_TOKEN 10 // 67+ Extra Bits 14+1
#define EOB_TOKEN 11 // EOB Extra Bits 0+0
#define ENTROPY_TOKENS 12
#define ENTROPY_NODES 11
DECLARE_ALIGNED(16, extern const uint8_t, vp10_pt_energy_class[ENTROPY_TOKENS]);
#define CAT1_MIN_VAL 5
#define CAT2_MIN_VAL 7
#define CAT3_MIN_VAL 11
#define CAT4_MIN_VAL 19
#define CAT5_MIN_VAL 35
#define CAT6_MIN_VAL 67
// Extra bit probabilities.
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat1_prob[1]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat2_prob[2]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat3_prob[3]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat4_prob[4]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat5_prob[5]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat6_prob[14]);
#if CONFIG_VP9_HIGHBITDEPTH
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat1_prob_high10[1]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat2_prob_high10[2]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat3_prob_high10[3]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat4_prob_high10[4]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat5_prob_high10[5]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat6_prob_high10[16]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat1_prob_high12[1]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat2_prob_high12[2]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat3_prob_high12[3]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat4_prob_high12[4]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat5_prob_high12[5]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_cat6_prob_high12[18]);
#endif // CONFIG_VP9_HIGHBITDEPTH
#define EOB_MODEL_TOKEN 3
typedef struct {
const vpx_tree_index *tree;
const vpx_prob *prob;
int len;
int base_val;
const int16_t *cost;
} vp10_extra_bit;
// indexed by token value
extern const vp10_extra_bit vp10_extra_bits[ENTROPY_TOKENS];
#if CONFIG_VP9_HIGHBITDEPTH
extern const vp10_extra_bit vp10_extra_bits_high10[ENTROPY_TOKENS];
extern const vp10_extra_bit vp10_extra_bits_high12[ENTROPY_TOKENS];
#endif // CONFIG_VP9_HIGHBITDEPTH
#define DCT_MAX_VALUE 16384
#if CONFIG_VP9_HIGHBITDEPTH
#define DCT_MAX_VALUE_HIGH10 65536
#define DCT_MAX_VALUE_HIGH12 262144
#endif // CONFIG_VP9_HIGHBITDEPTH
/* Coefficients are predicted via a 3-dimensional probability table. */
#define REF_TYPES 2 // intra=0, inter=1
/* Middle dimension reflects the coefficient position within the transform. */
#define COEF_BANDS 6
/* Inside dimension is measure of nearby complexity, that reflects the energy
of nearby coefficients are nonzero. For the first coefficient (DC, unless
block type is 0), we look at the (already encoded) blocks above and to the
left of the current block. The context index is then the number (0,1,or 2)
of these blocks having nonzero coefficients.
After decoding a coefficient, the measure is determined by the size of the
most recently decoded coefficient.
Note that the intuitive meaning of this measure changes as coefficients
are decoded, e.g., prior to the first token, a zero means that my neighbors
are empty while, after the first token, because of the use of end-of-block,
a zero means we just decoded a zero and hence guarantees that a non-zero
coefficient will appear later in this block. However, this shift
in meaning is perfectly OK because our context depends also on the
coefficient band (and since zigzag positions 0, 1, and 2 are in
distinct bands). */
#define COEFF_CONTEXTS 6
#define BAND_COEFF_CONTEXTS(band) ((band) == 0 ? 3 : COEFF_CONTEXTS)
// #define ENTROPY_STATS
typedef unsigned int vp10_coeff_count[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS]
[ENTROPY_TOKENS];
typedef unsigned int vp10_coeff_stats[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS]
[ENTROPY_NODES][2];
#define SUBEXP_PARAM 4 /* Subexponential code parameter */
#define MODULUS_PARAM 13 /* Modulus parameter */
struct VP10Common;
void vp10_default_coef_probs(struct VP10Common *cm);
void vp10_adapt_coef_probs(struct VP10Common *cm);
// This is the index in the scan order beyond which all coefficients for
// 8x8 transform and above are in the top band.
// This macro is currently unused but may be used by certain implementations
#define MAXBAND_INDEX 21
DECLARE_ALIGNED(16, extern const uint8_t, vp10_coefband_trans_8x8plus[1024]);
DECLARE_ALIGNED(16, extern const uint8_t, vp10_coefband_trans_4x4[16]);
static INLINE const uint8_t *get_band_translate(TX_SIZE tx_size) {
return tx_size == TX_4X4 ? vp10_coefband_trans_4x4
: vp10_coefband_trans_8x8plus;
}
// 128 lists of probabilities are stored for the following ONE node probs:
// 1, 3, 5, 7, ..., 253, 255
// In between probabilities are interpolated linearly
#define COEFF_PROB_MODELS 256
#define UNCONSTRAINED_NODES 3
#define PIVOT_NODE 2 // which node is pivot
#define MODEL_NODES (ENTROPY_NODES - UNCONSTRAINED_NODES)
extern const vpx_tree_index vp10_coef_con_tree[TREE_SIZE(ENTROPY_TOKENS)];
extern const vpx_prob vp10_pareto8_full[COEFF_PROB_MODELS][MODEL_NODES];
extern const vpx_prob vp10_pareto8_token_probs[COEFF_PROB_MODELS - 1][ENTROPY_TOKENS - 2];
void vp10_build_pareto8_dec_tab(
const vpx_prob token_probs[COEFF_PROB_MODELS - 1][ENTROPY_TOKENS - 2],
struct rans_dec_sym dec_tab[COEFF_PROB_MODELS - 1][256]);
typedef vpx_prob vp10_coeff_probs_model[REF_TYPES][COEF_BANDS]
[COEFF_CONTEXTS][UNCONSTRAINED_NODES];
typedef unsigned int vp10_coeff_count_model[REF_TYPES][COEF_BANDS]
[COEFF_CONTEXTS]
[UNCONSTRAINED_NODES + 1];
void vp10_model_to_full_probs(const vpx_prob *model, vpx_prob *full);
typedef char ENTROPY_CONTEXT;
static INLINE int combine_entropy_contexts(ENTROPY_CONTEXT a,
ENTROPY_CONTEXT b) {
return (a != 0) + (b != 0);
}
static INLINE int get_entropy_context(TX_SIZE tx_size, const ENTROPY_CONTEXT *a,
const ENTROPY_CONTEXT *l) {
ENTROPY_CONTEXT above_ec = 0, left_ec = 0;
switch (tx_size) {
case TX_4X4:
above_ec = a[0] != 0;
left_ec = l[0] != 0;
break;
case TX_8X8:
above_ec = !!*(const uint16_t *)a;
left_ec = !!*(const uint16_t *)l;
break;
case TX_16X16:
above_ec = !!*(const uint32_t *)a;
left_ec = !!*(const uint32_t *)l;
break;
case TX_32X32:
above_ec = !!*(const uint64_t *)a;
left_ec = !!*(const uint64_t *)l;
break;
default:
assert(0 && "Invalid transform size.");
break;
}
return combine_entropy_contexts(above_ec, left_ec);
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_ENTROPY_H_

469
vp10/common/entropymode.c Normal file
View File

@@ -0,0 +1,469 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_mem/vpx_mem.h"
#include "vp10/common/onyxc_int.h"
#include "vp10/common/seg_common.h"
const vpx_prob vp10_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1] = {
{ // above = dc
{ 137, 30, 42, 148, 151, 207, 70, 52, 91 }, // left = dc
{ 92, 45, 102, 136, 116, 180, 74, 90, 100 }, // left = v
{ 73, 32, 19, 187, 222, 215, 46, 34, 100 }, // left = h
{ 91, 30, 32, 116, 121, 186, 93, 86, 94 }, // left = d45
{ 72, 35, 36, 149, 68, 206, 68, 63, 105 }, // left = d135
{ 73, 31, 28, 138, 57, 124, 55, 122, 151 }, // left = d117
{ 67, 23, 21, 140, 126, 197, 40, 37, 171 }, // left = d153
{ 86, 27, 28, 128, 154, 212, 45, 43, 53 }, // left = d207
{ 74, 32, 27, 107, 86, 160, 63, 134, 102 }, // left = d63
{ 59, 67, 44, 140, 161, 202, 78, 67, 119 } // left = tm
}, { // above = v
{ 63, 36, 126, 146, 123, 158, 60, 90, 96 }, // left = dc
{ 43, 46, 168, 134, 107, 128, 69, 142, 92 }, // left = v
{ 44, 29, 68, 159, 201, 177, 50, 57, 77 }, // left = h
{ 58, 38, 76, 114, 97, 172, 78, 133, 92 }, // left = d45
{ 46, 41, 76, 140, 63, 184, 69, 112, 57 }, // left = d135
{ 38, 32, 85, 140, 46, 112, 54, 151, 133 }, // left = d117
{ 39, 27, 61, 131, 110, 175, 44, 75, 136 }, // left = d153
{ 52, 30, 74, 113, 130, 175, 51, 64, 58 }, // left = d207
{ 47, 35, 80, 100, 74, 143, 64, 163, 74 }, // left = d63
{ 36, 61, 116, 114, 128, 162, 80, 125, 82 } // left = tm
}, { // above = h
{ 82, 26, 26, 171, 208, 204, 44, 32, 105 }, // left = dc
{ 55, 44, 68, 166, 179, 192, 57, 57, 108 }, // left = v
{ 42, 26, 11, 199, 241, 228, 23, 15, 85 }, // left = h
{ 68, 42, 19, 131, 160, 199, 55, 52, 83 }, // left = d45
{ 58, 50, 25, 139, 115, 232, 39, 52, 118 }, // left = d135
{ 50, 35, 33, 153, 104, 162, 64, 59, 131 }, // left = d117
{ 44, 24, 16, 150, 177, 202, 33, 19, 156 }, // left = d153
{ 55, 27, 12, 153, 203, 218, 26, 27, 49 }, // left = d207
{ 53, 49, 21, 110, 116, 168, 59, 80, 76 }, // left = d63
{ 38, 72, 19, 168, 203, 212, 50, 50, 107 } // left = tm
}, { // above = d45
{ 103, 26, 36, 129, 132, 201, 83, 80, 93 }, // left = dc
{ 59, 38, 83, 112, 103, 162, 98, 136, 90 }, // left = v
{ 62, 30, 23, 158, 200, 207, 59, 57, 50 }, // left = h
{ 67, 30, 29, 84, 86, 191, 102, 91, 59 }, // left = d45
{ 60, 32, 33, 112, 71, 220, 64, 89, 104 }, // left = d135
{ 53, 26, 34, 130, 56, 149, 84, 120, 103 }, // left = d117
{ 53, 21, 23, 133, 109, 210, 56, 77, 172 }, // left = d153
{ 77, 19, 29, 112, 142, 228, 55, 66, 36 }, // left = d207
{ 61, 29, 29, 93, 97, 165, 83, 175, 162 }, // left = d63
{ 47, 47, 43, 114, 137, 181, 100, 99, 95 } // left = tm
}, { // above = d135
{ 69, 23, 29, 128, 83, 199, 46, 44, 101 }, // left = dc
{ 53, 40, 55, 139, 69, 183, 61, 80, 110 }, // left = v
{ 40, 29, 19, 161, 180, 207, 43, 24, 91 }, // left = h
{ 60, 34, 19, 105, 61, 198, 53, 64, 89 }, // left = d45
{ 52, 31, 22, 158, 40, 209, 58, 62, 89 }, // left = d135
{ 44, 31, 29, 147, 46, 158, 56, 102, 198 }, // left = d117
{ 35, 19, 12, 135, 87, 209, 41, 45, 167 }, // left = d153
{ 55, 25, 21, 118, 95, 215, 38, 39, 66 }, // left = d207
{ 51, 38, 25, 113, 58, 164, 70, 93, 97 }, // left = d63
{ 47, 54, 34, 146, 108, 203, 72, 103, 151 } // left = tm
}, { // above = d117
{ 64, 19, 37, 156, 66, 138, 49, 95, 133 }, // left = dc
{ 46, 27, 80, 150, 55, 124, 55, 121, 135 }, // left = v
{ 36, 23, 27, 165, 149, 166, 54, 64, 118 }, // left = h
{ 53, 21, 36, 131, 63, 163, 60, 109, 81 }, // left = d45
{ 40, 26, 35, 154, 40, 185, 51, 97, 123 }, // left = d135
{ 35, 19, 34, 179, 19, 97, 48, 129, 124 }, // left = d117
{ 36, 20, 26, 136, 62, 164, 33, 77, 154 }, // left = d153
{ 45, 18, 32, 130, 90, 157, 40, 79, 91 }, // left = d207
{ 45, 26, 28, 129, 45, 129, 49, 147, 123 }, // left = d63
{ 38, 44, 51, 136, 74, 162, 57, 97, 121 } // left = tm
}, { // above = d153
{ 75, 17, 22, 136, 138, 185, 32, 34, 166 }, // left = dc
{ 56, 39, 58, 133, 117, 173, 48, 53, 187 }, // left = v
{ 35, 21, 12, 161, 212, 207, 20, 23, 145 }, // left = h
{ 56, 29, 19, 117, 109, 181, 55, 68, 112 }, // left = d45
{ 47, 29, 17, 153, 64, 220, 59, 51, 114 }, // left = d135
{ 46, 16, 24, 136, 76, 147, 41, 64, 172 }, // left = d117
{ 34, 17, 11, 108, 152, 187, 13, 15, 209 }, // left = d153
{ 51, 24, 14, 115, 133, 209, 32, 26, 104 }, // left = d207
{ 55, 30, 18, 122, 79, 179, 44, 88, 116 }, // left = d63
{ 37, 49, 25, 129, 168, 164, 41, 54, 148 } // left = tm
}, { // above = d207
{ 82, 22, 32, 127, 143, 213, 39, 41, 70 }, // left = dc
{ 62, 44, 61, 123, 105, 189, 48, 57, 64 }, // left = v
{ 47, 25, 17, 175, 222, 220, 24, 30, 86 }, // left = h
{ 68, 36, 17, 106, 102, 206, 59, 74, 74 }, // left = d45
{ 57, 39, 23, 151, 68, 216, 55, 63, 58 }, // left = d135
{ 49, 30, 35, 141, 70, 168, 82, 40, 115 }, // left = d117
{ 51, 25, 15, 136, 129, 202, 38, 35, 139 }, // left = d153
{ 68, 26, 16, 111, 141, 215, 29, 28, 28 }, // left = d207
{ 59, 39, 19, 114, 75, 180, 77, 104, 42 }, // left = d63
{ 40, 61, 26, 126, 152, 206, 61, 59, 93 } // left = tm
}, { // above = d63
{ 78, 23, 39, 111, 117, 170, 74, 124, 94 }, // left = dc
{ 48, 34, 86, 101, 92, 146, 78, 179, 134 }, // left = v
{ 47, 22, 24, 138, 187, 178, 68, 69, 59 }, // left = h
{ 56, 25, 33, 105, 112, 187, 95, 177, 129 }, // left = d45
{ 48, 31, 27, 114, 63, 183, 82, 116, 56 }, // left = d135
{ 43, 28, 37, 121, 63, 123, 61, 192, 169 }, // left = d117
{ 42, 17, 24, 109, 97, 177, 56, 76, 122 }, // left = d153
{ 58, 18, 28, 105, 139, 182, 70, 92, 63 }, // left = d207
{ 46, 23, 32, 74, 86, 150, 67, 183, 88 }, // left = d63
{ 36, 38, 48, 92, 122, 165, 88, 137, 91 } // left = tm
}, { // above = tm
{ 65, 70, 60, 155, 159, 199, 61, 60, 81 }, // left = dc
{ 44, 78, 115, 132, 119, 173, 71, 112, 93 }, // left = v
{ 39, 38, 21, 184, 227, 206, 42, 32, 64 }, // left = h
{ 58, 47, 36, 124, 137, 193, 80, 82, 78 }, // left = d45
{ 49, 50, 35, 144, 95, 205, 63, 78, 59 }, // left = d135
{ 41, 53, 52, 148, 71, 142, 65, 128, 51 }, // left = d117
{ 40, 36, 28, 143, 143, 202, 40, 55, 137 }, // left = d153
{ 52, 34, 29, 129, 183, 227, 42, 35, 43 }, // left = d207
{ 42, 44, 44, 104, 105, 164, 64, 130, 80 }, // left = d63
{ 43, 81, 53, 140, 169, 204, 68, 84, 72 } // left = tm
}
};
const vpx_prob vp10_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1] = {
{ 144, 11, 54, 157, 195, 130, 46, 58, 108 }, // y = dc
{ 118, 15, 123, 148, 131, 101, 44, 93, 131 }, // y = v
{ 113, 12, 23, 188, 226, 142, 26, 32, 125 }, // y = h
{ 120, 11, 50, 123, 163, 135, 64, 77, 103 }, // y = d45
{ 113, 9, 36, 155, 111, 157, 32, 44, 161 }, // y = d135
{ 116, 9, 55, 176, 76, 96, 37, 61, 149 }, // y = d117
{ 115, 9, 28, 141, 161, 167, 21, 25, 193 }, // y = d153
{ 120, 12, 32, 145, 195, 142, 32, 38, 86 }, // y = d207
{ 116, 12, 64, 120, 140, 125, 49, 115, 121 }, // y = d63
{ 102, 19, 66, 162, 182, 122, 35, 59, 128 } // y = tm
};
static const vpx_prob default_if_y_probs[BLOCK_SIZE_GROUPS][INTRA_MODES - 1] = {
{ 65, 32, 18, 144, 162, 194, 41, 51, 98 }, // block_size < 8x8
{ 132, 68, 18, 165, 217, 196, 45, 40, 78 }, // block_size < 16x16
{ 173, 80, 19, 176, 240, 193, 64, 35, 46 }, // block_size < 32x32
{ 221, 135, 38, 194, 248, 121, 96, 85, 29 } // block_size >= 32x32
};
static const vpx_prob default_if_uv_probs[INTRA_MODES][INTRA_MODES - 1] = {
{ 120, 7, 76, 176, 208, 126, 28, 54, 103 }, // y = dc
{ 48, 12, 154, 155, 139, 90, 34, 117, 119 }, // y = v
{ 67, 6, 25, 204, 243, 158, 13, 21, 96 }, // y = h
{ 97, 5, 44, 131, 176, 139, 48, 68, 97 }, // y = d45
{ 83, 5, 42, 156, 111, 152, 26, 49, 152 }, // y = d135
{ 80, 5, 58, 178, 74, 83, 33, 62, 145 }, // y = d117
{ 86, 5, 32, 154, 192, 168, 14, 22, 163 }, // y = d153
{ 85, 5, 32, 156, 216, 148, 19, 29, 73 }, // y = d207
{ 77, 7, 64, 116, 132, 122, 37, 126, 120 }, // y = d63
{ 101, 21, 107, 181, 192, 103, 19, 67, 125 } // y = tm
};
const vpx_prob vp10_kf_partition_probs[PARTITION_CONTEXTS]
[PARTITION_TYPES - 1] = {
// 8x8 -> 4x4
{ 158, 97, 94 }, // a/l both not split
{ 93, 24, 99 }, // a split, l not split
{ 85, 119, 44 }, // l split, a not split
{ 62, 59, 67 }, // a/l both split
// 16x16 -> 8x8
{ 149, 53, 53 }, // a/l both not split
{ 94, 20, 48 }, // a split, l not split
{ 83, 53, 24 }, // l split, a not split
{ 52, 18, 18 }, // a/l both split
// 32x32 -> 16x16
{ 150, 40, 39 }, // a/l both not split
{ 78, 12, 26 }, // a split, l not split
{ 67, 33, 11 }, // l split, a not split
{ 24, 7, 5 }, // a/l both split
// 64x64 -> 32x32
{ 174, 35, 49 }, // a/l both not split
{ 68, 11, 27 }, // a split, l not split
{ 57, 15, 9 }, // l split, a not split
{ 12, 3, 3 }, // a/l both split
};
static const vpx_prob default_partition_probs[PARTITION_CONTEXTS]
[PARTITION_TYPES - 1] = {
// 8x8 -> 4x4
{ 199, 122, 141 }, // a/l both not split
{ 147, 63, 159 }, // a split, l not split
{ 148, 133, 118 }, // l split, a not split
{ 121, 104, 114 }, // a/l both split
// 16x16 -> 8x8
{ 174, 73, 87 }, // a/l both not split
{ 92, 41, 83 }, // a split, l not split
{ 82, 99, 50 }, // l split, a not split
{ 53, 39, 39 }, // a/l both split
// 32x32 -> 16x16
{ 177, 58, 59 }, // a/l both not split
{ 68, 26, 63 }, // a split, l not split
{ 52, 79, 25 }, // l split, a not split
{ 17, 14, 12 }, // a/l both split
// 64x64 -> 32x32
{ 222, 34, 30 }, // a/l both not split
{ 72, 16, 44 }, // a split, l not split
{ 58, 32, 12 }, // l split, a not split
{ 10, 7, 6 }, // a/l both split
};
static const vpx_prob default_inter_mode_probs[INTER_MODE_CONTEXTS]
[INTER_MODES - 1] = {
{2, 173, 34}, // 0 = both zero mv
{7, 145, 85}, // 1 = one zero mv + one a predicted mv
{7, 166, 63}, // 2 = two predicted mvs
{7, 94, 66}, // 3 = one predicted/zero and one new mv
{8, 64, 46}, // 4 = two new mvs
{17, 81, 31}, // 5 = one intra neighbour + x
{25, 29, 30}, // 6 = two intra neighbours
};
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
const vpx_tree_index vp10_intra_mode_tree[TREE_SIZE(INTRA_MODES)] = {
-DC_PRED, 2, /* 0 = DC_NODE */
-TM_PRED, 4, /* 1 = TM_NODE */
-V_PRED, 6, /* 2 = V_NODE */
8, 12, /* 3 = COM_NODE */
-H_PRED, 10, /* 4 = H_NODE */
-D135_PRED, -D117_PRED, /* 5 = D135_NODE */
-D45_PRED, 14, /* 6 = D45_NODE */
-D63_PRED, 16, /* 7 = D63_NODE */
-D153_PRED, -D207_PRED /* 8 = D153_NODE */
};
const vpx_tree_index vp10_inter_mode_tree[TREE_SIZE(INTER_MODES)] = {
-INTER_OFFSET(ZEROMV), 2,
-INTER_OFFSET(NEARESTMV), 4,
-INTER_OFFSET(NEARMV), -INTER_OFFSET(NEWMV)
};
const vpx_tree_index vp10_partition_tree[TREE_SIZE(PARTITION_TYPES)] = {
-PARTITION_NONE, 2,
-PARTITION_HORZ, 4,
-PARTITION_VERT, -PARTITION_SPLIT
};
static const vpx_prob default_intra_inter_p[INTRA_INTER_CONTEXTS] = {
9, 102, 187, 225
};
static const vpx_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
239, 183, 119, 96, 41
};
static const vpx_prob default_comp_ref_p[REF_CONTEXTS] = {
50, 126, 123, 221, 226
};
static const vpx_prob default_single_ref_p[REF_CONTEXTS][2] = {
{ 33, 16 },
{ 77, 74 },
{ 142, 142 },
{ 172, 170 },
{ 238, 247 }
};
static const struct tx_probs default_tx_probs = {
{ { 3, 136, 37 },
{ 5, 52, 13 } },
{ { 20, 152 },
{ 15, 101 } },
{ { 100 },
{ 66 } }
};
void vp10_tx_counts_to_branch_counts_32x32(const unsigned int *tx_count_32x32p,
unsigned int (*ct_32x32p)[2]) {
ct_32x32p[0][0] = tx_count_32x32p[TX_4X4];
ct_32x32p[0][1] = tx_count_32x32p[TX_8X8] +
tx_count_32x32p[TX_16X16] +
tx_count_32x32p[TX_32X32];
ct_32x32p[1][0] = tx_count_32x32p[TX_8X8];
ct_32x32p[1][1] = tx_count_32x32p[TX_16X16] +
tx_count_32x32p[TX_32X32];
ct_32x32p[2][0] = tx_count_32x32p[TX_16X16];
ct_32x32p[2][1] = tx_count_32x32p[TX_32X32];
}
void vp10_tx_counts_to_branch_counts_16x16(const unsigned int *tx_count_16x16p,
unsigned int (*ct_16x16p)[2]) {
ct_16x16p[0][0] = tx_count_16x16p[TX_4X4];
ct_16x16p[0][1] = tx_count_16x16p[TX_8X8] + tx_count_16x16p[TX_16X16];
ct_16x16p[1][0] = tx_count_16x16p[TX_8X8];
ct_16x16p[1][1] = tx_count_16x16p[TX_16X16];
}
void vp10_tx_counts_to_branch_counts_8x8(const unsigned int *tx_count_8x8p,
unsigned int (*ct_8x8p)[2]) {
ct_8x8p[0][0] = tx_count_8x8p[TX_4X4];
ct_8x8p[0][1] = tx_count_8x8p[TX_8X8];
}
static const vpx_prob default_skip_probs[SKIP_CONTEXTS] = {
192, 128, 64
};
static const vpx_prob default_switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS]
[SWITCHABLE_FILTERS - 1] = {
{ 235, 162, },
{ 36, 255, },
{ 34, 3, },
{ 149, 144, },
};
static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->uv_mode_prob, default_if_uv_probs);
vp10_copy(fc->y_mode_prob, default_if_y_probs);
vp10_copy(fc->switchable_interp_prob, default_switchable_interp_prob);
vp10_copy(fc->partition_prob, default_partition_probs);
vp10_copy(fc->intra_inter_prob, default_intra_inter_p);
vp10_copy(fc->comp_inter_prob, default_comp_inter_p);
vp10_copy(fc->comp_ref_prob, default_comp_ref_p);
vp10_copy(fc->single_ref_prob, default_single_ref_p);
fc->tx_probs = default_tx_probs;
vp10_copy(fc->skip_probs, default_skip_probs);
vp10_copy(fc->inter_mode_probs, default_inter_mode_probs);
}
const vpx_tree_index vp10_switchable_interp_tree
[TREE_SIZE(SWITCHABLE_FILTERS)] = {
-EIGHTTAP, 2,
-EIGHTTAP_SMOOTH, -EIGHTTAP_SHARP
};
void vp10_adapt_mode_probs(VP10_COMMON *cm) {
int i, j;
FRAME_CONTEXT *fc = cm->fc;
const FRAME_CONTEXT *pre_fc = &cm->frame_contexts[cm->frame_context_idx];
const FRAME_COUNTS *counts = &cm->counts;
for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
fc->intra_inter_prob[i] = mode_mv_merge_probs(pre_fc->intra_inter_prob[i],
counts->intra_inter[i]);
for (i = 0; i < COMP_INTER_CONTEXTS; i++)
fc->comp_inter_prob[i] = mode_mv_merge_probs(pre_fc->comp_inter_prob[i],
counts->comp_inter[i]);
for (i = 0; i < REF_CONTEXTS; i++)
fc->comp_ref_prob[i] = mode_mv_merge_probs(pre_fc->comp_ref_prob[i],
counts->comp_ref[i]);
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
fc->single_ref_prob[i][j] = mode_mv_merge_probs(
pre_fc->single_ref_prob[i][j], counts->single_ref[i][j]);
for (i = 0; i < INTER_MODE_CONTEXTS; i++)
vpx_tree_merge_probs(vp10_inter_mode_tree, pre_fc->inter_mode_probs[i],
counts->inter_mode[i], fc->inter_mode_probs[i]);
for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
vpx_tree_merge_probs(vp10_intra_mode_tree, pre_fc->y_mode_prob[i],
counts->y_mode[i], fc->y_mode_prob[i]);
for (i = 0; i < INTRA_MODES; ++i)
vpx_tree_merge_probs(vp10_intra_mode_tree, pre_fc->uv_mode_prob[i],
counts->uv_mode[i], fc->uv_mode_prob[i]);
for (i = 0; i < PARTITION_CONTEXTS; i++)
vpx_tree_merge_probs(vp10_partition_tree, pre_fc->partition_prob[i],
counts->partition[i], fc->partition_prob[i]);
if (cm->interp_filter == SWITCHABLE) {
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
vpx_tree_merge_probs(vp10_switchable_interp_tree,
pre_fc->switchable_interp_prob[i],
counts->switchable_interp[i],
fc->switchable_interp_prob[i]);
}
if (cm->tx_mode == TX_MODE_SELECT) {
int j;
unsigned int branch_ct_8x8p[TX_SIZES - 3][2];
unsigned int branch_ct_16x16p[TX_SIZES - 2][2];
unsigned int branch_ct_32x32p[TX_SIZES - 1][2];
for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
vp10_tx_counts_to_branch_counts_8x8(counts->tx.p8x8[i], branch_ct_8x8p);
for (j = 0; j < TX_SIZES - 3; ++j)
fc->tx_probs.p8x8[i][j] = mode_mv_merge_probs(
pre_fc->tx_probs.p8x8[i][j], branch_ct_8x8p[j]);
vp10_tx_counts_to_branch_counts_16x16(counts->tx.p16x16[i], branch_ct_16x16p);
for (j = 0; j < TX_SIZES - 2; ++j)
fc->tx_probs.p16x16[i][j] = mode_mv_merge_probs(
pre_fc->tx_probs.p16x16[i][j], branch_ct_16x16p[j]);
vp10_tx_counts_to_branch_counts_32x32(counts->tx.p32x32[i], branch_ct_32x32p);
for (j = 0; j < TX_SIZES - 1; ++j)
fc->tx_probs.p32x32[i][j] = mode_mv_merge_probs(
pre_fc->tx_probs.p32x32[i][j], branch_ct_32x32p[j]);
}
}
for (i = 0; i < SKIP_CONTEXTS; ++i)
fc->skip_probs[i] = mode_mv_merge_probs(
pre_fc->skip_probs[i], counts->skip[i]);
}
static void set_default_lf_deltas(struct loopfilter *lf) {
lf->mode_ref_delta_enabled = 1;
lf->mode_ref_delta_update = 1;
lf->ref_deltas[INTRA_FRAME] = 1;
lf->ref_deltas[LAST_FRAME] = 0;
lf->ref_deltas[GOLDEN_FRAME] = -1;
lf->ref_deltas[ALTREF_FRAME] = -1;
lf->mode_deltas[0] = 0;
lf->mode_deltas[1] = 0;
}
void vp10_setup_past_independence(VP10_COMMON *cm) {
// Reset the segment feature data to the default stats:
// Features disabled, 0, with delta coding (Default state).
struct loopfilter *const lf = &cm->lf;
int i;
vp10_clearall_segfeatures(&cm->seg);
cm->seg.abs_delta = SEGMENT_DELTADATA;
if (cm->last_frame_seg_map && !cm->frame_parallel_decode)
memset(cm->last_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
if (cm->current_frame_seg_map)
memset(cm->current_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
// Reset the mode ref deltas for loop filter
vp10_zero(lf->last_ref_deltas);
vp10_zero(lf->last_mode_deltas);
set_default_lf_deltas(lf);
// To force update of the sharpness
lf->last_sharpness_level = -1;
vp10_default_coef_probs(cm);
init_mode_probs(cm->fc);
vp10_init_mv_probs(cm);
cm->fc->initialized = 1;
if (cm->frame_type == KEY_FRAME ||
cm->error_resilient_mode || cm->reset_frame_context == 3) {
// Reset all frame contexts.
for (i = 0; i < FRAME_CONTEXTS; ++i)
cm->frame_contexts[i] = *cm->fc;
} else if (cm->reset_frame_context == 2) {
// Reset only the frame context specified in the frame header.
cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
}
// prev_mip will only be allocated in encoder.
if (frame_is_intra_only(cm) && cm->prev_mip && !cm->frame_parallel_decode)
memset(cm->prev_mip, 0,
cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->prev_mip));
vp10_zero(cm->ref_frame_sign_bias);
cm->frame_context_idx = 0;
}

107
vp10/common/entropymode.h Normal file
View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_ENTROPYMODE_H_
#define VP10_COMMON_ENTROPYMODE_H_
#include "vp10/common/entropy.h"
#include "vp10/common/entropymv.h"
#include "vp10/common/filter.h"
#include "vpx_dsp/vpx_filter.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BLOCK_SIZE_GROUPS 4
#define TX_SIZE_CONTEXTS 2
#define INTER_OFFSET(mode) ((mode) - NEARESTMV)
struct VP10Common;
struct tx_probs {
vpx_prob p32x32[TX_SIZE_CONTEXTS][TX_SIZES - 1];
vpx_prob p16x16[TX_SIZE_CONTEXTS][TX_SIZES - 2];
vpx_prob p8x8[TX_SIZE_CONTEXTS][TX_SIZES - 3];
};
struct tx_counts {
unsigned int p32x32[TX_SIZE_CONTEXTS][TX_SIZES];
unsigned int p16x16[TX_SIZE_CONTEXTS][TX_SIZES - 1];
unsigned int p8x8[TX_SIZE_CONTEXTS][TX_SIZES - 2];
unsigned int tx_totals[TX_SIZES];
};
typedef struct frame_contexts {
vpx_prob y_mode_prob[BLOCK_SIZE_GROUPS][INTRA_MODES - 1];
vpx_prob uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
vpx_prob partition_prob[PARTITION_CONTEXTS][PARTITION_TYPES - 1];
vp10_coeff_probs_model coef_probs[TX_SIZES][PLANE_TYPES];
vpx_prob switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS]
[SWITCHABLE_FILTERS - 1];
vpx_prob inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1];
vpx_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
vpx_prob comp_inter_prob[COMP_INTER_CONTEXTS];
vpx_prob single_ref_prob[REF_CONTEXTS][2];
vpx_prob comp_ref_prob[REF_CONTEXTS];
struct tx_probs tx_probs;
vpx_prob skip_probs[SKIP_CONTEXTS];
nmv_context nmvc;
int initialized;
} FRAME_CONTEXT;
typedef struct FRAME_COUNTS {
unsigned int y_mode[BLOCK_SIZE_GROUPS][INTRA_MODES];
unsigned int uv_mode[INTRA_MODES][INTRA_MODES];
unsigned int partition[PARTITION_CONTEXTS][PARTITION_TYPES];
vp10_coeff_count_model coef[TX_SIZES][PLANE_TYPES];
unsigned int eob_branch[TX_SIZES][PLANE_TYPES][REF_TYPES]
[COEF_BANDS][COEFF_CONTEXTS];
unsigned int switchable_interp[SWITCHABLE_FILTER_CONTEXTS]
[SWITCHABLE_FILTERS];
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
unsigned int single_ref[REF_CONTEXTS][2][2];
unsigned int comp_ref[REF_CONTEXTS][2];
struct tx_counts tx;
unsigned int skip[SKIP_CONTEXTS][2];
nmv_context_counts mv;
} FRAME_COUNTS;
extern const vpx_prob vp10_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
extern const vpx_prob vp10_kf_y_mode_prob[INTRA_MODES][INTRA_MODES]
[INTRA_MODES - 1];
extern const vpx_prob vp10_kf_partition_probs[PARTITION_CONTEXTS]
[PARTITION_TYPES - 1];
extern const vpx_tree_index vp10_intra_mode_tree[TREE_SIZE(INTRA_MODES)];
extern const vpx_tree_index vp10_inter_mode_tree[TREE_SIZE(INTER_MODES)];
extern const vpx_tree_index vp10_partition_tree[TREE_SIZE(PARTITION_TYPES)];
extern const vpx_tree_index vp10_switchable_interp_tree
[TREE_SIZE(SWITCHABLE_FILTERS)];
void vp10_setup_past_independence(struct VP10Common *cm);
void vp10_adapt_mode_probs(struct VP10Common *cm);
void vp10_tx_counts_to_branch_counts_32x32(const unsigned int *tx_count_32x32p,
unsigned int (*ct_32x32p)[2]);
void vp10_tx_counts_to_branch_counts_16x16(const unsigned int *tx_count_16x16p,
unsigned int (*ct_16x16p)[2]);
void vp10_tx_counts_to_branch_counts_8x8(const unsigned int *tx_count_8x8p,
unsigned int (*ct_8x8p)[2]);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_ENTROPYMODE_H_

218
vp10/common/entropymv.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp10/common/onyxc_int.h"
#include "vp10/common/entropymv.h"
// Integer pel reference mv threshold for use of high-precision 1/8 mv
#define COMPANDED_MVREF_THRESH 8
const vpx_tree_index vp10_mv_joint_tree[TREE_SIZE(MV_JOINTS)] = {
-MV_JOINT_ZERO, 2,
-MV_JOINT_HNZVZ, 4,
-MV_JOINT_HZVNZ, -MV_JOINT_HNZVNZ
};
const vpx_tree_index vp10_mv_class_tree[TREE_SIZE(MV_CLASSES)] = {
-MV_CLASS_0, 2,
-MV_CLASS_1, 4,
6, 8,
-MV_CLASS_2, -MV_CLASS_3,
10, 12,
-MV_CLASS_4, -MV_CLASS_5,
-MV_CLASS_6, 14,
16, 18,
-MV_CLASS_7, -MV_CLASS_8,
-MV_CLASS_9, -MV_CLASS_10,
};
const vpx_tree_index vp10_mv_class0_tree[TREE_SIZE(CLASS0_SIZE)] = {
-0, -1,
};
const vpx_tree_index vp10_mv_fp_tree[TREE_SIZE(MV_FP_SIZE)] = {
-0, 2,
-1, 4,
-2, -3
};
static const nmv_context default_nmv_context = {
{32, 64, 96},
{
{ // Vertical component
128, // sign
{224, 144, 192, 168, 192, 176, 192, 198, 198, 245}, // class
{216}, // class0
{136, 140, 148, 160, 176, 192, 224, 234, 234, 240}, // bits
{{128, 128, 64}, {96, 112, 64}}, // class0_fp
{64, 96, 64}, // fp
160, // class0_hp bit
128, // hp
},
{ // Horizontal component
128, // sign
{216, 128, 176, 160, 176, 176, 192, 198, 198, 208}, // class
{208}, // class0
{136, 140, 148, 160, 176, 192, 224, 234, 234, 240}, // bits
{{128, 128, 64}, {96, 112, 64}}, // class0_fp
{64, 96, 64}, // fp
160, // class0_hp bit
128, // hp
}
},
};
static const uint8_t log_in_base_2[] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10
};
static INLINE int mv_class_base(MV_CLASS_TYPE c) {
return c ? CLASS0_SIZE << (c + 2) : 0;
}
MV_CLASS_TYPE vp10_get_mv_class(int z, int *offset) {
const MV_CLASS_TYPE c = (z >= CLASS0_SIZE * 4096) ?
MV_CLASS_10 : (MV_CLASS_TYPE)log_in_base_2[z >> 3];
if (offset)
*offset = z - mv_class_base(c);
return c;
}
int vp10_use_mv_hp(const MV *ref) {
return (abs(ref->row) >> 3) < COMPANDED_MVREF_THRESH &&
(abs(ref->col) >> 3) < COMPANDED_MVREF_THRESH;
}
static void inc_mv_component(int v, nmv_component_counts *comp_counts,
int incr, int usehp) {
int s, z, c, o, d, e, f;
assert(v != 0); /* should not be zero */
s = v < 0;
comp_counts->sign[s] += incr;
z = (s ? -v : v) - 1; /* magnitude - 1 */
c = vp10_get_mv_class(z, &o);
comp_counts->classes[c] += incr;
d = (o >> 3); /* int mv data */
f = (o >> 1) & 3; /* fractional pel mv data */
e = (o & 1); /* high precision mv data */
if (c == MV_CLASS_0) {
comp_counts->class0[d] += incr;
comp_counts->class0_fp[d][f] += incr;
comp_counts->class0_hp[e] += usehp * incr;
} else {
int i;
int b = c + CLASS0_BITS - 1; // number of bits
for (i = 0; i < b; ++i)
comp_counts->bits[i][((d >> i) & 1)] += incr;
comp_counts->fp[f] += incr;
comp_counts->hp[e] += usehp * incr;
}
}
void vp10_inc_mv(const MV *mv, nmv_context_counts *counts) {
if (counts != NULL) {
const MV_JOINT_TYPE j = vp10_get_mv_joint(mv);
++counts->joints[j];
if (mv_joint_vertical(j)) {
inc_mv_component(mv->row, &counts->comps[0], 1, 1);
}
if (mv_joint_horizontal(j)) {
inc_mv_component(mv->col, &counts->comps[1], 1, 1);
}
}
}
void vp10_adapt_mv_probs(VP10_COMMON *cm, int allow_hp) {
int i, j;
nmv_context *fc = &cm->fc->nmvc;
const nmv_context *pre_fc = &cm->frame_contexts[cm->frame_context_idx].nmvc;
const nmv_context_counts *counts = &cm->counts.mv;
vpx_tree_merge_probs(vp10_mv_joint_tree, pre_fc->joints, counts->joints,
fc->joints);
for (i = 0; i < 2; ++i) {
nmv_component *comp = &fc->comps[i];
const nmv_component *pre_comp = &pre_fc->comps[i];
const nmv_component_counts *c = &counts->comps[i];
comp->sign = mode_mv_merge_probs(pre_comp->sign, c->sign);
vpx_tree_merge_probs(vp10_mv_class_tree, pre_comp->classes, c->classes,
comp->classes);
vpx_tree_merge_probs(vp10_mv_class0_tree, pre_comp->class0, c->class0,
comp->class0);
for (j = 0; j < MV_OFFSET_BITS; ++j)
comp->bits[j] = mode_mv_merge_probs(pre_comp->bits[j], c->bits[j]);
for (j = 0; j < CLASS0_SIZE; ++j)
vpx_tree_merge_probs(vp10_mv_fp_tree, pre_comp->class0_fp[j],
c->class0_fp[j], comp->class0_fp[j]);
vpx_tree_merge_probs(vp10_mv_fp_tree, pre_comp->fp, c->fp, comp->fp);
if (allow_hp) {
comp->class0_hp = mode_mv_merge_probs(pre_comp->class0_hp, c->class0_hp);
comp->hp = mode_mv_merge_probs(pre_comp->hp, c->hp);
}
}
}
void vp10_init_mv_probs(VP10_COMMON *cm) {
cm->fc->nmvc = default_nmv_context;
}

133
vp10/common/entropymv.h Normal file
View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_ENTROPYMV_H_
#define VP10_COMMON_ENTROPYMV_H_
#include "./vpx_config.h"
#include "vpx_dsp/prob.h"
#include "vp10/common/mv.h"
#ifdef __cplusplus
extern "C" {
#endif
struct VP10Common;
void vp10_init_mv_probs(struct VP10Common *cm);
void vp10_adapt_mv_probs(struct VP10Common *cm, int usehp);
int vp10_use_mv_hp(const MV *ref);
#define MV_UPDATE_PROB 252
/* Symbols for coding which components are zero jointly */
#define MV_JOINTS 4
typedef enum {
MV_JOINT_ZERO = 0, /* Zero vector */
MV_JOINT_HNZVZ = 1, /* Vert zero, hor nonzero */
MV_JOINT_HZVNZ = 2, /* Hor zero, vert nonzero */
MV_JOINT_HNZVNZ = 3, /* Both components nonzero */
} MV_JOINT_TYPE;
static INLINE int mv_joint_vertical(MV_JOINT_TYPE type) {
return type == MV_JOINT_HZVNZ || type == MV_JOINT_HNZVNZ;
}
static INLINE int mv_joint_horizontal(MV_JOINT_TYPE type) {
return type == MV_JOINT_HNZVZ || type == MV_JOINT_HNZVNZ;
}
/* Symbols for coding magnitude class of nonzero components */
#define MV_CLASSES 11
typedef enum {
MV_CLASS_0 = 0, /* (0, 2] integer pel */
MV_CLASS_1 = 1, /* (2, 4] integer pel */
MV_CLASS_2 = 2, /* (4, 8] integer pel */
MV_CLASS_3 = 3, /* (8, 16] integer pel */
MV_CLASS_4 = 4, /* (16, 32] integer pel */
MV_CLASS_5 = 5, /* (32, 64] integer pel */
MV_CLASS_6 = 6, /* (64, 128] integer pel */
MV_CLASS_7 = 7, /* (128, 256] integer pel */
MV_CLASS_8 = 8, /* (256, 512] integer pel */
MV_CLASS_9 = 9, /* (512, 1024] integer pel */
MV_CLASS_10 = 10, /* (1024,2048] integer pel */
} MV_CLASS_TYPE;
#define CLASS0_BITS 1 /* bits at integer precision for class 0 */
#define CLASS0_SIZE (1 << CLASS0_BITS)
#define MV_OFFSET_BITS (MV_CLASSES + CLASS0_BITS - 2)
#define MV_FP_SIZE 4
#define MV_MAX_BITS (MV_CLASSES + CLASS0_BITS + 2)
#define MV_MAX ((1 << MV_MAX_BITS) - 1)
#define MV_VALS ((MV_MAX << 1) + 1)
#define MV_IN_USE_BITS 14
#define MV_UPP ((1 << MV_IN_USE_BITS) - 1)
#define MV_LOW (-(1 << MV_IN_USE_BITS))
extern const vpx_tree_index vp10_mv_joint_tree[];
extern const vpx_tree_index vp10_mv_class_tree[];
extern const vpx_tree_index vp10_mv_class0_tree[];
extern const vpx_tree_index vp10_mv_fp_tree[];
typedef struct {
vpx_prob sign;
vpx_prob classes[MV_CLASSES - 1];
vpx_prob class0[CLASS0_SIZE - 1];
vpx_prob bits[MV_OFFSET_BITS];
vpx_prob class0_fp[CLASS0_SIZE][MV_FP_SIZE - 1];
vpx_prob fp[MV_FP_SIZE - 1];
vpx_prob class0_hp;
vpx_prob hp;
} nmv_component;
typedef struct {
vpx_prob joints[MV_JOINTS - 1];
nmv_component comps[2];
} nmv_context;
static INLINE MV_JOINT_TYPE vp10_get_mv_joint(const MV *mv) {
if (mv->row == 0) {
return mv->col == 0 ? MV_JOINT_ZERO : MV_JOINT_HNZVZ;
} else {
return mv->col == 0 ? MV_JOINT_HZVNZ : MV_JOINT_HNZVNZ;
}
}
MV_CLASS_TYPE vp10_get_mv_class(int z, int *offset);
typedef struct {
unsigned int sign[2];
unsigned int classes[MV_CLASSES];
unsigned int class0[CLASS0_SIZE];
unsigned int bits[MV_OFFSET_BITS][2];
unsigned int class0_fp[CLASS0_SIZE][MV_FP_SIZE];
unsigned int fp[MV_FP_SIZE];
unsigned int class0_hp[2];
unsigned int hp[2];
} nmv_component_counts;
typedef struct {
unsigned int joints[MV_JOINTS];
nmv_component_counts comps[2];
} nmv_context_counts;
void vp10_inc_mv(const MV *mv, nmv_context_counts *mvctx);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_ENTROPYMV_H_

147
vp10/common/enums.h Normal file
View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_ENUMS_H_
#define VP10_COMMON_ENUMS_H_
#include "./vpx_config.h"
#include "vpx/vpx_integer.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MI_SIZE_LOG2 3
#define MI_BLOCK_SIZE_LOG2 (6 - MI_SIZE_LOG2) // 64 = 2^6
#define MI_SIZE (1 << MI_SIZE_LOG2) // pixels per mi-unit
#define MI_BLOCK_SIZE (1 << MI_BLOCK_SIZE_LOG2) // mi-units per max block
#define MI_MASK (MI_BLOCK_SIZE - 1)
// Bitstream profiles indicated by 2-3 bits in the uncompressed header.
// 00: Profile 0. 8-bit 4:2:0 only.
// 10: Profile 1. 8-bit 4:4:4, 4:2:2, and 4:4:0.
// 01: Profile 2. 10-bit and 12-bit color only, with 4:2:0 sampling.
// 110: Profile 3. 10-bit and 12-bit color only, with 4:2:2/4:4:4/4:4:0
// sampling.
// 111: Undefined profile.
typedef enum BITSTREAM_PROFILE {
PROFILE_0,
PROFILE_1,
PROFILE_2,
PROFILE_3,
MAX_PROFILES
} BITSTREAM_PROFILE;
#define BLOCK_4X4 0
#define BLOCK_4X8 1
#define BLOCK_8X4 2
#define BLOCK_8X8 3
#define BLOCK_8X16 4
#define BLOCK_16X8 5
#define BLOCK_16X16 6
#define BLOCK_16X32 7
#define BLOCK_32X16 8
#define BLOCK_32X32 9
#define BLOCK_32X64 10
#define BLOCK_64X32 11
#define BLOCK_64X64 12
#define BLOCK_SIZES 13
#define BLOCK_INVALID BLOCK_SIZES
typedef uint8_t BLOCK_SIZE;
typedef enum PARTITION_TYPE {
PARTITION_NONE,
PARTITION_HORZ,
PARTITION_VERT,
PARTITION_SPLIT,
PARTITION_TYPES,
PARTITION_INVALID = PARTITION_TYPES
} PARTITION_TYPE;
typedef char PARTITION_CONTEXT;
#define PARTITION_PLOFFSET 4 // number of probability models per block size
#define PARTITION_CONTEXTS (4 * PARTITION_PLOFFSET)
// block transform size
typedef uint8_t TX_SIZE;
#define TX_4X4 ((TX_SIZE)0) // 4x4 transform
#define TX_8X8 ((TX_SIZE)1) // 8x8 transform
#define TX_16X16 ((TX_SIZE)2) // 16x16 transform
#define TX_32X32 ((TX_SIZE)3) // 32x32 transform
#define TX_SIZES ((TX_SIZE)4)
// frame transform mode
typedef enum {
ONLY_4X4 = 0, // only 4x4 transform used
ALLOW_8X8 = 1, // allow block transform size up to 8x8
ALLOW_16X16 = 2, // allow block transform size up to 16x16
ALLOW_32X32 = 3, // allow block transform size up to 32x32
TX_MODE_SELECT = 4, // transform specified for each block
TX_MODES = 5,
} TX_MODE;
typedef enum {
DCT_DCT = 0, // DCT in both horizontal and vertical
ADST_DCT = 1, // ADST in vertical, DCT in horizontal
DCT_ADST = 2, // DCT in vertical, ADST in horizontal
ADST_ADST = 3, // ADST in both directions
TX_TYPES = 4
} TX_TYPE;
typedef enum {
VP9_LAST_FLAG = 1 << 0,
VP9_GOLD_FLAG = 1 << 1,
VP9_ALT_FLAG = 1 << 2,
} VP9_REFFRAME;
typedef enum {
PLANE_TYPE_Y = 0,
PLANE_TYPE_UV = 1,
PLANE_TYPES
} PLANE_TYPE;
#define DC_PRED 0 // Average of above and left pixels
#define V_PRED 1 // Vertical
#define H_PRED 2 // Horizontal
#define D45_PRED 3 // Directional 45 deg = round(arctan(1/1) * 180/pi)
#define D135_PRED 4 // Directional 135 deg = 180 - 45
#define D117_PRED 5 // Directional 117 deg = 180 - 63
#define D153_PRED 6 // Directional 153 deg = 180 - 27
#define D207_PRED 7 // Directional 207 deg = 180 + 27
#define D63_PRED 8 // Directional 63 deg = round(arctan(2/1) * 180/pi)
#define TM_PRED 9 // True-motion
#define NEARESTMV 10
#define NEARMV 11
#define ZEROMV 12
#define NEWMV 13
#define MB_MODE_COUNT 14
typedef uint8_t PREDICTION_MODE;
#define INTRA_MODES (TM_PRED + 1)
#define INTER_MODES (1 + NEWMV - NEARESTMV)
#define SKIP_CONTEXTS 3
#define INTER_MODE_CONTEXTS 7
/* Segment Feature Masks */
#define MAX_MV_REF_CANDIDATES 2
#define INTRA_INTER_CONTEXTS 4
#define COMP_INTER_CONTEXTS 5
#define REF_CONTEXTS 5
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_ENUMS_H_

104
vp10/common/filter.c Normal file
View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "vp10/common/filter.h"
DECLARE_ALIGNED(256, static const InterpKernel,
bilinear_filters[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0 },
{ 0, 0, 0, 120, 8, 0, 0, 0 },
{ 0, 0, 0, 112, 16, 0, 0, 0 },
{ 0, 0, 0, 104, 24, 0, 0, 0 },
{ 0, 0, 0, 96, 32, 0, 0, 0 },
{ 0, 0, 0, 88, 40, 0, 0, 0 },
{ 0, 0, 0, 80, 48, 0, 0, 0 },
{ 0, 0, 0, 72, 56, 0, 0, 0 },
{ 0, 0, 0, 64, 64, 0, 0, 0 },
{ 0, 0, 0, 56, 72, 0, 0, 0 },
{ 0, 0, 0, 48, 80, 0, 0, 0 },
{ 0, 0, 0, 40, 88, 0, 0, 0 },
{ 0, 0, 0, 32, 96, 0, 0, 0 },
{ 0, 0, 0, 24, 104, 0, 0, 0 },
{ 0, 0, 0, 16, 112, 0, 0, 0 },
{ 0, 0, 0, 8, 120, 0, 0, 0 }
};
// Lagrangian interpolation filter
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0},
{ 0, 1, -5, 126, 8, -3, 1, 0},
{ -1, 3, -10, 122, 18, -6, 2, 0},
{ -1, 4, -13, 118, 27, -9, 3, -1},
{ -1, 4, -16, 112, 37, -11, 4, -1},
{ -1, 5, -18, 105, 48, -14, 4, -1},
{ -1, 5, -19, 97, 58, -16, 5, -1},
{ -1, 6, -19, 88, 68, -18, 5, -1},
{ -1, 6, -19, 78, 78, -19, 6, -1},
{ -1, 5, -18, 68, 88, -19, 6, -1},
{ -1, 5, -16, 58, 97, -19, 5, -1},
{ -1, 4, -14, 48, 105, -18, 5, -1},
{ -1, 4, -11, 37, 112, -16, 4, -1},
{ -1, 3, -9, 27, 118, -13, 4, -1},
{ 0, 2, -6, 18, 122, -10, 3, -1},
{ 0, 1, -3, 8, 126, -5, 1, 0}
};
// DCT based filter
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8s[SUBPEL_SHIFTS]) = {
{0, 0, 0, 128, 0, 0, 0, 0},
{-1, 3, -7, 127, 8, -3, 1, 0},
{-2, 5, -13, 125, 17, -6, 3, -1},
{-3, 7, -17, 121, 27, -10, 5, -2},
{-4, 9, -20, 115, 37, -13, 6, -2},
{-4, 10, -23, 108, 48, -16, 8, -3},
{-4, 10, -24, 100, 59, -19, 9, -3},
{-4, 11, -24, 90, 70, -21, 10, -4},
{-4, 11, -23, 80, 80, -23, 11, -4},
{-4, 10, -21, 70, 90, -24, 11, -4},
{-3, 9, -19, 59, 100, -24, 10, -4},
{-3, 8, -16, 48, 108, -23, 10, -4},
{-2, 6, -13, 37, 115, -20, 9, -4},
{-2, 5, -10, 27, 121, -17, 7, -3},
{-1, 3, -6, 17, 125, -13, 5, -2},
{0, 1, -3, 8, 127, -7, 3, -1}
};
// freqmultiplier = 0.5
DECLARE_ALIGNED(256, static const InterpKernel,
sub_pel_filters_8lp[SUBPEL_SHIFTS]) = {
{ 0, 0, 0, 128, 0, 0, 0, 0},
{-3, -1, 32, 64, 38, 1, -3, 0},
{-2, -2, 29, 63, 41, 2, -3, 0},
{-2, -2, 26, 63, 43, 4, -4, 0},
{-2, -3, 24, 62, 46, 5, -4, 0},
{-2, -3, 21, 60, 49, 7, -4, 0},
{-1, -4, 18, 59, 51, 9, -4, 0},
{-1, -4, 16, 57, 53, 12, -4, -1},
{-1, -4, 14, 55, 55, 14, -4, -1},
{-1, -4, 12, 53, 57, 16, -4, -1},
{ 0, -4, 9, 51, 59, 18, -4, -1},
{ 0, -4, 7, 49, 60, 21, -3, -2},
{ 0, -4, 5, 46, 62, 24, -3, -2},
{ 0, -4, 4, 43, 63, 26, -2, -2},
{ 0, -3, 2, 41, 63, 29, -2, -2},
{ 0, -3, 1, 38, 64, 32, -1, -3}
};
const InterpKernel *vp10_filter_kernels[4] = {
sub_pel_filters_8,
sub_pel_filters_8lp,
sub_pel_filters_8s,
bilinear_filters
};

42
vp10/common/filter.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2011 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_FILTER_H_
#define VP10_COMMON_FILTER_H_
#include "./vpx_config.h"
#include "vpx/vpx_integer.h"
#include "vpx_dsp/vpx_filter.h"
#include "vpx_ports/mem.h"
#ifdef __cplusplus
extern "C" {
#endif
#define EIGHTTAP 0
#define EIGHTTAP_SMOOTH 1
#define EIGHTTAP_SHARP 2
#define SWITCHABLE_FILTERS 3 /* Number of switchable filters */
#define BILINEAR 3
// The codec can operate in four possible inter prediction filter mode:
// 8-tap, 8-tap-smooth, 8-tap-sharp, and switching between the three.
#define SWITCHABLE_FILTER_CONTEXTS (SWITCHABLE_FILTERS + 1)
#define SWITCHABLE 4 /* should be the last one */
typedef uint8_t INTERP_FILTER;
extern const InterpKernel *vp10_filter_kernels[4];
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_FILTER_H_

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "vp10/common/frame_buffers.h"
#include "vpx_mem/vpx_mem.h"
int vp10_alloc_internal_frame_buffers(InternalFrameBufferList *list) {
assert(list != NULL);
vp10_free_internal_frame_buffers(list);
list->num_internal_frame_buffers =
VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
list->int_fb =
(InternalFrameBuffer *)vpx_calloc(list->num_internal_frame_buffers,
sizeof(*list->int_fb));
return (list->int_fb == NULL);
}
void vp10_free_internal_frame_buffers(InternalFrameBufferList *list) {
int i;
assert(list != NULL);
for (i = 0; i < list->num_internal_frame_buffers; ++i) {
vpx_free(list->int_fb[i].data);
list->int_fb[i].data = NULL;
}
vpx_free(list->int_fb);
list->int_fb = NULL;
}
int vp10_get_frame_buffer(void *cb_priv, size_t min_size,
vpx_codec_frame_buffer_t *fb) {
int i;
InternalFrameBufferList *const int_fb_list =
(InternalFrameBufferList *)cb_priv;
if (int_fb_list == NULL)
return -1;
// Find a free frame buffer.
for (i = 0; i < int_fb_list->num_internal_frame_buffers; ++i) {
if (!int_fb_list->int_fb[i].in_use)
break;
}
if (i == int_fb_list->num_internal_frame_buffers)
return -1;
if (int_fb_list->int_fb[i].size < min_size) {
int_fb_list->int_fb[i].data =
(uint8_t *)vpx_realloc(int_fb_list->int_fb[i].data, min_size);
if (!int_fb_list->int_fb[i].data)
return -1;
// This memset is needed for fixing valgrind error from C loop filter
// due to access uninitialized memory in frame border. It could be
// removed if border is totally removed.
memset(int_fb_list->int_fb[i].data, 0, min_size);
int_fb_list->int_fb[i].size = min_size;
}
fb->data = int_fb_list->int_fb[i].data;
fb->size = int_fb_list->int_fb[i].size;
int_fb_list->int_fb[i].in_use = 1;
// Set the frame buffer's private data to point at the internal frame buffer.
fb->priv = &int_fb_list->int_fb[i];
return 0;
}
int vp10_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;
return 0;
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_FRAME_BUFFERS_H_
#define VP10_COMMON_FRAME_BUFFERS_H_
#include "vpx/vpx_frame_buffer.h"
#include "vpx/vpx_integer.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct InternalFrameBuffer {
uint8_t *data;
size_t size;
int in_use;
} InternalFrameBuffer;
typedef struct InternalFrameBufferList {
int num_internal_frame_buffers;
InternalFrameBuffer *int_fb;
} InternalFrameBufferList;
// Initializes |list|. Returns 0 on success.
int vp10_alloc_internal_frame_buffers(InternalFrameBufferList *list);
// Free any data allocated to the frame buffers.
void vp10_free_internal_frame_buffers(InternalFrameBufferList *list);
// Callback used by libvpx to request an external frame buffer. |cb_priv|
// Callback private data, which points to an InternalFrameBufferList.
// |min_size| is the minimum size in bytes needed to decode the next frame.
// |fb| pointer to the frame buffer.
int vp10_get_frame_buffer(void *cb_priv, size_t min_size,
vpx_codec_frame_buffer_t *fb);
// Callback used by libvpx when there are no references to the frame buffer.
// |cb_priv| is not used. |fb| pointer to the frame buffer.
int vp10_release_frame_buffer(void *cb_priv, vpx_codec_frame_buffer_t *fb);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_FRAME_BUFFERS_H_

492
vp10/common/idct.c Normal file
View File

@@ -0,0 +1,492 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "./vp10_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "vp10/common/blockd.h"
#include "vp10/common/idct.h"
#include "vpx_dsp/inv_txfm.h"
#include "vpx_ports/mem.h"
void vp10_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride,
int tx_type) {
const transform_2d IHT_4[] = {
{ idct4_c, idct4_c }, // DCT_DCT = 0
{ iadst4_c, idct4_c }, // ADST_DCT = 1
{ idct4_c, iadst4_c }, // DCT_ADST = 2
{ iadst4_c, iadst4_c } // ADST_ADST = 3
};
int i, j;
tran_low_t out[4 * 4];
tran_low_t *outptr = out;
tran_low_t temp_in[4], temp_out[4];
// inverse transform row vectors
for (i = 0; i < 4; ++i) {
IHT_4[tx_type].rows(input, outptr);
input += 4;
outptr += 4;
}
// inverse transform column vectors
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j)
temp_in[j] = out[j * 4 + i];
IHT_4[tx_type].cols(temp_in, temp_out);
for (j = 0; j < 4; ++j) {
dest[j * stride + i] = clip_pixel_add(dest[j * stride + i],
ROUND_POWER_OF_TWO(temp_out[j], 4));
}
}
}
static const transform_2d IHT_8[] = {
{ idct8_c, idct8_c }, // DCT_DCT = 0
{ iadst8_c, idct8_c }, // ADST_DCT = 1
{ idct8_c, iadst8_c }, // DCT_ADST = 2
{ iadst8_c, iadst8_c } // ADST_ADST = 3
};
void vp10_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride,
int tx_type) {
int i, j;
tran_low_t out[8 * 8];
tran_low_t *outptr = out;
tran_low_t temp_in[8], temp_out[8];
const transform_2d ht = IHT_8[tx_type];
// inverse transform row vectors
for (i = 0; i < 8; ++i) {
ht.rows(input, outptr);
input += 8;
outptr += 8;
}
// inverse transform column vectors
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
temp_in[j] = out[j * 8 + i];
ht.cols(temp_in, temp_out);
for (j = 0; j < 8; ++j) {
dest[j * stride + i] = clip_pixel_add(dest[j * stride + i],
ROUND_POWER_OF_TWO(temp_out[j], 5));
}
}
}
static const transform_2d IHT_16[] = {
{ idct16_c, idct16_c }, // DCT_DCT = 0
{ iadst16_c, idct16_c }, // ADST_DCT = 1
{ idct16_c, iadst16_c }, // DCT_ADST = 2
{ iadst16_c, iadst16_c } // ADST_ADST = 3
};
void vp10_iht16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride,
int tx_type) {
int i, j;
tran_low_t out[16 * 16];
tran_low_t *outptr = out;
tran_low_t temp_in[16], temp_out[16];
const transform_2d ht = IHT_16[tx_type];
// Rows
for (i = 0; i < 16; ++i) {
ht.rows(input, outptr);
input += 16;
outptr += 16;
}
// Columns
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j)
temp_in[j] = out[j * 16 + i];
ht.cols(temp_in, temp_out);
for (j = 0; j < 16; ++j) {
dest[j * stride + i] = clip_pixel_add(dest[j * stride + i],
ROUND_POWER_OF_TWO(temp_out[j], 6));
}
}
}
// idct
void vp10_idct4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob) {
if (eob > 1)
vpx_idct4x4_16_add(input, dest, stride);
else
vpx_idct4x4_1_add(input, dest, stride);
}
void vp10_iwht4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob) {
if (eob > 1)
vpx_iwht4x4_16_add(input, dest, stride);
else
vpx_iwht4x4_1_add(input, dest, stride);
}
void vp10_idct8x8_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob) {
// If dc is 1, then input[0] is the reconstructed value, do not need
// dequantization. Also, when dc is 1, dc is counted in eobs, namely eobs >=1.
// The calculation can be simplified if there are not many non-zero dct
// coefficients. Use eobs to decide what to do.
// TODO(yunqingwang): "eobs = 1" case is also handled in vp10_short_idct8x8_c.
// Combine that with code here.
if (eob == 1)
// DC only DCT coefficient
vpx_idct8x8_1_add(input, dest, stride);
else if (eob <= 12)
vpx_idct8x8_12_add(input, dest, stride);
else
vpx_idct8x8_64_add(input, dest, stride);
}
void vp10_idct16x16_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob) {
/* The calculation can be simplified if there are not many non-zero dct
* coefficients. Use eobs to separate different cases. */
if (eob == 1)
/* DC only DCT coefficient. */
vpx_idct16x16_1_add(input, dest, stride);
else if (eob <= 10)
vpx_idct16x16_10_add(input, dest, stride);
else
vpx_idct16x16_256_add(input, dest, stride);
}
void vp10_idct32x32_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob) {
if (eob == 1)
vpx_idct32x32_1_add(input, dest, stride);
else if (eob <= 34)
// non-zero coeff only in upper-left 8x8
vpx_idct32x32_34_add(input, dest, stride);
else
vpx_idct32x32_1024_add(input, dest, stride);
}
void vp10_inv_txfm_add_4x4(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type,
void (*itxm_add_4x4)(const tran_low_t *input,
uint8_t *dest, int stride, int eob)) {
switch (tx_type) {
case DCT_DCT:
itxm_add_4x4(input, dest, stride, eob);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
vp10_iht4x4_16_add(input, dest, stride, tx_type);
break;
default:
assert(0);
break;
}
}
void vp10_inv_txfm_add_8x8(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type) {
switch (tx_type) {
case DCT_DCT:
vp10_idct8x8_add(input, dest, stride, eob);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
vp10_iht8x8_64_add(input, dest, stride, tx_type);
break;
default:
assert(0);
break;
}
}
void vp10_inv_txfm_add_16x16(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type) {
switch (tx_type) {
case DCT_DCT:
vp10_idct16x16_add(input, dest, stride, eob);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
vp10_iht16x16_256_add(input, dest, stride, tx_type);
break;
default:
assert(0);
break;
}
}
void vp10_inv_txfm_add_32x32(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type) {
switch (tx_type) {
case DCT_DCT:
vp10_idct32x32_add(input, dest, stride, eob);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
assert(0);
break;
default:
assert(0);
break;
}
}
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest8,
int stride, int tx_type, int bd) {
const highbd_transform_2d IHT_4[] = {
{ vpx_highbd_idct4_c, vpx_highbd_idct4_c }, // DCT_DCT = 0
{ vpx_highbd_iadst4_c, vpx_highbd_idct4_c }, // ADST_DCT = 1
{ vpx_highbd_idct4_c, vpx_highbd_iadst4_c }, // DCT_ADST = 2
{ vpx_highbd_iadst4_c, vpx_highbd_iadst4_c } // ADST_ADST = 3
};
uint16_t *dest = CONVERT_TO_SHORTPTR(dest8);
int i, j;
tran_low_t out[4 * 4];
tran_low_t *outptr = out;
tran_low_t temp_in[4], temp_out[4];
// Inverse transform row vectors.
for (i = 0; i < 4; ++i) {
IHT_4[tx_type].rows(input, outptr, bd);
input += 4;
outptr += 4;
}
// Inverse transform column vectors.
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j)
temp_in[j] = out[j * 4 + i];
IHT_4[tx_type].cols(temp_in, temp_out, bd);
for (j = 0; j < 4; ++j) {
dest[j * stride + i] = highbd_clip_pixel_add(
dest[j * stride + i], ROUND_POWER_OF_TWO(temp_out[j], 4), bd);
}
}
}
static const highbd_transform_2d HIGH_IHT_8[] = {
{ vpx_highbd_idct8_c, vpx_highbd_idct8_c }, // DCT_DCT = 0
{ vpx_highbd_iadst8_c, vpx_highbd_idct8_c }, // ADST_DCT = 1
{ vpx_highbd_idct8_c, vpx_highbd_iadst8_c }, // DCT_ADST = 2
{ vpx_highbd_iadst8_c, vpx_highbd_iadst8_c } // ADST_ADST = 3
};
void vp10_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest8,
int stride, int tx_type, int bd) {
int i, j;
tran_low_t out[8 * 8];
tran_low_t *outptr = out;
tran_low_t temp_in[8], temp_out[8];
const highbd_transform_2d ht = HIGH_IHT_8[tx_type];
uint16_t *dest = CONVERT_TO_SHORTPTR(dest8);
// Inverse transform row vectors.
for (i = 0; i < 8; ++i) {
ht.rows(input, outptr, bd);
input += 8;
outptr += 8;
}
// Inverse transform column vectors.
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
temp_in[j] = out[j * 8 + i];
ht.cols(temp_in, temp_out, bd);
for (j = 0; j < 8; ++j) {
dest[j * stride + i] = highbd_clip_pixel_add(
dest[j * stride + i], ROUND_POWER_OF_TWO(temp_out[j], 5), bd);
}
}
}
static const highbd_transform_2d HIGH_IHT_16[] = {
{ vpx_highbd_idct16_c, vpx_highbd_idct16_c }, // DCT_DCT = 0
{ vpx_highbd_iadst16_c, vpx_highbd_idct16_c }, // ADST_DCT = 1
{ vpx_highbd_idct16_c, vpx_highbd_iadst16_c }, // DCT_ADST = 2
{ vpx_highbd_iadst16_c, vpx_highbd_iadst16_c } // ADST_ADST = 3
};
void vp10_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *dest8,
int stride, int tx_type, int bd) {
int i, j;
tran_low_t out[16 * 16];
tran_low_t *outptr = out;
tran_low_t temp_in[16], temp_out[16];
const highbd_transform_2d ht = HIGH_IHT_16[tx_type];
uint16_t *dest = CONVERT_TO_SHORTPTR(dest8);
// Rows
for (i = 0; i < 16; ++i) {
ht.rows(input, outptr, bd);
input += 16;
outptr += 16;
}
// Columns
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j)
temp_in[j] = out[j * 16 + i];
ht.cols(temp_in, temp_out, bd);
for (j = 0; j < 16; ++j) {
dest[j * stride + i] = highbd_clip_pixel_add(
dest[j * stride + i], ROUND_POWER_OF_TWO(temp_out[j], 6), bd);
}
}
}
// idct
void vp10_highbd_idct4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob, int bd) {
if (eob > 1)
vpx_highbd_idct4x4_16_add(input, dest, stride, bd);
else
vpx_highbd_idct4x4_1_add(input, dest, stride, bd);
}
void vp10_highbd_iwht4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob, int bd) {
if (eob > 1)
vpx_highbd_iwht4x4_16_add(input, dest, stride, bd);
else
vpx_highbd_iwht4x4_1_add(input, dest, stride, bd);
}
void vp10_highbd_idct8x8_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob, int bd) {
// If dc is 1, then input[0] is the reconstructed value, do not need
// dequantization. Also, when dc is 1, dc is counted in eobs, namely eobs >=1.
// The calculation can be simplified if there are not many non-zero dct
// coefficients. Use eobs to decide what to do.
// TODO(yunqingwang): "eobs = 1" case is also handled in vp10_short_idct8x8_c.
// Combine that with code here.
// DC only DCT coefficient
if (eob == 1) {
vpx_highbd_idct8x8_1_add(input, dest, stride, bd);
} else if (eob <= 10) {
vpx_highbd_idct8x8_10_add(input, dest, stride, bd);
} else {
vpx_highbd_idct8x8_64_add(input, dest, stride, bd);
}
}
void vp10_highbd_idct16x16_add(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd) {
// The calculation can be simplified if there are not many non-zero dct
// coefficients. Use eobs to separate different cases.
// DC only DCT coefficient.
if (eob == 1) {
vpx_highbd_idct16x16_1_add(input, dest, stride, bd);
} else if (eob <= 10) {
vpx_highbd_idct16x16_10_add(input, dest, stride, bd);
} else {
vpx_highbd_idct16x16_256_add(input, dest, stride, bd);
}
}
void vp10_highbd_idct32x32_add(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd) {
// Non-zero coeff only in upper-left 8x8
if (eob == 1) {
vpx_highbd_idct32x32_1_add(input, dest, stride, bd);
} else if (eob <= 34) {
vpx_highbd_idct32x32_34_add(input, dest, stride, bd);
} else {
vpx_highbd_idct32x32_1024_add(input, dest, stride, bd);
}
}
void vp10_highbd_inv_txfm_add_4x4(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd, TX_TYPE tx_type,
void (*highbd_itxm_add_4x4)
(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd)) {
switch (tx_type) {
case DCT_DCT:
highbd_itxm_add_4x4(input, dest, stride, eob, bd);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
vp10_highbd_iht4x4_16_add(input, dest, stride, tx_type, bd);
break;
default:
assert(0);
break;
}
}
void vp10_highbd_inv_txfm_add_8x8(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd,
TX_TYPE tx_type) {
switch (tx_type) {
case DCT_DCT:
vp10_highbd_idct8x8_add(input, dest, stride, eob, bd);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
vp10_highbd_iht8x8_64_add(input, dest, stride, tx_type, bd);
break;
default:
assert(0);
break;
}
}
void vp10_highbd_inv_txfm_add_16x16(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd,
TX_TYPE tx_type) {
switch (tx_type) {
case DCT_DCT:
vp10_highbd_idct16x16_add(input, dest, stride, eob, bd);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
vp10_highbd_iht16x16_256_add(input, dest, stride, tx_type, bd);
break;
default:
assert(0);
break;
}
}
void vp10_highbd_inv_txfm_add_32x32(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd,
TX_TYPE tx_type) {
switch (tx_type) {
case DCT_DCT:
vp10_highbd_idct32x32_add(input, dest, stride, eob, bd);
break;
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
assert(0);
break;
default:
assert(0);
break;
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH

86
vp10/common/idct.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_IDCT_H_
#define VP10_COMMON_IDCT_H_
#include <assert.h>
#include "./vpx_config.h"
#include "vp10/common/common.h"
#include "vp10/common/enums.h"
#include "vpx_dsp/inv_txfm.h"
#include "vpx_dsp/txfm_common.h"
#include "vpx_ports/mem.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*transform_1d)(const tran_low_t*, tran_low_t*);
typedef struct {
transform_1d cols, rows; // vertical and horizontal
} transform_2d;
#if CONFIG_VP9_HIGHBITDEPTH
typedef void (*highbd_transform_1d)(const tran_low_t*, tran_low_t*, int bd);
typedef struct {
highbd_transform_1d cols, rows; // vertical and horizontal
} highbd_transform_2d;
#endif // CONFIG_VP9_HIGHBITDEPTH
void vp10_iwht4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob);
void vp10_idct4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob);
void vp10_inv_txfm_add_4x4(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type,
void (*itxm_add_4x4)(const tran_low_t *input,
uint8_t *dest, int stride, int eob));
void vp10_inv_txfm_add_8x8(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type);
void vp10_inv_txfm_add_16x16(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type);
void vp10_inv_txfm_add_32x32(const tran_low_t *input, uint8_t *dest,
int stride, int eob, TX_TYPE tx_type);
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_iwht4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob, int bd);
void vp10_highbd_idct4x4_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob, int bd);
void vp10_highbd_idct8x8_add(const tran_low_t *input, uint8_t *dest, int stride,
int eob, int bd);
void vp10_highbd_idct16x16_add(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd);
void vp10_highbd_idct32x32_add(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd);
void vp10_highbd_inv_txfm_add_4x4(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd, TX_TYPE tx_type,
void (*highbd_itxm_add_4x4)
(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd));
void vp10_highbd_inv_txfm_add_8x8(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd, TX_TYPE tx_type);
void vp10_highbd_inv_txfm_add_16x16(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd,
TX_TYPE tx_type);
void vp10_highbd_inv_txfm_add_32x32(const tran_low_t *input, uint8_t *dest,
int stride, int eob, int bd,
TX_TYPE tx_type);
#endif // CONFIG_VP9_HIGHBITDEPTH
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_IDCT_H_

1618
vp10/common/loopfilter.c Normal file

File diff suppressed because it is too large Load Diff

154
vp10/common/loopfilter.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_LOOPFILTER_H_
#define VP10_COMMON_LOOPFILTER_H_
#include "vpx_ports/mem.h"
#include "./vpx_config.h"
#include "vp10/common/blockd.h"
#include "vp10/common/seg_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_LOOP_FILTER 63
#define MAX_SHARPNESS 7
#define SIMD_WIDTH 16
#define MAX_MODE_LF_DELTAS 2
enum lf_path {
LF_PATH_420,
LF_PATH_444,
LF_PATH_SLOW,
};
struct loopfilter {
int filter_level;
int sharpness_level;
int last_sharpness_level;
uint8_t mode_ref_delta_enabled;
uint8_t mode_ref_delta_update;
// 0 = Intra, Last, GF, ARF
signed char ref_deltas[MAX_REF_FRAMES];
signed char last_ref_deltas[MAX_REF_FRAMES];
// 0 = ZERO_MV, MV
signed char mode_deltas[MAX_MODE_LF_DELTAS];
signed char last_mode_deltas[MAX_MODE_LF_DELTAS];
};
// Need to align this structure so when it is declared and
// passed it can be loaded into vector registers.
typedef struct {
DECLARE_ALIGNED(SIMD_WIDTH, uint8_t, mblim[SIMD_WIDTH]);
DECLARE_ALIGNED(SIMD_WIDTH, uint8_t, lim[SIMD_WIDTH]);
DECLARE_ALIGNED(SIMD_WIDTH, uint8_t, hev_thr[SIMD_WIDTH]);
} loop_filter_thresh;
typedef struct {
loop_filter_thresh lfthr[MAX_LOOP_FILTER + 1];
uint8_t lvl[MAX_SEGMENTS][MAX_REF_FRAMES][MAX_MODE_LF_DELTAS];
} loop_filter_info_n;
// This structure holds bit masks for all 8x8 blocks in a 64x64 region.
// Each 1 bit represents a position in which we want to apply the loop filter.
// Left_ entries refer to whether we apply a filter on the border to the
// left of the block. Above_ entries refer to whether or not to apply a
// filter on the above border. Int_ entries refer to whether or not to
// apply borders on the 4x4 edges within the 8x8 block that each bit
// represents.
// Since each transform is accompanied by a potentially different type of
// loop filter there is a different entry in the array for each transform size.
typedef struct {
uint64_t left_y[TX_SIZES];
uint64_t above_y[TX_SIZES];
uint64_t int_4x4_y;
uint16_t left_uv[TX_SIZES];
uint16_t above_uv[TX_SIZES];
uint16_t int_4x4_uv;
uint8_t lfl_y[64];
uint8_t lfl_uv[16];
} LOOP_FILTER_MASK;
/* assorted loopfilter functions which get used elsewhere */
struct VP10Common;
struct macroblockd;
struct VP9LfSyncData;
// This function sets up the bit masks for the entire 64x64 region represented
// by mi_row, mi_col.
void vp10_setup_mask(struct VP10Common *const cm,
const int mi_row, const int mi_col,
MODE_INFO **mi_8x8, const int mode_info_stride,
LOOP_FILTER_MASK *lfm);
void vp10_filter_block_plane_ss00(struct VP10Common *const cm,
struct macroblockd_plane *const plane,
int mi_row,
LOOP_FILTER_MASK *lfm);
void vp10_filter_block_plane_ss11(struct VP10Common *const cm,
struct macroblockd_plane *const plane,
int mi_row,
LOOP_FILTER_MASK *lfm);
void vp10_filter_block_plane_non420(struct VP10Common *cm,
struct macroblockd_plane *plane,
MODE_INFO **mi_8x8,
int mi_row, int mi_col);
void vp10_loop_filter_init(struct VP10Common *cm);
// Update the loop filter for the current frame.
// This should be called before vp10_loop_filter_rows(), vp10_loop_filter_frame()
// calls this function directly.
void vp10_loop_filter_frame_init(struct VP10Common *cm, int default_filt_lvl);
void vp10_loop_filter_frame(YV12_BUFFER_CONFIG *frame,
struct VP10Common *cm,
struct macroblockd *mbd,
int filter_level,
int y_only, int partial_frame);
// Apply the loop filter to [start, stop) macro block rows in frame_buffer.
void vp10_loop_filter_rows(YV12_BUFFER_CONFIG *frame_buffer,
struct VP10Common *cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int start, int stop, int y_only);
typedef struct LoopFilterWorkerData {
YV12_BUFFER_CONFIG *frame_buffer;
struct VP10Common *cm;
struct macroblockd_plane planes[MAX_MB_PLANE];
int start;
int stop;
int y_only;
} LFWorkerData;
void vp10_loop_filter_data_reset(
LFWorkerData *lf_data, YV12_BUFFER_CONFIG *frame_buffer,
struct VP10Common *cm, const struct macroblockd_plane planes[MAX_MB_PLANE]);
// Operates on the rows described by 'lf_data'.
int vp10_loop_filter_worker(LFWorkerData *const lf_data, void *unused);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_LOOPFILTER_H_

394
vp10/common/mfqe.c Normal file
View File

@@ -0,0 +1,394 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_config.h"
#include "./vp10_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "./vpx_scale_rtcd.h"
#include "vp10/common/onyxc_int.h"
#include "vp10/common/postproc.h"
// TODO(jackychen): Replace this function with SSE2 code. There is
// one SSE2 implementation in vp8, so will consider how to share it
// between vp8 and vp9.
static void filter_by_weight(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
int block_size, int src_weight) {
const int dst_weight = (1 << MFQE_PRECISION) - src_weight;
const int rounding_bit = 1 << (MFQE_PRECISION - 1);
int r, c;
for (r = 0; r < block_size; r++) {
for (c = 0; c < block_size; c++) {
dst[c] = (src[c] * src_weight + dst[c] * dst_weight + rounding_bit)
>> MFQE_PRECISION;
}
src += src_stride;
dst += dst_stride;
}
}
void vp10_filter_by_weight8x8_c(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride, int src_weight) {
filter_by_weight(src, src_stride, dst, dst_stride, 8, src_weight);
}
void vp10_filter_by_weight16x16_c(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
int src_weight) {
filter_by_weight(src, src_stride, dst, dst_stride, 16, src_weight);
}
static void filter_by_weight32x32(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride, int weight) {
vp10_filter_by_weight16x16(src, src_stride, dst, dst_stride, weight);
vp10_filter_by_weight16x16(src + 16, src_stride, dst + 16, dst_stride,
weight);
vp10_filter_by_weight16x16(src + src_stride * 16, src_stride,
dst + dst_stride * 16, dst_stride, weight);
vp10_filter_by_weight16x16(src + src_stride * 16 + 16, src_stride,
dst + dst_stride * 16 + 16, dst_stride, weight);
}
static void filter_by_weight64x64(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride, int weight) {
filter_by_weight32x32(src, src_stride, dst, dst_stride, weight);
filter_by_weight32x32(src + 32, src_stride, dst + 32,
dst_stride, weight);
filter_by_weight32x32(src + src_stride * 32, src_stride,
dst + dst_stride * 32, dst_stride, weight);
filter_by_weight32x32(src + src_stride * 32 + 32, src_stride,
dst + dst_stride * 32 + 32, dst_stride, weight);
}
static void apply_ifactor(const uint8_t *y, int y_stride, uint8_t *yd,
int yd_stride, const uint8_t *u, const uint8_t *v,
int uv_stride, uint8_t *ud, uint8_t *vd,
int uvd_stride, BLOCK_SIZE block_size,
int weight) {
if (block_size == BLOCK_16X16) {
vp10_filter_by_weight16x16(y, y_stride, yd, yd_stride, weight);
vp10_filter_by_weight8x8(u, uv_stride, ud, uvd_stride, weight);
vp10_filter_by_weight8x8(v, uv_stride, vd, uvd_stride, weight);
} else if (block_size == BLOCK_32X32) {
filter_by_weight32x32(y, y_stride, yd, yd_stride, weight);
vp10_filter_by_weight16x16(u, uv_stride, ud, uvd_stride, weight);
vp10_filter_by_weight16x16(v, uv_stride, vd, uvd_stride, weight);
} else if (block_size == BLOCK_64X64) {
filter_by_weight64x64(y, y_stride, yd, yd_stride, weight);
filter_by_weight32x32(u, uv_stride, ud, uvd_stride, weight);
filter_by_weight32x32(v, uv_stride, vd, uvd_stride, weight);
}
}
// TODO(jackychen): Determine whether replace it with assembly code.
static void copy_mem8x8(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride) {
int r;
for (r = 0; r < 8; r++) {
memcpy(dst, src, 8);
src += src_stride;
dst += dst_stride;
}
}
static void copy_mem16x16(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride) {
int r;
for (r = 0; r < 16; r++) {
memcpy(dst, src, 16);
src += src_stride;
dst += dst_stride;
}
}
static void copy_mem32x32(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride) {
copy_mem16x16(src, src_stride, dst, dst_stride);
copy_mem16x16(src + 16, src_stride, dst + 16, dst_stride);
copy_mem16x16(src + src_stride * 16, src_stride,
dst + dst_stride * 16, dst_stride);
copy_mem16x16(src + src_stride * 16 + 16, src_stride,
dst + dst_stride * 16 + 16, dst_stride);
}
void copy_mem64x64(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride) {
copy_mem32x32(src, src_stride, dst, dst_stride);
copy_mem32x32(src + 32, src_stride, dst + 32, dst_stride);
copy_mem32x32(src + src_stride * 32, src_stride,
dst + src_stride * 32, dst_stride);
copy_mem32x32(src + src_stride * 32 + 32, src_stride,
dst + src_stride * 32 + 32, dst_stride);
}
static void copy_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,
int y_stride, int uv_stride, uint8_t *yd, uint8_t *ud,
uint8_t *vd, int yd_stride, int uvd_stride,
BLOCK_SIZE bs) {
if (bs == BLOCK_16X16) {
copy_mem16x16(y, y_stride, yd, yd_stride);
copy_mem8x8(u, uv_stride, ud, uvd_stride);
copy_mem8x8(v, uv_stride, vd, uvd_stride);
} else if (bs == BLOCK_32X32) {
copy_mem32x32(y, y_stride, yd, yd_stride);
copy_mem16x16(u, uv_stride, ud, uvd_stride);
copy_mem16x16(v, uv_stride, vd, uvd_stride);
} else {
copy_mem64x64(y, y_stride, yd, yd_stride);
copy_mem32x32(u, uv_stride, ud, uvd_stride);
copy_mem32x32(v, uv_stride, vd, uvd_stride);
}
}
static void get_thr(BLOCK_SIZE bs, int qdiff, int *sad_thr, int *vdiff_thr) {
const int adj = qdiff >> MFQE_PRECISION;
if (bs == BLOCK_16X16) {
*sad_thr = 7 + adj;
} else if (bs == BLOCK_32X32) {
*sad_thr = 6 + adj;
} else { // BLOCK_64X64
*sad_thr = 5 + adj;
}
*vdiff_thr = 125 + qdiff;
}
static void mfqe_block(BLOCK_SIZE bs, const uint8_t *y, const uint8_t *u,
const uint8_t *v, int y_stride, int uv_stride,
uint8_t *yd, uint8_t *ud, uint8_t *vd, int yd_stride,
int uvd_stride, int qdiff) {
int sad, sad_thr, vdiff, vdiff_thr;
uint32_t sse;
get_thr(bs, qdiff, &sad_thr, &vdiff_thr);
if (bs == BLOCK_16X16) {
vdiff = (vpx_variance16x16(y, y_stride, yd, yd_stride, &sse) + 128) >> 8;
sad = (vpx_sad16x16(y, y_stride, yd, yd_stride) + 128) >> 8;
} else if (bs == BLOCK_32X32) {
vdiff = (vpx_variance32x32(y, y_stride, yd, yd_stride, &sse) + 512) >> 10;
sad = (vpx_sad32x32(y, y_stride, yd, yd_stride) + 512) >> 10;
} else /* if (bs == BLOCK_64X64) */ {
vdiff = (vpx_variance64x64(y, y_stride, yd, yd_stride, &sse) + 2048) >> 12;
sad = (vpx_sad64x64(y, y_stride, yd, yd_stride) + 2048) >> 12;
}
// vdiff > sad * 3 means vdiff should not be too small, otherwise,
// it might be a lighting change in smooth area. When there is a
// lighting change in smooth area, it is dangerous to do MFQE.
if (sad > 1 && vdiff > sad * 3) {
const int weight = 1 << MFQE_PRECISION;
int ifactor = weight * sad * vdiff / (sad_thr * vdiff_thr);
// When ifactor equals weight, no MFQE is done.
if (ifactor > weight) {
ifactor = weight;
}
apply_ifactor(y, y_stride, yd, yd_stride, u, v, uv_stride, ud, vd,
uvd_stride, bs, ifactor);
} else {
// Copy the block from current frame (i.e., no mfqe is done).
copy_block(y, u, v, y_stride, uv_stride, yd, ud, vd,
yd_stride, uvd_stride, bs);
}
}
static int mfqe_decision(MODE_INFO *mi, BLOCK_SIZE cur_bs) {
// Check the motion in current block(for inter frame),
// or check the motion in the correlated block in last frame (for keyframe).
const int mv_len_square = mi->mbmi.mv[0].as_mv.row *
mi->mbmi.mv[0].as_mv.row +
mi->mbmi.mv[0].as_mv.col *
mi->mbmi.mv[0].as_mv.col;
const int mv_threshold = 100;
return mi->mbmi.mode >= NEARESTMV && // Not an intra block
cur_bs >= BLOCK_16X16 &&
mv_len_square <= mv_threshold;
}
// Process each partiton in a super block, recursively.
static void mfqe_partition(VP10_COMMON *cm, MODE_INFO *mi, BLOCK_SIZE bs,
const uint8_t *y, const uint8_t *u,
const uint8_t *v, int y_stride, int uv_stride,
uint8_t *yd, uint8_t *ud, uint8_t *vd,
int yd_stride, int uvd_stride) {
int mi_offset, y_offset, uv_offset;
const BLOCK_SIZE cur_bs = mi->mbmi.sb_type;
const int qdiff = cm->base_qindex - cm->postproc_state.last_base_qindex;
const int bsl = b_width_log2_lookup[bs];
PARTITION_TYPE partition = partition_lookup[bsl][cur_bs];
const BLOCK_SIZE subsize = get_subsize(bs, partition);
if (cur_bs < BLOCK_8X8) {
// If there are blocks smaller than 8x8, it must be on the boundary.
return;
}
// No MFQE on blocks smaller than 16x16
if (bs == BLOCK_16X16) {
partition = PARTITION_NONE;
}
if (bs == BLOCK_64X64) {
mi_offset = 4;
y_offset = 32;
uv_offset = 16;
} else {
mi_offset = 2;
y_offset = 16;
uv_offset = 8;
}
switch (partition) {
BLOCK_SIZE mfqe_bs, bs_tmp;
case PARTITION_HORZ:
if (bs == BLOCK_64X64) {
mfqe_bs = BLOCK_64X32;
bs_tmp = BLOCK_32X32;
} else {
mfqe_bs = BLOCK_32X16;
bs_tmp = BLOCK_16X16;
}
if (mfqe_decision(mi, mfqe_bs)) {
// Do mfqe on the first square partition.
mfqe_block(bs_tmp, y, u, v, y_stride, uv_stride,
yd, ud, vd, yd_stride, uvd_stride, qdiff);
// Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset, u + uv_offset, v + uv_offset,
y_stride, uv_stride, yd + y_offset, ud + uv_offset,
vd + uv_offset, yd_stride, uvd_stride, qdiff);
}
if (mfqe_decision(mi + mi_offset * cm->mi_stride, mfqe_bs)) {
// Do mfqe on the first square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride, u + uv_offset * uv_stride,
v + uv_offset * uv_stride, y_stride, uv_stride,
yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
vd + uv_offset * uvd_stride, yd_stride, uvd_stride, qdiff);
// Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride + y_offset,
u + uv_offset * uv_stride + uv_offset,
v + uv_offset * uv_stride + uv_offset, y_stride,
uv_stride, yd + y_offset * yd_stride + y_offset,
ud + uv_offset * uvd_stride + uv_offset,
vd + uv_offset * uvd_stride + uv_offset,
yd_stride, uvd_stride, qdiff);
}
break;
case PARTITION_VERT:
if (bs == BLOCK_64X64) {
mfqe_bs = BLOCK_32X64;
bs_tmp = BLOCK_32X32;
} else {
mfqe_bs = BLOCK_16X32;
bs_tmp = BLOCK_16X16;
}
if (mfqe_decision(mi, mfqe_bs)) {
// Do mfqe on the first square partition.
mfqe_block(bs_tmp, y, u, v, y_stride, uv_stride,
yd, ud, vd, yd_stride, uvd_stride, qdiff);
// Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride, u + uv_offset * uv_stride,
v + uv_offset * uv_stride, y_stride, uv_stride,
yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
vd + uv_offset * uvd_stride, yd_stride, uvd_stride, qdiff);
}
if (mfqe_decision(mi + mi_offset, mfqe_bs)) {
// Do mfqe on the first square partition.
mfqe_block(bs_tmp, y + y_offset, u + uv_offset, v + uv_offset,
y_stride, uv_stride, yd + y_offset, ud + uv_offset,
vd + uv_offset, yd_stride, uvd_stride, qdiff);
// Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride + y_offset,
u + uv_offset * uv_stride + uv_offset,
v + uv_offset * uv_stride + uv_offset, y_stride,
uv_stride, yd + y_offset * yd_stride + y_offset,
ud + uv_offset * uvd_stride + uv_offset,
vd + uv_offset * uvd_stride + uv_offset,
yd_stride, uvd_stride, qdiff);
}
break;
case PARTITION_NONE:
if (mfqe_decision(mi, cur_bs)) {
// Do mfqe on this partition.
mfqe_block(cur_bs, y, u, v, y_stride, uv_stride,
yd, ud, vd, yd_stride, uvd_stride, qdiff);
} else {
// Copy the block from current frame(i.e., no mfqe is done).
copy_block(y, u, v, y_stride, uv_stride, yd, ud, vd,
yd_stride, uvd_stride, bs);
}
break;
case PARTITION_SPLIT:
// Recursion on four square partitions, e.g. if bs is 64X64,
// then look into four 32X32 blocks in it.
mfqe_partition(cm, mi, subsize, y, u, v, y_stride, uv_stride, yd, ud, vd,
yd_stride, uvd_stride);
mfqe_partition(cm, mi + mi_offset, subsize, y + y_offset, u + uv_offset,
v + uv_offset, y_stride, uv_stride, yd + y_offset,
ud + uv_offset, vd + uv_offset, yd_stride, uvd_stride);
mfqe_partition(cm, mi + mi_offset * cm->mi_stride, subsize,
y + y_offset * y_stride, u + uv_offset * uv_stride,
v + uv_offset * uv_stride, y_stride, uv_stride,
yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
vd + uv_offset * uvd_stride, yd_stride, uvd_stride);
mfqe_partition(cm, mi + mi_offset * cm->mi_stride + mi_offset,
subsize, y + y_offset * y_stride + y_offset,
u + uv_offset * uv_stride + uv_offset,
v + uv_offset * uv_stride + uv_offset, y_stride,
uv_stride, yd + y_offset * yd_stride + y_offset,
ud + uv_offset * uvd_stride + uv_offset,
vd + uv_offset * uvd_stride + uv_offset,
yd_stride, uvd_stride);
break;
default:
assert(0);
}
}
void vp10_mfqe(VP10_COMMON *cm) {
int mi_row, mi_col;
// Current decoded frame.
const YV12_BUFFER_CONFIG *show = cm->frame_to_show;
// Last decoded frame and will store the MFQE result.
YV12_BUFFER_CONFIG *dest = &cm->post_proc_buffer;
// Loop through each super block.
for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE) {
for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) {
MODE_INFO *mi;
MODE_INFO *mi_local = cm->mi + (mi_row * cm->mi_stride + mi_col);
// Motion Info in last frame.
MODE_INFO *mi_prev = cm->postproc_state.prev_mi +
(mi_row * cm->mi_stride + mi_col);
const uint32_t y_stride = show->y_stride;
const uint32_t uv_stride = show->uv_stride;
const uint32_t yd_stride = dest->y_stride;
const uint32_t uvd_stride = dest->uv_stride;
const uint32_t row_offset_y = mi_row << 3;
const uint32_t row_offset_uv = mi_row << 2;
const uint32_t col_offset_y = mi_col << 3;
const uint32_t col_offset_uv = mi_col << 2;
const uint8_t *y = show->y_buffer + row_offset_y * y_stride +
col_offset_y;
const uint8_t *u = show->u_buffer + row_offset_uv * uv_stride +
col_offset_uv;
const uint8_t *v = show->v_buffer + row_offset_uv * uv_stride +
col_offset_uv;
uint8_t *yd = dest->y_buffer + row_offset_y * yd_stride + col_offset_y;
uint8_t *ud = dest->u_buffer + row_offset_uv * uvd_stride +
col_offset_uv;
uint8_t *vd = dest->v_buffer + row_offset_uv * uvd_stride +
col_offset_uv;
if (frame_is_intra_only(cm)) {
mi = mi_prev;
} else {
mi = mi_local;
}
mfqe_partition(cm, mi, BLOCK_64X64, y, u, v, y_stride, uv_stride, yd, ud,
vd, yd_stride, uvd_stride);
}
}
}

31
vp10/common/mfqe.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_MFQE_H_
#define VP10_COMMON_MFQE_H_
#ifdef __cplusplus
extern "C" {
#endif
// Multiframe Quality Enhancement.
// The aim for MFQE is to replace pixel blocks in the current frame with
// the correlated pixel blocks (with higher quality) in the last frame.
// The replacement can only be taken in stationary blocks by checking
// the motion of the blocks and other conditions such as the SAD of
// the current block and correlated block, the variance of the block
// difference, etc.
void vp10_mfqe(struct VP10Common *cm);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_MFQE_H_

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2013 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 <assert.h>
#include <stdio.h>
#include "./vpx_config.h"
#include "./vp10_rtcd.h"
#include "vp10/common/common.h"
#include "vp10/common/blockd.h"
#include "vp10/common/idct.h"
#include "vpx_dsp/mips/inv_txfm_dspr2.h"
#include "vpx_dsp/txfm_common.h"
#include "vpx_ports/mem.h"
#if HAVE_DSPR2
void vp10_iht16x16_256_add_dspr2(const int16_t *input, uint8_t *dest,
int pitch, int tx_type) {
int i, j;
DECLARE_ALIGNED(32, int16_t, out[16 * 16]);
int16_t *outptr = out;
int16_t temp_out[16];
uint32_t pos = 45;
/* bit positon for extract from acc */
__asm__ __volatile__ (
"wrdsp %[pos], 1 \n\t"
:
: [pos] "r" (pos)
);
switch (tx_type) {
case DCT_DCT: // DCT in both horizontal and vertical
idct16_rows_dspr2(input, outptr, 16);
idct16_cols_add_blk_dspr2(out, dest, pitch);
break;
case ADST_DCT: // ADST in vertical, DCT in horizontal
idct16_rows_dspr2(input, outptr, 16);
outptr = out;
for (i = 0; i < 16; ++i) {
iadst16_dspr2(outptr, temp_out);
for (j = 0; j < 16; ++j)
dest[j * pitch + i] =
clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 6)
+ dest[j * pitch + i]);
outptr += 16;
}
break;
case DCT_ADST: // DCT in vertical, ADST in horizontal
{
int16_t temp_in[16 * 16];
for (i = 0; i < 16; ++i) {
/* prefetch row */
prefetch_load((const uint8_t *)(input + 16));
iadst16_dspr2(input, outptr);
input += 16;
outptr += 16;
}
for (i = 0; i < 16; ++i)
for (j = 0; j < 16; ++j)
temp_in[j * 16 + i] = out[i * 16 + j];
idct16_cols_add_blk_dspr2(temp_in, dest, pitch);
}
break;
case ADST_ADST: // ADST in both directions
{
int16_t temp_in[16];
for (i = 0; i < 16; ++i) {
/* prefetch row */
prefetch_load((const uint8_t *)(input + 16));
iadst16_dspr2(input, outptr);
input += 16;
outptr += 16;
}
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j)
temp_in[j] = out[j * 16 + i];
iadst16_dspr2(temp_in, temp_out);
for (j = 0; j < 16; ++j)
dest[j * pitch + i] =
clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 6)
+ dest[j * pitch + i]);
}
}
break;
default:
printf("vp10_short_iht16x16_add_dspr2 : Invalid tx_type\n");
break;
}
}
#endif // #if HAVE_DSPR2

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2013 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 <assert.h>
#include <stdio.h>
#include "./vpx_config.h"
#include "./vp10_rtcd.h"
#include "vp10/common/common.h"
#include "vp10/common/blockd.h"
#include "vp10/common/idct.h"
#include "vpx_dsp/mips/inv_txfm_dspr2.h"
#include "vpx_dsp/txfm_common.h"
#include "vpx_ports/mem.h"
#if HAVE_DSPR2
void vp10_iht4x4_16_add_dspr2(const int16_t *input, uint8_t *dest,
int dest_stride, int tx_type) {
int i, j;
DECLARE_ALIGNED(32, int16_t, out[4 * 4]);
int16_t *outptr = out;
int16_t temp_in[4 * 4], temp_out[4];
uint32_t pos = 45;
/* bit positon for extract from acc */
__asm__ __volatile__ (
"wrdsp %[pos], 1 \n\t"
:
: [pos] "r" (pos)
);
switch (tx_type) {
case DCT_DCT: // DCT in both horizontal and vertical
vpx_idct4_rows_dspr2(input, outptr);
vpx_idct4_columns_add_blk_dspr2(&out[0], dest, dest_stride);
break;
case ADST_DCT: // ADST in vertical, DCT in horizontal
vpx_idct4_rows_dspr2(input, outptr);
outptr = out;
for (i = 0; i < 4; ++i) {
iadst4_dspr2(outptr, temp_out);
for (j = 0; j < 4; ++j)
dest[j * dest_stride + i] =
clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 4)
+ dest[j * dest_stride + i]);
outptr += 4;
}
break;
case DCT_ADST: // DCT in vertical, ADST in horizontal
for (i = 0; i < 4; ++i) {
iadst4_dspr2(input, outptr);
input += 4;
outptr += 4;
}
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j) {
temp_in[i * 4 + j] = out[j * 4 + i];
}
}
vpx_idct4_columns_add_blk_dspr2(&temp_in[0], dest, dest_stride);
break;
case ADST_ADST: // ADST in both directions
for (i = 0; i < 4; ++i) {
iadst4_dspr2(input, outptr);
input += 4;
outptr += 4;
}
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j)
temp_in[j] = out[j * 4 + i];
iadst4_dspr2(temp_in, temp_out);
for (j = 0; j < 4; ++j)
dest[j * dest_stride + i] =
clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 4)
+ dest[j * dest_stride + i]);
}
break;
default:
printf("vp10_short_iht4x4_add_dspr2 : Invalid tx_type\n");
break;
}
}
#endif // #if HAVE_DSPR2

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2013 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 <assert.h>
#include <stdio.h>
#include "./vpx_config.h"
#include "./vp10_rtcd.h"
#include "vp10/common/common.h"
#include "vp10/common/blockd.h"
#include "vpx_dsp/mips/inv_txfm_dspr2.h"
#include "vpx_dsp/txfm_common.h"
#include "vpx_ports/mem.h"
#if HAVE_DSPR2
void vp10_iht8x8_64_add_dspr2(const int16_t *input, uint8_t *dest,
int dest_stride, int tx_type) {
int i, j;
DECLARE_ALIGNED(32, int16_t, out[8 * 8]);
int16_t *outptr = out;
int16_t temp_in[8 * 8], temp_out[8];
uint32_t pos = 45;
/* bit positon for extract from acc */
__asm__ __volatile__ (
"wrdsp %[pos], 1 \n\t"
:
: [pos] "r" (pos)
);
switch (tx_type) {
case DCT_DCT: // DCT in both horizontal and vertical
idct8_rows_dspr2(input, outptr, 8);
idct8_columns_add_blk_dspr2(&out[0], dest, dest_stride);
break;
case ADST_DCT: // ADST in vertical, DCT in horizontal
idct8_rows_dspr2(input, outptr, 8);
for (i = 0; i < 8; ++i) {
iadst8_dspr2(&out[i * 8], temp_out);
for (j = 0; j < 8; ++j)
dest[j * dest_stride + i] =
clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 5)
+ dest[j * dest_stride + i]);
}
break;
case DCT_ADST: // DCT in vertical, ADST in horizontal
for (i = 0; i < 8; ++i) {
iadst8_dspr2(input, outptr);
input += 8;
outptr += 8;
}
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j) {
temp_in[i * 8 + j] = out[j * 8 + i];
}
}
idct8_columns_add_blk_dspr2(&temp_in[0], dest, dest_stride);
break;
case ADST_ADST: // ADST in both directions
for (i = 0; i < 8; ++i) {
iadst8_dspr2(input, outptr);
input += 8;
outptr += 8;
}
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
temp_in[j] = out[j * 8 + i];
iadst8_dspr2(temp_in, temp_out);
for (j = 0; j < 8; ++j)
dest[j * dest_stride + i] =
clip_pixel(ROUND_POWER_OF_TWO(temp_out[j], 5)
+ dest[j * dest_stride + i]);
}
break;
default:
printf("vp10_short_iht8x8_add_dspr2 : Invalid tx_type\n");
break;
}
}
#endif // #if HAVE_DSPR2

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2015 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 <assert.h>
#include "vp10/common/enums.h"
#include "vpx_dsp/mips/inv_txfm_msa.h"
void vp10_iht16x16_256_add_msa(const int16_t *input, uint8_t *dst,
int32_t dst_stride, int32_t tx_type) {
int32_t i;
DECLARE_ALIGNED(32, int16_t, out[16 * 16]);
int16_t *out_ptr = &out[0];
switch (tx_type) {
case DCT_DCT:
/* transform rows */
for (i = 0; i < 2; ++i) {
/* process 16 * 8 block */
vpx_idct16_1d_rows_msa((input + (i << 7)), (out_ptr + (i << 7)));
}
/* transform columns */
for (i = 0; i < 2; ++i) {
/* process 8 * 16 block */
vpx_idct16_1d_columns_addblk_msa((out_ptr + (i << 3)), (dst + (i << 3)),
dst_stride);
}
break;
case ADST_DCT:
/* transform rows */
for (i = 0; i < 2; ++i) {
/* process 16 * 8 block */
vpx_idct16_1d_rows_msa((input + (i << 7)), (out_ptr + (i << 7)));
}
/* transform columns */
for (i = 0; i < 2; ++i) {
vpx_iadst16_1d_columns_addblk_msa((out_ptr + (i << 3)),
(dst + (i << 3)), dst_stride);
}
break;
case DCT_ADST:
/* transform rows */
for (i = 0; i < 2; ++i) {
/* process 16 * 8 block */
vpx_iadst16_1d_rows_msa((input + (i << 7)), (out_ptr + (i << 7)));
}
/* transform columns */
for (i = 0; i < 2; ++i) {
/* process 8 * 16 block */
vpx_idct16_1d_columns_addblk_msa((out_ptr + (i << 3)), (dst + (i << 3)),
dst_stride);
}
break;
case ADST_ADST:
/* transform rows */
for (i = 0; i < 2; ++i) {
/* process 16 * 8 block */
vpx_iadst16_1d_rows_msa((input + (i << 7)), (out_ptr + (i << 7)));
}
/* transform columns */
for (i = 0; i < 2; ++i) {
vpx_iadst16_1d_columns_addblk_msa((out_ptr + (i << 3)),
(dst + (i << 3)), dst_stride);
}
break;
default:
assert(0);
break;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2015 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 <assert.h>
#include "vp10/common/enums.h"
#include "vpx_dsp/mips/inv_txfm_msa.h"
void vp10_iht4x4_16_add_msa(const int16_t *input, uint8_t *dst,
int32_t dst_stride, int32_t tx_type) {
v8i16 in0, in1, in2, in3;
/* load vector elements of 4x4 block */
LD4x4_SH(input, in0, in1, in2, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
switch (tx_type) {
case DCT_DCT:
/* DCT in horizontal */
VP9_IDCT4x4(in0, in1, in2, in3, in0, in1, in2, in3);
/* DCT in vertical */
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
VP9_IDCT4x4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
case ADST_DCT:
/* DCT in horizontal */
VP9_IDCT4x4(in0, in1, in2, in3, in0, in1, in2, in3);
/* ADST in vertical */
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
VP9_IADST4x4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
case DCT_ADST:
/* ADST in horizontal */
VP9_IADST4x4(in0, in1, in2, in3, in0, in1, in2, in3);
/* DCT in vertical */
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
VP9_IDCT4x4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
case ADST_ADST:
/* ADST in horizontal */
VP9_IADST4x4(in0, in1, in2, in3, in0, in1, in2, in3);
/* ADST in vertical */
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
VP9_IADST4x4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
default:
assert(0);
break;
}
/* final rounding (add 2^3, divide by 2^4) and shift */
SRARI_H4_SH(in0, in1, in2, in3, 4);
/* add block and store 4x4 */
ADDBLK_ST4x4_UB(in0, in1, in2, in3, dst, dst_stride);
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2015 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 <assert.h>
#include "vp10/common/enums.h"
#include "vpx_dsp/mips/inv_txfm_msa.h"
void vp10_iht8x8_64_add_msa(const int16_t *input, uint8_t *dst,
int32_t dst_stride, int32_t tx_type) {
v8i16 in0, in1, in2, in3, in4, in5, in6, in7;
/* load vector elements of 8x8 block */
LD_SH8(input, 8, in0, in1, in2, in3, in4, in5, in6, in7);
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
switch (tx_type) {
case DCT_DCT:
/* DCT in horizontal */
VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
/* DCT in vertical */
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
break;
case ADST_DCT:
/* DCT in horizontal */
VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
/* ADST in vertical */
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
VP9_ADST8(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
break;
case DCT_ADST:
/* ADST in horizontal */
VP9_ADST8(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
/* DCT in vertical */
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
break;
case ADST_ADST:
/* ADST in horizontal */
VP9_ADST8(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
/* ADST in vertical */
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
VP9_ADST8(in0, in1, in2, in3, in4, in5, in6, in7,
in0, in1, in2, in3, in4, in5, in6, in7);
break;
default:
assert(0);
break;
}
/* final rounding (add 2^4, divide by 2^5) and shift */
SRARI_H4_SH(in0, in1, in2, in3, 5);
SRARI_H4_SH(in4, in5, in6, in7, 5);
/* add block and store 8x8 */
VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3);
dst += (4 * dst_stride);
VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in4, in5, in6, in7);
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2015 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 "./vp10_rtcd.h"
#include "vp10/common/onyxc_int.h"
#include "vpx_dsp/mips/macros_msa.h"
static void filter_by_weight8x8_msa(const uint8_t *src_ptr, int32_t src_stride,
uint8_t *dst_ptr, int32_t dst_stride,
int32_t src_weight) {
int32_t dst_weight = (1 << MFQE_PRECISION) - src_weight;
int32_t row;
uint64_t src0_d, src1_d, dst0_d, dst1_d;
v16i8 src0 = { 0 };
v16i8 src1 = { 0 };
v16i8 dst0 = { 0 };
v16i8 dst1 = { 0 };
v8i16 src_wt, dst_wt, res_h_r, res_h_l, src_r, src_l, dst_r, dst_l;
src_wt = __msa_fill_h(src_weight);
dst_wt = __msa_fill_h(dst_weight);
for (row = 2; row--;) {
LD2(src_ptr, src_stride, src0_d, src1_d);
src_ptr += (2 * src_stride);
LD2(dst_ptr, dst_stride, dst0_d, dst1_d);
INSERT_D2_SB(src0_d, src1_d, src0);
INSERT_D2_SB(dst0_d, dst1_d, dst0);
LD2(src_ptr, src_stride, src0_d, src1_d);
src_ptr += (2 * src_stride);
LD2((dst_ptr + 2 * dst_stride), dst_stride, dst0_d, dst1_d);
INSERT_D2_SB(src0_d, src1_d, src1);
INSERT_D2_SB(dst0_d, dst1_d, dst1);
UNPCK_UB_SH(src0, src_r, src_l);
UNPCK_UB_SH(dst0, dst_r, dst_l);
res_h_r = (src_r * src_wt);
res_h_r += (dst_r * dst_wt);
res_h_l = (src_l * src_wt);
res_h_l += (dst_l * dst_wt);
SRARI_H2_SH(res_h_r, res_h_l, MFQE_PRECISION);
dst0 = (v16i8)__msa_pckev_b((v16i8)res_h_l, (v16i8)res_h_r);
ST8x2_UB(dst0, dst_ptr, dst_stride);
dst_ptr += (2 * dst_stride);
UNPCK_UB_SH(src1, src_r, src_l);
UNPCK_UB_SH(dst1, dst_r, dst_l);
res_h_r = (src_r * src_wt);
res_h_r += (dst_r * dst_wt);
res_h_l = (src_l * src_wt);
res_h_l += (dst_l * dst_wt);
SRARI_H2_SH(res_h_r, res_h_l, MFQE_PRECISION);
dst1 = (v16i8)__msa_pckev_b((v16i8)res_h_l, (v16i8)res_h_r);
ST8x2_UB(dst1, dst_ptr, dst_stride);
dst_ptr += (2 * dst_stride);
}
}
static void filter_by_weight16x16_msa(const uint8_t *src_ptr,
int32_t src_stride,
uint8_t *dst_ptr,
int32_t dst_stride,
int32_t src_weight) {
int32_t dst_weight = (1 << MFQE_PRECISION) - src_weight;
int32_t row;
v16i8 src0, src1, src2, src3, dst0, dst1, dst2, dst3;
v8i16 src_wt, dst_wt, res_h_r, res_h_l, src_r, src_l, dst_r, dst_l;
src_wt = __msa_fill_h(src_weight);
dst_wt = __msa_fill_h(dst_weight);
for (row = 4; row--;) {
LD_SB4(src_ptr, src_stride, src0, src1, src2, src3);
src_ptr += (4 * src_stride);
LD_SB4(dst_ptr, dst_stride, dst0, dst1, dst2, dst3);
UNPCK_UB_SH(src0, src_r, src_l);
UNPCK_UB_SH(dst0, dst_r, dst_l);
res_h_r = (src_r * src_wt);
res_h_r += (dst_r * dst_wt);
res_h_l = (src_l * src_wt);
res_h_l += (dst_l * dst_wt);
SRARI_H2_SH(res_h_r, res_h_l, MFQE_PRECISION);
PCKEV_ST_SB(res_h_r, res_h_l, dst_ptr);
dst_ptr += dst_stride;
UNPCK_UB_SH(src1, src_r, src_l);
UNPCK_UB_SH(dst1, dst_r, dst_l);
res_h_r = (src_r * src_wt);
res_h_r += (dst_r * dst_wt);
res_h_l = (src_l * src_wt);
res_h_l += (dst_l * dst_wt);
SRARI_H2_SH(res_h_r, res_h_l, MFQE_PRECISION);
PCKEV_ST_SB(res_h_r, res_h_l, dst_ptr);
dst_ptr += dst_stride;
UNPCK_UB_SH(src2, src_r, src_l);
UNPCK_UB_SH(dst2, dst_r, dst_l);
res_h_r = (src_r * src_wt);
res_h_r += (dst_r * dst_wt);
res_h_l = (src_l * src_wt);
res_h_l += (dst_l * dst_wt);
SRARI_H2_SH(res_h_r, res_h_l, MFQE_PRECISION);
PCKEV_ST_SB(res_h_r, res_h_l, dst_ptr);
dst_ptr += dst_stride;
UNPCK_UB_SH(src3, src_r, src_l);
UNPCK_UB_SH(dst3, dst_r, dst_l);
res_h_r = (src_r * src_wt);
res_h_r += (dst_r * dst_wt);
res_h_l = (src_l * src_wt);
res_h_l += (dst_l * dst_wt);
SRARI_H2_SH(res_h_r, res_h_l, MFQE_PRECISION);
PCKEV_ST_SB(res_h_r, res_h_l, dst_ptr);
dst_ptr += dst_stride;
}
}
void vp10_filter_by_weight8x8_msa(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
int src_weight) {
filter_by_weight8x8_msa(src, src_stride, dst, dst_stride, src_weight);
}
void vp10_filter_by_weight16x16_msa(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
int src_weight) {
filter_by_weight16x16_msa(src, src_stride, dst, dst_stride, src_weight);
}

55
vp10/common/mv.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_MV_H_
#define VP10_COMMON_MV_H_
#include "vpx/vpx_integer.h"
#include "vp10/common/common.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mv {
int16_t row;
int16_t col;
} MV;
typedef union int_mv {
uint32_t as_int;
MV as_mv;
} int_mv; /* facilitates faster equality tests and copies */
typedef struct mv32 {
int32_t row;
int32_t col;
} MV32;
static INLINE int is_zero_mv(const MV *mv) {
return *((const uint32_t *)mv) == 0;
}
static INLINE int is_equal_mv(const MV *a, const MV *b) {
return *((const uint32_t *)a) == *((const uint32_t *)b);
}
static INLINE void clamp_mv(MV *mv, int min_col, int max_col,
int min_row, int max_row) {
mv->col = clamp(mv->col, min_col, max_col);
mv->row = clamp(mv->row, min_row, max_row);
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_MV_H_

229
vp10/common/mvref_common.c Normal file
View File

@@ -0,0 +1,229 @@
/*
* 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 "vp10/common/mvref_common.h"
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
static void find_mv_refs_idx(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int block, int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data,
uint8_t *mode_context) {
const int *ref_sign_bias = cm->ref_frame_sign_bias;
int i, refmv_count = 0;
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
int different_ref_found = 0;
int context_counter = 0;
const MV_REF *const prev_frame_mvs = cm->use_prev_frame_mvs ?
cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col : NULL;
const TileInfo *const tile = &xd->tile;
// Blank the reference vector list
memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
// The nearest 2 blocks are treated differently
// if the size < 8x8 we get the mv from the bmi substructure,
// and we also need to keep a mode count.
for (i = 0; i < 2; ++i) {
const POSITION *const mv_ref = &mv_ref_search[i];
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
const MODE_INFO *const candidate_mi = xd->mi[mv_ref->col + mv_ref->row *
xd->mi_stride];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
// Keep counts for entropy encoding.
context_counter += mode_2_counter[candidate->mode];
different_ref_found = 1;
if (candidate->ref_frame[0] == ref_frame)
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
refmv_count, mv_ref_list, Done);
else if (candidate->ref_frame[1] == ref_frame)
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
refmv_count, mv_ref_list, Done);
}
}
// Check the rest of the neighbors in much the same way
// as before except we don't need to keep track of sub blocks or
// mode counts.
for (; i < MVREF_NEIGHBOURS; ++i) {
const POSITION *const mv_ref = &mv_ref_search[i];
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row *
xd->mi_stride]->mbmi;
different_ref_found = 1;
if (candidate->ref_frame[0] == ref_frame)
ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, Done);
else if (candidate->ref_frame[1] == ref_frame)
ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, Done);
}
}
// TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
// on windows platform. The sync here is unncessary if use_perv_frame_mvs
// is 0. But after removing it, there will be hang in the unit test on windows
// due to several threads waiting for a thread's signal.
#if defined(_WIN32) && !HAVE_PTHREAD_H
if (cm->frame_parallel_decode && sync != NULL) {
sync(data, mi_row);
}
#endif
// Check the last frame's mode and mv info.
if (cm->use_prev_frame_mvs) {
// Synchronize here for frame parallel decode if sync function is provided.
if (cm->frame_parallel_decode && sync != NULL) {
sync(data, mi_row);
}
if (prev_frame_mvs->ref_frame[0] == ref_frame) {
ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, Done);
} else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, Done);
}
}
// Since we couldn't find 2 mvs from the same reference frame
// go back through the neighbors and find motion vectors from
// different reference frames.
if (different_ref_found) {
for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
const POSITION *mv_ref = &mv_ref_search[i];
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row
* xd->mi_stride]->mbmi;
// If the candidate is INTRA we don't want to consider its mv.
IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
refmv_count, mv_ref_list, Done);
}
}
}
// Since we still don't have a candidate we'll try the last frame.
if (cm->use_prev_frame_mvs) {
if (prev_frame_mvs->ref_frame[0] != ref_frame &&
prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
int_mv mv = prev_frame_mvs->mv[0];
if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
ref_sign_bias[ref_frame]) {
mv.as_mv.row *= -1;
mv.as_mv.col *= -1;
}
ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
}
if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
prev_frame_mvs->ref_frame[1] != ref_frame &&
prev_frame_mvs->mv[1].as_int != prev_frame_mvs->mv[0].as_int) {
int_mv mv = prev_frame_mvs->mv[1];
if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
ref_sign_bias[ref_frame]) {
mv.as_mv.row *= -1;
mv.as_mv.col *= -1;
}
ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
}
}
Done:
mode_context[ref_frame] = counter_to_context[context_counter];
// Clamp vectors
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
}
void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data,
uint8_t *mode_context) {
find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, sync, data, mode_context);
}
static void lower_mv_precision(MV *mv, int allow_hp) {
const int use_hp = allow_hp && vp10_use_mv_hp(mv);
if (!use_hp) {
if (mv->row & 1)
mv->row += (mv->row > 0 ? -1 : 1);
if (mv->col & 1)
mv->col += (mv->col > 0 ? -1 : 1);
}
}
void vp10_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
int_mv *mvlist, int_mv *nearest_mv,
int_mv *near_mv) {
int i;
// Make sure all the candidates are properly clamped etc
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
lower_mv_precision(&mvlist[i].as_mv, allow_hp);
clamp_mv2(&mvlist[i].as_mv, xd);
}
*nearest_mv = mvlist[0];
*near_mv = mvlist[1];
}
void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
int block, int ref, int mi_row, int mi_col,
int_mv *nearest_mv, int_mv *near_mv,
uint8_t *mode_context) {
int_mv mv_list[MAX_MV_REF_CANDIDATES];
MODE_INFO *const mi = xd->mi[0];
b_mode_info *bmi = mi->bmi;
int n;
assert(MAX_MV_REF_CANDIDATES == 2);
find_mv_refs_idx(cm, xd, mi, mi->mbmi.ref_frame[ref], mv_list, block,
mi_row, mi_col, NULL, NULL, mode_context);
near_mv->as_int = 0;
switch (block) {
case 0:
nearest_mv->as_int = mv_list[0].as_int;
near_mv->as_int = mv_list[1].as_int;
break;
case 1:
case 2:
nearest_mv->as_int = bmi[0].as_mv[ref].as_int;
for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
if (nearest_mv->as_int != mv_list[n].as_int) {
near_mv->as_int = mv_list[n].as_int;
break;
}
break;
case 3: {
int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
candidates[0] = bmi[1].as_mv[ref];
candidates[1] = bmi[0].as_mv[ref];
candidates[2] = mv_list[0];
candidates[3] = mv_list[1];
nearest_mv->as_int = bmi[2].as_mv[ref].as_int;
for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
if (nearest_mv->as_int != candidates[n].as_int) {
near_mv->as_int = candidates[n].as_int;
break;
}
break;
}
default:
assert(0 && "Invalid block index.");
}
}

232
vp10/common/mvref_common.h Normal file
View File

@@ -0,0 +1,232 @@
/*
* 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.
*/
#ifndef VP10_COMMON_MVREF_COMMON_H_
#define VP10_COMMON_MVREF_COMMON_H_
#include "vp10/common/onyxc_int.h"
#include "vp10/common/blockd.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LEFT_TOP_MARGIN ((VP9_ENC_BORDER_IN_PIXELS - VP9_INTERP_EXTEND) << 3)
#define RIGHT_BOTTOM_MARGIN ((VP9_ENC_BORDER_IN_PIXELS -\
VP9_INTERP_EXTEND) << 3)
#define MVREF_NEIGHBOURS 8
typedef struct position {
int row;
int col;
} POSITION;
typedef enum {
BOTH_ZERO = 0,
ZERO_PLUS_PREDICTED = 1,
BOTH_PREDICTED = 2,
NEW_PLUS_NON_INTRA = 3,
BOTH_NEW = 4,
INTRA_PLUS_NON_INTRA = 5,
BOTH_INTRA = 6,
INVALID_CASE = 9
} motion_vector_context;
// This is used to figure out a context for the ref blocks. The code flattens
// an array that would have 3 possible counts (0, 1 & 2) for 3 choices by
// adding 9 for each intra block, 3 for each zero mv and 1 for each new
// motion vector. This single number is then converted into a context
// with a single lookup ( counter_to_context ).
static const int mode_2_counter[MB_MODE_COUNT] = {
9, // DC_PRED
9, // V_PRED
9, // H_PRED
9, // D45_PRED
9, // D135_PRED
9, // D117_PRED
9, // D153_PRED
9, // D207_PRED
9, // D63_PRED
9, // TM_PRED
0, // NEARESTMV
0, // NEARMV
3, // ZEROMV
1, // NEWMV
};
// There are 3^3 different combinations of 3 counts that can be either 0,1 or
// 2. However the actual count can never be greater than 2 so the highest
// counter we need is 18. 9 is an invalid counter that's never used.
static const int counter_to_context[19] = {
BOTH_PREDICTED, // 0
NEW_PLUS_NON_INTRA, // 1
BOTH_NEW, // 2
ZERO_PLUS_PREDICTED, // 3
NEW_PLUS_NON_INTRA, // 4
INVALID_CASE, // 5
BOTH_ZERO, // 6
INVALID_CASE, // 7
INVALID_CASE, // 8
INTRA_PLUS_NON_INTRA, // 9
INTRA_PLUS_NON_INTRA, // 10
INVALID_CASE, // 11
INTRA_PLUS_NON_INTRA, // 12
INVALID_CASE, // 13
INVALID_CASE, // 14
INVALID_CASE, // 15
INVALID_CASE, // 16
INVALID_CASE, // 17
BOTH_INTRA // 18
};
static const POSITION mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
// 4X4
{{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
// 4X8
{{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
// 8X4
{{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
// 8X8
{{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
// 8X16
{{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}},
// 16X8
{{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}},
// 16X16
{{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
// 16X32
{{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}},
// 32X16
{{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
// 32X32
{{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
// 32X64
{{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}},
// 64X32
{{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}},
// 64X64
{{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}}
};
static const int idx_n_column_to_subblock[4][2] = {
{1, 2},
{1, 3},
{3, 2},
{3, 3}
};
// clamp_mv_ref
#define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units
static INLINE void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) {
clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER,
xd->mb_to_right_edge + MV_BORDER,
xd->mb_to_top_edge - MV_BORDER,
xd->mb_to_bottom_edge + MV_BORDER);
}
// This function returns either the appropriate sub block or block's mv
// on whether the block_size < 8x8 and we have check_sub_blocks set.
static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, int which_mv,
int search_col, int block_idx) {
return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8
? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]]
.as_mv[which_mv]
: candidate->mbmi.mv[which_mv];
}
// Performs mv sign inversion if indicated by the reference frame combination.
static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
const MV_REFERENCE_FRAME this_ref_frame,
const int *ref_sign_bias) {
int_mv mv = mbmi->mv[ref];
if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) {
mv.as_mv.row *= -1;
mv.as_mv.col *= -1;
}
return mv;
}
// This macro is used to add a motion vector mv_ref list if it isn't
// already in the list. If it's the second motion vector it will also
// skip all additional processing and jump to done!
#define ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done) \
do { \
if (refmv_count) { \
if ((mv).as_int != (mv_ref_list)[0].as_int) { \
(mv_ref_list)[(refmv_count)] = (mv); \
goto Done; \
} \
} else { \
(mv_ref_list)[(refmv_count)++] = (mv); \
} \
} while (0)
// If either reference frame is different, not INTRA, and they
// are different from each other scale and add the mv to our list.
#define IF_DIFF_REF_FRAME_ADD_MV(mbmi, ref_frame, ref_sign_bias, refmv_count, \
mv_ref_list, Done) \
do { \
if (is_inter_block(mbmi)) { \
if ((mbmi)->ref_frame[0] != ref_frame) \
ADD_MV_REF_LIST(scale_mv((mbmi), 0, ref_frame, ref_sign_bias), \
refmv_count, mv_ref_list, Done); \
if (has_second_ref(mbmi) && \
(mbmi)->ref_frame[1] != ref_frame && \
(mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) \
ADD_MV_REF_LIST(scale_mv((mbmi), 1, ref_frame, ref_sign_bias), \
refmv_count, mv_ref_list, Done); \
} \
} while (0)
// Checks that the given mi_row, mi_col and search point
// are inside the borders of the tile.
static INLINE int is_inside(const TileInfo *const tile,
int mi_col, int mi_row, int mi_rows,
const POSITION *mi_pos) {
return !(mi_row + mi_pos->row < 0 ||
mi_col + mi_pos->col < tile->mi_col_start ||
mi_row + mi_pos->row >= mi_rows ||
mi_col + mi_pos->col >= tile->mi_col_end);
}
// TODO(jingning): this mv clamping function should be block size dependent.
static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
xd->mb_to_top_edge - LEFT_TOP_MARGIN,
xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
}
typedef void (*find_mv_refs_sync)(void *const data, int mi_row);
void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list, int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data,
uint8_t *mode_context);
// check a list of motion vectors by sad score using a number rows of pixels
// above and a number cols of pixels in the left to select the one with best
// score to use as ref motion vector
void vp10_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
int_mv *mvlist, int_mv *nearest_mv, int_mv *near_mv);
void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
int block, int ref, int mi_row, int mi_col,
int_mv *nearest_mv, int_mv *near_mv,
uint8_t *mode_context);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_MVREF_COMMON_H_

470
vp10/common/onyxc_int.h Normal file
View File

@@ -0,0 +1,470 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_ONYXC_INT_H_
#define VP10_COMMON_ONYXC_INT_H_
#include "./vpx_config.h"
#include "vpx/internal/vpx_codec_internal.h"
#include "vpx_util/vpx_thread.h"
#include "./vp10_rtcd.h"
#include "vp10/common/alloccommon.h"
#include "vp10/common/loopfilter.h"
#include "vp10/common/entropymv.h"
#include "vp10/common/entropy.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/frame_buffers.h"
#include "vp10/common/quant_common.h"
#include "vp10/common/tile_common.h"
#if CONFIG_VP9_POSTPROC
#include "vp10/common/postproc.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define REFS_PER_FRAME (ALTREF_FRAME - LAST_FRAME + 1)
#define REF_FRAMES_LOG2 3
#define REF_FRAMES (1 << REF_FRAMES_LOG2)
// 4 scratch frames for the new frames to support a maximum of 4 cores decoding
// in parallel, 3 for scaled references on the encoder.
// TODO(hkuang): Add ondemand frame buffers instead of hardcoding the number
// of framebuffers.
// TODO(jkoleszar): These 3 extra references could probably come from the
// normal reference pool.
#define FRAME_BUFFERS (REF_FRAMES + 7)
#define FRAME_CONTEXTS_LOG2 2
#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
#define NUM_PING_PONG_BUFFERS 2
typedef enum {
SINGLE_REFERENCE = 0,
COMPOUND_REFERENCE = 1,
REFERENCE_MODE_SELECT = 2,
REFERENCE_MODES = 3,
} REFERENCE_MODE;
typedef struct {
int_mv mv[2];
MV_REFERENCE_FRAME ref_frame[2];
} MV_REF;
typedef struct {
int ref_count;
MV_REF *mvs;
int mi_rows;
int mi_cols;
vpx_codec_frame_buffer_t raw_frame_buffer;
YV12_BUFFER_CONFIG buf;
// The Following variables will only be used in frame parallel decode.
// frame_worker_owner indicates which FrameWorker owns this buffer. NULL means
// that no FrameWorker owns, or is decoding, this buffer.
VPxWorker *frame_worker_owner;
// row and col indicate which position frame has been decoded to in real
// pixel unit. They are reset to -1 when decoding begins and set to INT_MAX
// when the frame is fully decoded.
int row;
int col;
} RefCntBuffer;
typedef struct BufferPool {
// 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];
// Frame buffers allocated internally by the codec.
InternalFrameBufferList int_frame_buffers;
} BufferPool;
typedef struct VP10Common {
struct vpx_internal_error_info error;
vpx_color_space_t color_space;
int width;
int height;
int display_width;
int display_height;
int last_width;
int last_height;
// TODO(jkoleszar): this implies chroma ss right now, but could vary per
// plane. Revisit as part of the future change to YV12_BUFFER_CONFIG to
// support additional planes.
int subsampling_x;
int subsampling_y;
#if CONFIG_VP9_HIGHBITDEPTH
int use_highbitdepth; // Marks if we need to use 16bit frame buffers.
#endif
YV12_BUFFER_CONFIG *frame_to_show;
RefCntBuffer *prev_frame;
// TODO(hkuang): Combine this with cur_buf in macroblockd.
RefCntBuffer *cur_frame;
int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
// Prepare ref_frame_map for the next frame.
// Only used in frame parallel decode.
int next_ref_frame_map[REF_FRAMES];
// TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
// roll new_fb_idx into it.
// Each frame can reference REFS_PER_FRAME buffers
RefBuffer frame_refs[REFS_PER_FRAME];
int new_fb_idx;
#if CONFIG_VP9_POSTPROC
YV12_BUFFER_CONFIG post_proc_buffer;
YV12_BUFFER_CONFIG post_proc_buffer_int;
#endif
FRAME_TYPE last_frame_type; /* last frame's frame type for motion search.*/
FRAME_TYPE frame_type;
int show_frame;
int last_show_frame;
int show_existing_frame;
// Flag signaling that the frame is encoded using only INTRA modes.
uint8_t intra_only;
uint8_t last_intra_only;
int allow_high_precision_mv;
// Flag signaling that the frame context should be reset to default values.
// 0 or 1 implies don't reset, 2 reset just the context specified in the
// frame header, 3 reset all contexts.
int reset_frame_context;
// MBs, mb_rows/cols is in 16-pixel units; mi_rows/cols is in
// MODE_INFO (8-pixel) units.
int MBs;
int mb_rows, mi_rows;
int mb_cols, mi_cols;
int mi_stride;
/* profile settings */
TX_MODE tx_mode;
int base_qindex;
int y_dc_delta_q;
int uv_dc_delta_q;
int uv_ac_delta_q;
int16_t y_dequant[MAX_SEGMENTS][2];
int16_t uv_dequant[MAX_SEGMENTS][2];
/* We allocate a MODE_INFO struct for each macroblock, together with
an extra row on top and column on the left to simplify prediction. */
int mi_alloc_size;
MODE_INFO *mip; /* Base of allocated array */
MODE_INFO *mi; /* Corresponds to upper left visible macroblock */
// TODO(agrange): Move prev_mi into encoder structure.
// prev_mip and prev_mi will only be allocated in VP9 encoder.
MODE_INFO *prev_mip; /* MODE_INFO array 'mip' from last decoded frame */
MODE_INFO *prev_mi; /* 'mi' from last frame (points into prev_mip) */
// Separate mi functions between encoder and decoder.
int (*alloc_mi)(struct VP10Common *cm, int mi_size);
void (*free_mi)(struct VP10Common *cm);
void (*setup_mi)(struct VP10Common *cm);
// Grid of pointers to 8x8 MODE_INFO structs. Any 8x8 not in the visible
// area will be NULL.
MODE_INFO **mi_grid_base;
MODE_INFO **mi_grid_visible;
MODE_INFO **prev_mi_grid_base;
MODE_INFO **prev_mi_grid_visible;
// Whether to use previous frame's motion vectors for prediction.
int use_prev_frame_mvs;
// Persistent mb segment id map used in prediction.
int seg_map_idx;
int prev_seg_map_idx;
uint8_t *seg_map_array[NUM_PING_PONG_BUFFERS];
uint8_t *last_frame_seg_map;
uint8_t *current_frame_seg_map;
int seg_map_alloc_size;
INTERP_FILTER interp_filter;
loop_filter_info_n lf_info;
int refresh_frame_context; /* Two state 0 = NO, 1 = YES */
int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */
struct loopfilter lf;
struct segmentation seg;
// TODO(hkuang): Remove this as it is the same as frame_parallel_decode
// in pbi.
int frame_parallel_decode; // frame-based threading.
// Context probabilities for reference frame prediction
MV_REFERENCE_FRAME comp_fixed_ref;
MV_REFERENCE_FRAME comp_var_ref[2];
REFERENCE_MODE reference_mode;
FRAME_CONTEXT *fc; /* this frame entropy */
FRAME_CONTEXT *frame_contexts; // FRAME_CONTEXTS
unsigned int frame_context_idx; /* Context to use/update */
FRAME_COUNTS counts;
unsigned int current_video_frame;
BITSTREAM_PROFILE profile;
// VPX_BITS_8 in profile 0 or 1, VPX_BITS_10 or VPX_BITS_12 in profile 2 or 3.
vpx_bit_depth_t bit_depth;
vpx_bit_depth_t dequant_bit_depth; // bit_depth of current dequantizer
#if CONFIG_VP9_POSTPROC
struct postproc_state postproc_state;
#endif
int error_resilient_mode;
int frame_parallel_decoding_mode;
int log2_tile_cols, log2_tile_rows;
int byte_alignment;
int skip_loop_filter;
// 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;
// External BufferPool passed from outside.
BufferPool *buffer_pool;
PARTITION_CONTEXT *above_seg_context;
ENTROPY_CONTEXT *above_context;
int above_context_alloc_cols;
} VP10_COMMON;
// TODO(hkuang): Don't need to lock the whole pool after implementing atomic
// frame reference count.
static void lock_buffer_pool(BufferPool *const pool) {
#if CONFIG_MULTITHREAD
pthread_mutex_lock(&pool->pool_mutex);
#else
(void)pool;
#endif
}
static void unlock_buffer_pool(BufferPool *const pool) {
#if CONFIG_MULTITHREAD
pthread_mutex_unlock(&pool->pool_mutex);
#else
(void)pool;
#endif
}
static INLINE YV12_BUFFER_CONFIG *get_ref_frame(VP10_COMMON *cm, int index) {
if (index < 0 || index >= REF_FRAMES)
return NULL;
if (cm->ref_frame_map[index] < 0)
return NULL;
assert(cm->ref_frame_map[index] < FRAME_BUFFERS);
return &cm->buffer_pool->frame_bufs[cm->ref_frame_map[index]].buf;
}
static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP10_COMMON *cm) {
return &cm->buffer_pool->frame_bufs[cm->new_fb_idx].buf;
}
static INLINE int get_free_fb(VP10_COMMON *cm) {
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
int i;
lock_buffer_pool(cm->buffer_pool);
for (i = 0; i < FRAME_BUFFERS; ++i)
if (frame_bufs[i].ref_count == 0)
break;
if (i != FRAME_BUFFERS) {
frame_bufs[i].ref_count = 1;
} else {
// Reset i to be INVALID_IDX to indicate no free buffer found.
i = INVALID_IDX;
}
unlock_buffer_pool(cm->buffer_pool);
return i;
}
static INLINE void ref_cnt_fb(RefCntBuffer *bufs, int *idx, int new_idx) {
const int ref_index = *idx;
if (ref_index >= 0 && bufs[ref_index].ref_count > 0)
bufs[ref_index].ref_count--;
*idx = new_idx;
bufs[new_idx].ref_count++;
}
static INLINE int mi_cols_aligned_to_sb(int n_mis) {
return ALIGN_POWER_OF_TWO(n_mis, MI_BLOCK_SIZE_LOG2);
}
static INLINE int frame_is_intra_only(const VP10_COMMON *const cm) {
return cm->frame_type == KEY_FRAME || cm->intra_only;
}
static INLINE void set_partition_probs(const VP10_COMMON *const cm,
MACROBLOCKD *const xd) {
xd->partition_probs =
frame_is_intra_only(cm) ?
&vp10_kf_partition_probs[0] :
(const vpx_prob (*)[PARTITION_TYPES - 1])cm->fc->partition_prob;
}
static INLINE void vp10_init_macroblockd(VP10_COMMON *cm, MACROBLOCKD *xd,
tran_low_t *dqcoeff) {
int i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
xd->plane[i].dqcoeff = dqcoeff;
xd->above_context[i] = cm->above_context +
i * sizeof(*cm->above_context) * 2 * mi_cols_aligned_to_sb(cm->mi_cols);
if (xd->plane[i].plane_type == PLANE_TYPE_Y) {
memcpy(xd->plane[i].seg_dequant, cm->y_dequant, sizeof(cm->y_dequant));
} else {
memcpy(xd->plane[i].seg_dequant, cm->uv_dequant, sizeof(cm->uv_dequant));
}
xd->fc = cm->fc;
xd->frame_parallel_decoding_mode = cm->frame_parallel_decoding_mode;
}
xd->above_seg_context = cm->above_seg_context;
xd->mi_stride = cm->mi_stride;
xd->error_info = &cm->error;
set_partition_probs(cm, xd);
}
static INLINE const vpx_prob* get_partition_probs(const MACROBLOCKD *xd,
int ctx) {
return xd->partition_probs[ctx];
}
static INLINE void set_skip_context(MACROBLOCKD *xd, int mi_row, int mi_col) {
const int above_idx = mi_col * 2;
const int left_idx = (mi_row * 2) & 15;
int i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
struct macroblockd_plane *const pd = &xd->plane[i];
pd->above_context = &xd->above_context[i][above_idx >> pd->subsampling_x];
pd->left_context = &xd->left_context[i][left_idx >> pd->subsampling_y];
}
}
static INLINE int calc_mi_size(int len) {
// len is in mi units.
return len + MI_BLOCK_SIZE;
}
static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
int mi_row, int bh,
int mi_col, int bw,
int mi_rows, int mi_cols) {
xd->mb_to_top_edge = -((mi_row * MI_SIZE) * 8);
xd->mb_to_bottom_edge = ((mi_rows - bh - mi_row) * MI_SIZE) * 8;
xd->mb_to_left_edge = -((mi_col * MI_SIZE) * 8);
xd->mb_to_right_edge = ((mi_cols - bw - mi_col) * MI_SIZE) * 8;
// Are edges available for intra prediction?
xd->up_available = (mi_row != 0);
xd->left_available = (mi_col > tile->mi_col_start);
if (xd->up_available) {
xd->above_mi = xd->mi[-xd->mi_stride];
// above_mi may be NULL in VP9 encoder's first pass.
xd->above_mbmi = xd->above_mi ? &xd->above_mi->mbmi : NULL;
} else {
xd->above_mi = NULL;
xd->above_mbmi = NULL;
}
if (xd->left_available) {
xd->left_mi = xd->mi[-1];
// left_mi may be NULL in VP9 encoder's first pass.
xd->left_mbmi = xd->left_mi ? &xd->left_mi->mbmi : NULL;
} else {
xd->left_mi = NULL;
xd->left_mbmi = NULL;
}
}
static INLINE void update_partition_context(MACROBLOCKD *xd,
int mi_row, int mi_col,
BLOCK_SIZE subsize,
BLOCK_SIZE bsize) {
PARTITION_CONTEXT *const above_ctx = xd->above_seg_context + mi_col;
PARTITION_CONTEXT *const left_ctx = xd->left_seg_context + (mi_row & MI_MASK);
// num_4x4_blocks_wide_lookup[bsize] / 2
const int bs = num_8x8_blocks_wide_lookup[bsize];
// update the partition context at the end notes. set partition bits
// of block sizes larger than the current one to be one, and partition
// bits of smaller block sizes to be zero.
memset(above_ctx, partition_context_lookup[subsize].above, bs);
memset(left_ctx, partition_context_lookup[subsize].left, bs);
}
static INLINE int partition_plane_context(const MACROBLOCKD *xd,
int mi_row, int mi_col,
BLOCK_SIZE bsize) {
const PARTITION_CONTEXT *above_ctx = xd->above_seg_context + mi_col;
const PARTITION_CONTEXT *left_ctx = xd->left_seg_context + (mi_row & MI_MASK);
const int bsl = mi_width_log2_lookup[bsize];
int above = (*above_ctx >> bsl) & 1 , left = (*left_ctx >> bsl) & 1;
assert(b_width_log2_lookup[bsize] == b_height_log2_lookup[bsize]);
assert(bsl >= 0);
return (left * 2 + above) + bsl * PARTITION_PLOFFSET;
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_ONYXC_INT_H_

746
vp10/common/postproc.c Normal file
View File

@@ -0,0 +1,746 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "./vpx_config.h"
#include "./vpx_scale_rtcd.h"
#include "./vp10_rtcd.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/system_state.h"
#include "vpx_scale/vpx_scale.h"
#include "vpx_scale/yv12config.h"
#include "vp10/common/onyxc_int.h"
#include "vp10/common/postproc.h"
#include "vp10/common/textblit.h"
#if CONFIG_VP9_POSTPROC
static const short kernel5[] = {
1, 1, 4, 1, 1
};
const short vp10_rv[] = {
8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
};
static const uint8_t q_diff_thresh = 20;
static const uint8_t last_q_thresh = 170;
void vp10_post_proc_down_and_across_c(const uint8_t *src_ptr,
uint8_t *dst_ptr,
int src_pixels_per_line,
int dst_pixels_per_line,
int rows,
int cols,
int flimit) {
uint8_t const *p_src;
uint8_t *p_dst;
int row, col, i, v, kernel;
int pitch = src_pixels_per_line;
uint8_t d[8];
(void)dst_pixels_per_line;
for (row = 0; row < rows; row++) {
/* post_proc_down for one row */
p_src = src_ptr;
p_dst = dst_ptr;
for (col = 0; col < cols; col++) {
kernel = 4;
v = p_src[col];
for (i = -2; i <= 2; i++) {
if (abs(v - p_src[col + i * pitch]) > flimit)
goto down_skip_convolve;
kernel += kernel5[2 + i] * p_src[col + i * pitch];
}
v = (kernel >> 3);
down_skip_convolve:
p_dst[col] = v;
}
/* now post_proc_across */
p_src = dst_ptr;
p_dst = dst_ptr;
for (i = 0; i < 8; i++)
d[i] = p_src[i];
for (col = 0; col < cols; col++) {
kernel = 4;
v = p_src[col];
d[col & 7] = v;
for (i = -2; i <= 2; i++) {
if (abs(v - p_src[col + i]) > flimit)
goto across_skip_convolve;
kernel += kernel5[2 + i] * p_src[col + i];
}
d[col & 7] = (kernel >> 3);
across_skip_convolve:
if (col >= 2)
p_dst[col - 2] = d[(col - 2) & 7];
}
/* handle the last two pixels */
p_dst[col - 2] = d[(col - 2) & 7];
p_dst[col - 1] = d[(col - 1) & 7];
/* next row */
src_ptr += pitch;
dst_ptr += pitch;
}
}
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_post_proc_down_and_across_c(const uint16_t *src_ptr,
uint16_t *dst_ptr,
int src_pixels_per_line,
int dst_pixels_per_line,
int rows,
int cols,
int flimit) {
uint16_t const *p_src;
uint16_t *p_dst;
int row, col, i, v, kernel;
int pitch = src_pixels_per_line;
uint16_t d[8];
for (row = 0; row < rows; row++) {
// post_proc_down for one row.
p_src = src_ptr;
p_dst = dst_ptr;
for (col = 0; col < cols; col++) {
kernel = 4;
v = p_src[col];
for (i = -2; i <= 2; i++) {
if (abs(v - p_src[col + i * pitch]) > flimit)
goto down_skip_convolve;
kernel += kernel5[2 + i] * p_src[col + i * pitch];
}
v = (kernel >> 3);
down_skip_convolve:
p_dst[col] = v;
}
/* now post_proc_across */
p_src = dst_ptr;
p_dst = dst_ptr;
for (i = 0; i < 8; i++)
d[i] = p_src[i];
for (col = 0; col < cols; col++) {
kernel = 4;
v = p_src[col];
d[col & 7] = v;
for (i = -2; i <= 2; i++) {
if (abs(v - p_src[col + i]) > flimit)
goto across_skip_convolve;
kernel += kernel5[2 + i] * p_src[col + i];
}
d[col & 7] = (kernel >> 3);
across_skip_convolve:
if (col >= 2)
p_dst[col - 2] = d[(col - 2) & 7];
}
/* handle the last two pixels */
p_dst[col - 2] = d[(col - 2) & 7];
p_dst[col - 1] = d[(col - 1) & 7];
/* next row */
src_ptr += pitch;
dst_ptr += dst_pixels_per_line;
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static int q2mbl(int x) {
if (x < 20) x = 20;
x = 50 + (x - 50) * 10 / 8;
return x * x / 3;
}
void vp10_mbpost_proc_across_ip_c(uint8_t *src, int pitch,
int rows, int cols, int flimit) {
int r, c, i;
uint8_t *s = src;
uint8_t d[16];
for (r = 0; r < rows; r++) {
int sumsq = 0;
int sum = 0;
for (i = -8; i <= 6; i++) {
sumsq += s[i] * s[i];
sum += s[i];
d[i + 8] = 0;
}
for (c = 0; c < cols + 8; c++) {
int x = s[c + 7] - s[c - 8];
int y = s[c + 7] + s[c - 8];
sum += x;
sumsq += x * y;
d[c & 15] = s[c];
if (sumsq * 15 - sum * sum < flimit) {
d[c & 15] = (8 + sum + s[c]) >> 4;
}
s[c - 8] = d[(c - 8) & 15];
}
s += pitch;
}
}
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch,
int rows, int cols, int flimit) {
int r, c, i;
uint16_t *s = src;
uint16_t d[16];
for (r = 0; r < rows; r++) {
int sumsq = 0;
int sum = 0;
for (i = -8; i <= 6; i++) {
sumsq += s[i] * s[i];
sum += s[i];
d[i + 8] = 0;
}
for (c = 0; c < cols + 8; c++) {
int x = s[c + 7] - s[c - 8];
int y = s[c + 7] + s[c - 8];
sum += x;
sumsq += x * y;
d[c & 15] = s[c];
if (sumsq * 15 - sum * sum < flimit) {
d[c & 15] = (8 + sum + s[c]) >> 4;
}
s[c - 8] = d[(c - 8) & 15];
}
s += pitch;
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
void vp10_mbpost_proc_down_c(uint8_t *dst, int pitch,
int rows, int cols, int flimit) {
int r, c, i;
const short *rv3 = &vp10_rv[63 & rand()]; // NOLINT
for (c = 0; c < cols; c++) {
uint8_t *s = &dst[c];
int sumsq = 0;
int sum = 0;
uint8_t d[16];
const short *rv2 = rv3 + ((c * 17) & 127);
for (i = -8; i <= 6; i++) {
sumsq += s[i * pitch] * s[i * pitch];
sum += s[i * pitch];
}
for (r = 0; r < rows + 8; r++) {
sumsq += s[7 * pitch] * s[ 7 * pitch] - s[-8 * pitch] * s[-8 * pitch];
sum += s[7 * pitch] - s[-8 * pitch];
d[r & 15] = s[0];
if (sumsq * 15 - sum * sum < flimit) {
d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4;
}
s[-8 * pitch] = d[(r - 8) & 15];
s += pitch;
}
}
}
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_mbpost_proc_down_c(uint16_t *dst, int pitch,
int rows, int cols, int flimit) {
int r, c, i;
const int16_t *rv3 = &vp10_rv[63 & rand()]; // NOLINT
for (c = 0; c < cols; c++) {
uint16_t *s = &dst[c];
int sumsq = 0;
int sum = 0;
uint16_t d[16];
const int16_t *rv2 = rv3 + ((c * 17) & 127);
for (i = -8; i <= 6; i++) {
sumsq += s[i * pitch] * s[i * pitch];
sum += s[i * pitch];
}
for (r = 0; r < rows + 8; r++) {
sumsq += s[7 * pitch] * s[ 7 * pitch] - s[-8 * pitch] * s[-8 * pitch];
sum += s[7 * pitch] - s[-8 * pitch];
d[r & 15] = s[0];
if (sumsq * 15 - sum * sum < flimit) {
d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4;
}
s[-8 * pitch] = d[(r - 8) & 15];
s += pitch;
}
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static void deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
YV12_BUFFER_CONFIG *post,
int q,
int low_var_thresh,
int flag) {
double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
int ppl = (int)(level + .5);
(void) low_var_thresh;
(void) flag;
#if CONFIG_VP9_HIGHBITDEPTH
if (source->flags & YV12_FLAG_HIGHBITDEPTH) {
vp10_highbd_post_proc_down_and_across(CONVERT_TO_SHORTPTR(source->y_buffer),
CONVERT_TO_SHORTPTR(post->y_buffer),
source->y_stride, post->y_stride,
source->y_height, source->y_width,
ppl);
vp10_highbd_mbpost_proc_across_ip(CONVERT_TO_SHORTPTR(post->y_buffer),
post->y_stride, post->y_height,
post->y_width, q2mbl(q));
vp10_highbd_mbpost_proc_down(CONVERT_TO_SHORTPTR(post->y_buffer),
post->y_stride, post->y_height,
post->y_width, q2mbl(q));
vp10_highbd_post_proc_down_and_across(CONVERT_TO_SHORTPTR(source->u_buffer),
CONVERT_TO_SHORTPTR(post->u_buffer),
source->uv_stride, post->uv_stride,
source->uv_height, source->uv_width,
ppl);
vp10_highbd_post_proc_down_and_across(CONVERT_TO_SHORTPTR(source->v_buffer),
CONVERT_TO_SHORTPTR(post->v_buffer),
source->uv_stride, post->uv_stride,
source->uv_height, source->uv_width,
ppl);
} else {
vp10_post_proc_down_and_across(source->y_buffer, post->y_buffer,
source->y_stride, post->y_stride,
source->y_height, source->y_width, ppl);
vp10_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
post->y_width, q2mbl(q));
vp10_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
post->y_width, q2mbl(q));
vp10_post_proc_down_and_across(source->u_buffer, post->u_buffer,
source->uv_stride, post->uv_stride,
source->uv_height, source->uv_width, ppl);
vp10_post_proc_down_and_across(source->v_buffer, post->v_buffer,
source->uv_stride, post->uv_stride,
source->uv_height, source->uv_width, ppl);
}
#else
vp10_post_proc_down_and_across(source->y_buffer, post->y_buffer,
source->y_stride, post->y_stride,
source->y_height, source->y_width, ppl);
vp10_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
post->y_width, q2mbl(q));
vp10_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
post->y_width, q2mbl(q));
vp10_post_proc_down_and_across(source->u_buffer, post->u_buffer,
source->uv_stride, post->uv_stride,
source->uv_height, source->uv_width, ppl);
vp10_post_proc_down_and_across(source->v_buffer, post->v_buffer,
source->uv_stride, post->uv_stride,
source->uv_height, source->uv_width, ppl);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
void vp10_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
int q) {
const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
+ 0.0065 + 0.5);
int i;
const uint8_t *const srcs[3] = {src->y_buffer, src->u_buffer, src->v_buffer};
const int src_strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
const int src_widths[3] = {src->y_width, src->uv_width, src->uv_width};
const int src_heights[3] = {src->y_height, src->uv_height, src->uv_height};
uint8_t *const dsts[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
for (i = 0; i < MAX_MB_PLANE; ++i) {
#if CONFIG_VP9_HIGHBITDEPTH
assert((src->flags & YV12_FLAG_HIGHBITDEPTH) ==
(dst->flags & YV12_FLAG_HIGHBITDEPTH));
if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
vp10_highbd_post_proc_down_and_across(CONVERT_TO_SHORTPTR(srcs[i]),
CONVERT_TO_SHORTPTR(dsts[i]),
src_strides[i], dst_strides[i],
src_heights[i], src_widths[i], ppl);
} else {
vp10_post_proc_down_and_across(srcs[i], dsts[i],
src_strides[i], dst_strides[i],
src_heights[i], src_widths[i], ppl);
}
#else
vp10_post_proc_down_and_across(srcs[i], dsts[i],
src_strides[i], dst_strides[i],
src_heights[i], src_widths[i], ppl);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
}
void vp10_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
int q) {
const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
+ 0.0065 + 0.5);
int i;
const uint8_t *const srcs[3] = {src->y_buffer, src->u_buffer, src->v_buffer};
const int src_strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
const int src_widths[3] = {src->y_width, src->uv_width, src->uv_width};
const int src_heights[3] = {src->y_height, src->uv_height, src->uv_height};
uint8_t *const dsts[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
for (i = 0; i < MAX_MB_PLANE; ++i) {
const int src_stride = src_strides[i];
const int src_width = src_widths[i] - 4;
const int src_height = src_heights[i] - 4;
const int dst_stride = dst_strides[i];
#if CONFIG_VP9_HIGHBITDEPTH
assert((src->flags & YV12_FLAG_HIGHBITDEPTH) ==
(dst->flags & YV12_FLAG_HIGHBITDEPTH));
if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
const uint16_t *const src_plane = CONVERT_TO_SHORTPTR(
srcs[i] + 2 * src_stride + 2);
uint16_t *const dst_plane = CONVERT_TO_SHORTPTR(
dsts[i] + 2 * dst_stride + 2);
vp10_highbd_post_proc_down_and_across(src_plane, dst_plane, src_stride,
dst_stride, src_height, src_width,
ppl);
} else {
const uint8_t *const src_plane = srcs[i] + 2 * src_stride + 2;
uint8_t *const dst_plane = dsts[i] + 2 * dst_stride + 2;
vp10_post_proc_down_and_across(src_plane, dst_plane, src_stride,
dst_stride, src_height, src_width, ppl);
}
#else
const uint8_t *const src_plane = srcs[i] + 2 * src_stride + 2;
uint8_t *const dst_plane = dsts[i] + 2 * dst_stride + 2;
vp10_post_proc_down_and_across(src_plane, dst_plane, src_stride, dst_stride,
src_height, src_width, ppl);
#endif
}
}
static double gaussian(double sigma, double mu, double x) {
return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
(exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
}
static void fillrd(struct postproc_state *state, int q, int a) {
char char_dist[300];
double sigma;
int ai = a, qi = q, i;
vpx_clear_system_state();
sigma = ai + .5 + .6 * (63 - qi) / 63.0;
/* set up a lookup table of 256 entries that matches
* a gaussian distribution with sigma determined by q.
*/
{
int next, j;
next = 0;
for (i = -32; i < 32; i++) {
int a_i = (int)(0.5 + 256 * gaussian(sigma, 0, i));
if (a_i) {
for (j = 0; j < a_i; j++) {
char_dist[next + j] = (char) i;
}
next = next + j;
}
}
for (; next < 256; next++)
char_dist[next] = 0;
}
for (i = 0; i < 3072; i++) {
state->noise[i] = char_dist[rand() & 0xff]; // NOLINT
}
for (i = 0; i < 16; i++) {
state->blackclamp[i] = -char_dist[0];
state->whiteclamp[i] = -char_dist[0];
state->bothclamp[i] = -2 * char_dist[0];
}
state->last_q = q;
state->last_noise = a;
}
void vp10_plane_add_noise_c(uint8_t *start, char *noise,
char blackclamp[16],
char whiteclamp[16],
char bothclamp[16],
unsigned int width, unsigned int height, int pitch) {
unsigned int i, j;
// TODO(jbb): why does simd code use both but c doesn't, normalize and
// fix..
(void) bothclamp;
for (i = 0; i < height; i++) {
uint8_t *pos = start + i * pitch;
char *ref = (char *)(noise + (rand() & 0xff)); // NOLINT
for (j = 0; j < width; j++) {
if (pos[j] < blackclamp[0])
pos[j] = blackclamp[0];
if (pos[j] > 255 + whiteclamp[0])
pos[j] = 255 + whiteclamp[0];
pos[j] += ref[j];
}
}
}
static void swap_mi_and_prev_mi(VP10_COMMON *cm) {
// Current mip will be the prev_mip for the next frame.
MODE_INFO *temp = cm->postproc_state.prev_mip;
cm->postproc_state.prev_mip = cm->mip;
cm->mip = temp;
// Update the upper left visible macroblock ptrs.
cm->mi = cm->mip + cm->mi_stride + 1;
cm->postproc_state.prev_mi = cm->postproc_state.prev_mip + cm->mi_stride + 1;
}
int vp10_post_proc_frame(struct VP10Common *cm,
YV12_BUFFER_CONFIG *dest, vp10_ppflags_t *ppflags) {
const int q = VPXMIN(105, cm->lf.filter_level * 2);
const int flags = ppflags->post_proc_flag;
YV12_BUFFER_CONFIG *const ppbuf = &cm->post_proc_buffer;
struct postproc_state *const ppstate = &cm->postproc_state;
if (!cm->frame_to_show)
return -1;
if (!flags) {
*dest = *cm->frame_to_show;
return 0;
}
vpx_clear_system_state();
// Alloc memory for prev_mip in the first frame.
if (cm->current_video_frame == 1) {
cm->postproc_state.last_base_qindex = cm->base_qindex;
cm->postproc_state.last_frame_valid = 1;
ppstate->prev_mip = vpx_calloc(cm->mi_alloc_size, sizeof(*cm->mip));
if (!ppstate->prev_mip) {
return 1;
}
ppstate->prev_mi = ppstate->prev_mip + cm->mi_stride + 1;
memset(ppstate->prev_mip, 0,
cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->mip));
}
// Allocate post_proc_buffer_int if needed.
if ((flags & VP9D_MFQE) && !cm->post_proc_buffer_int.buffer_alloc) {
if ((flags & VP9D_DEMACROBLOCK) || (flags & VP9D_DEBLOCK)) {
const int width = ALIGN_POWER_OF_TWO(cm->width, 4);
const int height = ALIGN_POWER_OF_TWO(cm->height, 4);
if (vpx_alloc_frame_buffer(&cm->post_proc_buffer_int, width, height,
cm->subsampling_x, cm->subsampling_y,
#if CONFIG_VP9_HIGHBITDEPTH
cm->use_highbitdepth,
#endif // CONFIG_VP9_HIGHBITDEPTH
VP9_ENC_BORDER_IN_PIXELS,
cm->byte_alignment) < 0) {
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate MFQE framebuffer");
}
// Ensure that postproc is set to all 0s so that post proc
// doesn't pull random data in from edge.
memset(cm->post_proc_buffer_int.buffer_alloc, 128,
cm->post_proc_buffer.frame_size);
}
}
if (vpx_realloc_frame_buffer(&cm->post_proc_buffer, cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
#if CONFIG_VP9_HIGHBITDEPTH
cm->use_highbitdepth,
#endif
VP9_DEC_BORDER_IN_PIXELS, cm->byte_alignment,
NULL, NULL, NULL) < 0)
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate post-processing buffer");
if ((flags & VP9D_MFQE) && cm->current_video_frame >= 2 &&
cm->postproc_state.last_frame_valid && cm->bit_depth == 8 &&
cm->postproc_state.last_base_qindex <= last_q_thresh &&
cm->base_qindex - cm->postproc_state.last_base_qindex >= q_diff_thresh) {
vp10_mfqe(cm);
// TODO(jackychen): Consider whether enable deblocking by default
// if mfqe is enabled. Need to take both the quality and the speed
// into consideration.
if ((flags & VP9D_DEMACROBLOCK) || (flags & VP9D_DEBLOCK)) {
vp8_yv12_copy_frame(ppbuf, &cm->post_proc_buffer_int);
}
if ((flags & VP9D_DEMACROBLOCK) && cm->post_proc_buffer_int.buffer_alloc) {
deblock_and_de_macro_block(&cm->post_proc_buffer_int, ppbuf,
q + (ppflags->deblocking_level - 5) * 10,
1, 0);
} else if (flags & VP9D_DEBLOCK) {
vp10_deblock(&cm->post_proc_buffer_int, ppbuf, q);
} else {
vp8_yv12_copy_frame(&cm->post_proc_buffer_int, ppbuf);
}
} else if (flags & VP9D_DEMACROBLOCK) {
deblock_and_de_macro_block(cm->frame_to_show, ppbuf,
q + (ppflags->deblocking_level - 5) * 10, 1, 0);
} else if (flags & VP9D_DEBLOCK) {
vp10_deblock(cm->frame_to_show, ppbuf, q);
} else {
vp8_yv12_copy_frame(cm->frame_to_show, ppbuf);
}
cm->postproc_state.last_base_qindex = cm->base_qindex;
cm->postproc_state.last_frame_valid = 1;
if (flags & VP9D_ADDNOISE) {
const int noise_level = ppflags->noise_level;
if (ppstate->last_q != q ||
ppstate->last_noise != noise_level) {
fillrd(ppstate, 63 - q, noise_level);
}
vp10_plane_add_noise(ppbuf->y_buffer, ppstate->noise, ppstate->blackclamp,
ppstate->whiteclamp, ppstate->bothclamp,
ppbuf->y_width, ppbuf->y_height, ppbuf->y_stride);
}
*dest = *ppbuf;
/* handle problem with extending borders */
dest->y_width = cm->width;
dest->y_height = cm->height;
dest->uv_width = dest->y_width >> cm->subsampling_x;
dest->uv_height = dest->y_height >> cm->subsampling_y;
swap_mi_and_prev_mi(cm);
return 0;
}
#endif // CONFIG_VP9_POSTPROC

53
vp10/common/postproc.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_POSTPROC_H_
#define VP10_COMMON_POSTPROC_H_
#include "vpx_ports/mem.h"
#include "vpx_scale/yv12config.h"
#include "vp10/common/blockd.h"
#include "vp10/common/mfqe.h"
#include "vp10/common/ppflags.h"
#ifdef __cplusplus
extern "C" {
#endif
struct postproc_state {
int last_q;
int last_noise;
char noise[3072];
int last_base_qindex;
int last_frame_valid;
MODE_INFO *prev_mip;
MODE_INFO *prev_mi;
DECLARE_ALIGNED(16, char, blackclamp[16]);
DECLARE_ALIGNED(16, char, whiteclamp[16]);
DECLARE_ALIGNED(16, char, bothclamp[16]);
};
struct VP10Common;
#define MFQE_PRECISION 4
int vp10_post_proc_frame(struct VP10Common *cm,
YV12_BUFFER_CONFIG *dest, vp10_ppflags_t *flags);
void vp10_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, int q);
void vp10_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, int q);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_POSTPROC_H_

43
vp10/common/ppflags.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_PPFLAGS_H_
#define VP10_COMMON_PPFLAGS_H_
#ifdef __cplusplus
extern "C" {
#endif
enum {
VP9D_NOFILTERING = 0,
VP9D_DEBLOCK = 1 << 0,
VP9D_DEMACROBLOCK = 1 << 1,
VP9D_ADDNOISE = 1 << 2,
VP9D_DEBUG_TXT_FRAME_INFO = 1 << 3,
VP9D_DEBUG_TXT_MBLK_MODES = 1 << 4,
VP9D_DEBUG_TXT_DC_DIFF = 1 << 5,
VP9D_DEBUG_TXT_RATE_INFO = 1 << 6,
VP9D_DEBUG_DRAW_MV = 1 << 7,
VP9D_DEBUG_CLR_BLK_MODES = 1 << 8,
VP9D_DEBUG_CLR_FRM_REF_BLKS = 1 << 9,
VP9D_MFQE = 1 << 10
};
typedef struct {
int post_proc_flag;
int deblocking_level;
int noise_level;
} vp10_ppflags_t;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_PPFLAGS_H_

339
vp10/common/pred_common.c Normal file
View File

@@ -0,0 +1,339 @@
/*
* 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 "vp10/common/common.h"
#include "vp10/common/pred_common.h"
#include "vp10/common/seg_common.h"
// Returns a context number for the given MB prediction signal
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int left_type = xd->left_available && is_inter_block(left_mbmi) ?
left_mbmi->interp_filter : SWITCHABLE_FILTERS;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const int above_type = xd->up_available && is_inter_block(above_mbmi) ?
above_mbmi->interp_filter : SWITCHABLE_FILTERS;
if (left_type == above_type)
return left_type;
else if (left_type == SWITCHABLE_FILTERS && above_type != SWITCHABLE_FILTERS)
return above_type;
else if (left_type != SWITCHABLE_FILTERS && above_type == SWITCHABLE_FILTERS)
return left_type;
else
return SWITCHABLE_FILTERS;
}
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
// 0 - inter/inter, inter/--, --/inter, --/--
// 1 - intra/inter, inter/intra
// 2 - intra/--, --/intra
// 3 - intra/intra
int vp10_get_intra_inter_context(const MACROBLOCKD *xd) {
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
if (has_above && has_left) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
return left_intra && above_intra ? 3
: left_intra || above_intra;
} else if (has_above || has_left) { // one edge available
return 2 * !is_inter_block(has_above ? above_mbmi : left_mbmi);
} else {
return 0;
}
}
int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
int ctx;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
if (has_above && has_left) { // both edges available
if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi))
// neither edge uses comp pred (0/1)
ctx = (above_mbmi->ref_frame[0] == cm->comp_fixed_ref) ^
(left_mbmi->ref_frame[0] == cm->comp_fixed_ref);
else if (!has_second_ref(above_mbmi))
// one of two edges uses comp pred (2/3)
ctx = 2 + (above_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
!is_inter_block(above_mbmi));
else if (!has_second_ref(left_mbmi))
// one of two edges uses comp pred (2/3)
ctx = 2 + (left_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
!is_inter_block(left_mbmi));
else // both edges use comp pred (4)
ctx = 4;
} else if (has_above || has_left) { // one edge available
const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
if (!has_second_ref(edge_mbmi))
// edge does not use comp pred (0/1)
ctx = edge_mbmi->ref_frame[0] == cm->comp_fixed_ref;
else
// edge uses comp pred (3)
ctx = 3;
} else { // no edges available (1)
ctx = 1;
}
assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS);
return ctx;
}
// Returns a context number for the given MB prediction signal
int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int var_ref_idx = !fix_ref_idx;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
if (above_intra && left_intra) { // intra/intra (2)
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi)) // single pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
else // comp pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx]
!= cm->comp_var_ref[1]);
} else { // inter/inter
const int l_sg = !has_second_ref(left_mbmi);
const int a_sg = !has_second_ref(above_mbmi);
const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[var_ref_idx];
const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[var_ref_idx];
if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
pred_context = 0;
} else if (l_sg && a_sg) { // single/single
if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) ||
(vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0]))
pred_context = 4;
else if (vrfa == vrfl)
pred_context = 3;
else
pred_context = 1;
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1])
pred_context = 1;
else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1])
pred_context = 2;
else
pred_context = 4;
} else if (vrfa == vrfl) { // comp/comp
pred_context = 4;
} else {
pred_context = 2;
}
}
} else if (above_in_image || left_in_image) { // one edge available
const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
if (!is_inter_block(edge_mbmi)) {
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi))
pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx]
!= cm->comp_var_ref[1]);
else
pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
}
} else { // no edges available (2)
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
return pred_context;
}
int vp10_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
if (has_above && has_left) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
if (above_intra && left_intra) { // intra/intra
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter or inter/intra
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi))
pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
else
pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
edge_mbmi->ref_frame[1] == LAST_FRAME);
} else { // inter/inter
const int above_has_second = has_second_ref(above_mbmi);
const int left_has_second = has_second_ref(left_mbmi);
const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
if (above_has_second && left_has_second) {
pred_context = 1 + (above0 == LAST_FRAME || above1 == LAST_FRAME ||
left0 == LAST_FRAME || left1 == LAST_FRAME);
} else if (above_has_second || left_has_second) {
const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
if (rfs == LAST_FRAME)
pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
else
pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
} else {
pred_context = 2 * (above0 == LAST_FRAME) + 2 * (left0 == LAST_FRAME);
}
}
} else if (has_above || has_left) { // one edge available
const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
if (!is_inter_block(edge_mbmi)) { // intra
pred_context = 2;
} else { // inter
if (!has_second_ref(edge_mbmi))
pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
else
pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
edge_mbmi->ref_frame[1] == LAST_FRAME);
}
} else { // no edges available
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
return pred_context;
}
int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
if (has_above && has_left) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
if (above_intra && left_intra) { // intra/intra
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter or inter/intra
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi)) {
if (edge_mbmi->ref_frame[0] == LAST_FRAME)
pred_context = 3;
else
pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
} else {
pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
}
} else { // inter/inter
const int above_has_second = has_second_ref(above_mbmi);
const int left_has_second = has_second_ref(left_mbmi);
const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
if (above_has_second && left_has_second) {
if (above0 == left0 && above1 == left1)
pred_context = 3 * (above0 == GOLDEN_FRAME ||
above1 == GOLDEN_FRAME ||
left0 == GOLDEN_FRAME ||
left1 == GOLDEN_FRAME);
else
pred_context = 2;
} else if (above_has_second || left_has_second) {
const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
if (rfs == GOLDEN_FRAME)
pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
else if (rfs == ALTREF_FRAME)
pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
else
pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
} else {
if (above0 == LAST_FRAME && left0 == LAST_FRAME) {
pred_context = 3;
} else if (above0 == LAST_FRAME || left0 == LAST_FRAME) {
const MV_REFERENCE_FRAME edge0 = (above0 == LAST_FRAME) ? left0
: above0;
pred_context = 4 * (edge0 == GOLDEN_FRAME);
} else {
pred_context = 2 * (above0 == GOLDEN_FRAME) +
2 * (left0 == GOLDEN_FRAME);
}
}
}
} else if (has_above || has_left) { // one edge available
const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
if (!is_inter_block(edge_mbmi) ||
(edge_mbmi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mbmi)))
pred_context = 2;
else if (!has_second_ref(edge_mbmi))
pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
else
pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
} else { // no edges available (2)
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
return pred_context;
}

172
vp10/common/pred_common.h Normal file
View File

@@ -0,0 +1,172 @@
/*
* 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.
*/
#ifndef VP10_COMMON_PRED_COMMON_H_
#define VP10_COMMON_PRED_COMMON_H_
#include "vp10/common/blockd.h"
#include "vp10/common/onyxc_int.h"
#include "vpx_dsp/vpx_dsp_common.h"
#ifdef __cplusplus
extern "C" {
#endif
static INLINE int get_segment_id(const VP10_COMMON *cm,
const uint8_t *segment_ids,
BLOCK_SIZE bsize, int mi_row, int mi_col) {
const int mi_offset = mi_row * cm->mi_cols + mi_col;
const int bw = num_8x8_blocks_wide_lookup[bsize];
const int bh = num_8x8_blocks_high_lookup[bsize];
const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
int x, y, segment_id = MAX_SEGMENTS;
for (y = 0; y < ymis; ++y)
for (x = 0; x < xmis; ++x)
segment_id =
VPXMIN(segment_id, segment_ids[mi_offset + y * cm->mi_cols + x]);
assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
return segment_id;
}
static INLINE int vp10_get_pred_context_seg_id(const MACROBLOCKD *xd) {
const MODE_INFO *const above_mi = xd->above_mi;
const MODE_INFO *const left_mi = xd->left_mi;
const int above_sip = (above_mi != NULL) ?
above_mi->mbmi.seg_id_predicted : 0;
const int left_sip = (left_mi != NULL) ? left_mi->mbmi.seg_id_predicted : 0;
return above_sip + left_sip;
}
static INLINE vpx_prob vp10_get_pred_prob_seg_id(const struct segmentation *seg,
const MACROBLOCKD *xd) {
return seg->pred_probs[vp10_get_pred_context_seg_id(xd)];
}
static INLINE int vp10_get_skip_context(const MACROBLOCKD *xd) {
const MODE_INFO *const above_mi = xd->above_mi;
const MODE_INFO *const left_mi = xd->left_mi;
const int above_skip = (above_mi != NULL) ? above_mi->mbmi.skip : 0;
const int left_skip = (left_mi != NULL) ? left_mi->mbmi.skip : 0;
return above_skip + left_skip;
}
static INLINE vpx_prob vp10_get_skip_prob(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->skip_probs[vp10_get_skip_context(xd)];
}
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd);
int vp10_get_intra_inter_context(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_intra_inter_prob(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->intra_inter_prob[vp10_get_intra_inter_context(xd)];
}
int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_reference_mode_prob(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->comp_inter_prob[vp10_get_reference_mode_context(cm, xd)];
}
int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_ref_p(cm, xd);
return cm->fc->comp_ref_prob[pred_context];
}
int vp10_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p1(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p1(xd)][0];
}
int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p2(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p2(xd)][1];
}
// Returns a context number for the given MB prediction signal
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real blocks.
// The prediction flags in these dummy entries are initialized to 0.
static INLINE int get_tx_size_context(const MACROBLOCKD *xd) {
const int max_tx_size = max_txsize_lookup[xd->mi[0]->mbmi.sb_type];
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
int above_ctx = (has_above && !above_mbmi->skip) ? (int)above_mbmi->tx_size
: max_tx_size;
int left_ctx = (has_left && !left_mbmi->skip) ? (int)left_mbmi->tx_size
: max_tx_size;
if (!has_left)
left_ctx = above_ctx;
if (!has_above)
above_ctx = left_ctx;
return (above_ctx + left_ctx) > max_tx_size;
}
static INLINE const vpx_prob *get_tx_probs(TX_SIZE max_tx_size, int ctx,
const struct tx_probs *tx_probs) {
switch (max_tx_size) {
case TX_8X8:
return tx_probs->p8x8[ctx];
case TX_16X16:
return tx_probs->p16x16[ctx];
case TX_32X32:
return tx_probs->p32x32[ctx];
default:
assert(0 && "Invalid max_tx_size.");
return NULL;
}
}
static INLINE const vpx_prob *get_tx_probs2(TX_SIZE max_tx_size,
const MACROBLOCKD *xd,
const struct tx_probs *tx_probs) {
return get_tx_probs(max_tx_size, get_tx_size_context(xd), tx_probs);
}
static INLINE unsigned int *get_tx_counts(TX_SIZE max_tx_size, int ctx,
struct tx_counts *tx_counts) {
switch (max_tx_size) {
case TX_8X8:
return tx_counts->p8x8[ctx];
case TX_16X16:
return tx_counts->p16x16[ctx];
case TX_32X32:
return tx_counts->p32x32[ctx];
default:
assert(0 && "Invalid max_tx_size.");
return NULL;
}
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_PRED_COMMON_H_

278
vp10/common/quant_common.c Normal file
View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp10/common/common.h"
#include "vp10/common/quant_common.h"
#include "vp10/common/seg_common.h"
static const int16_t dc_qlookup[QINDEX_RANGE] = {
4, 8, 8, 9, 10, 11, 12, 12,
13, 14, 15, 16, 17, 18, 19, 19,
20, 21, 22, 23, 24, 25, 26, 26,
27, 28, 29, 30, 31, 32, 32, 33,
34, 35, 36, 37, 38, 38, 39, 40,
41, 42, 43, 43, 44, 45, 46, 47,
48, 48, 49, 50, 51, 52, 53, 53,
54, 55, 56, 57, 57, 58, 59, 60,
61, 62, 62, 63, 64, 65, 66, 66,
67, 68, 69, 70, 70, 71, 72, 73,
74, 74, 75, 76, 77, 78, 78, 79,
80, 81, 81, 82, 83, 84, 85, 85,
87, 88, 90, 92, 93, 95, 96, 98,
99, 101, 102, 104, 105, 107, 108, 110,
111, 113, 114, 116, 117, 118, 120, 121,
123, 125, 127, 129, 131, 134, 136, 138,
140, 142, 144, 146, 148, 150, 152, 154,
156, 158, 161, 164, 166, 169, 172, 174,
177, 180, 182, 185, 187, 190, 192, 195,
199, 202, 205, 208, 211, 214, 217, 220,
223, 226, 230, 233, 237, 240, 243, 247,
250, 253, 257, 261, 265, 269, 272, 276,
280, 284, 288, 292, 296, 300, 304, 309,
313, 317, 322, 326, 330, 335, 340, 344,
349, 354, 359, 364, 369, 374, 379, 384,
389, 395, 400, 406, 411, 417, 423, 429,
435, 441, 447, 454, 461, 467, 475, 482,
489, 497, 505, 513, 522, 530, 539, 549,
559, 569, 579, 590, 602, 614, 626, 640,
654, 668, 684, 700, 717, 736, 755, 775,
796, 819, 843, 869, 896, 925, 955, 988,
1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336,
};
#if CONFIG_VP9_HIGHBITDEPTH
static const int16_t dc_qlookup_10[QINDEX_RANGE] = {
4, 9, 10, 13, 15, 17, 20, 22,
25, 28, 31, 34, 37, 40, 43, 47,
50, 53, 57, 60, 64, 68, 71, 75,
78, 82, 86, 90, 93, 97, 101, 105,
109, 113, 116, 120, 124, 128, 132, 136,
140, 143, 147, 151, 155, 159, 163, 166,
170, 174, 178, 182, 185, 189, 193, 197,
200, 204, 208, 212, 215, 219, 223, 226,
230, 233, 237, 241, 244, 248, 251, 255,
259, 262, 266, 269, 273, 276, 280, 283,
287, 290, 293, 297, 300, 304, 307, 310,
314, 317, 321, 324, 327, 331, 334, 337,
343, 350, 356, 362, 369, 375, 381, 387,
394, 400, 406, 412, 418, 424, 430, 436,
442, 448, 454, 460, 466, 472, 478, 484,
490, 499, 507, 516, 525, 533, 542, 550,
559, 567, 576, 584, 592, 601, 609, 617,
625, 634, 644, 655, 666, 676, 687, 698,
708, 718, 729, 739, 749, 759, 770, 782,
795, 807, 819, 831, 844, 856, 868, 880,
891, 906, 920, 933, 947, 961, 975, 988,
1001, 1015, 1030, 1045, 1061, 1076, 1090, 1105,
1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236,
1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379,
1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537,
1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717,
1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929,
1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197,
2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561,
2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953,
4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
};
static const int16_t dc_qlookup_12[QINDEX_RANGE] = {
4, 12, 18, 25, 33, 41, 50, 60,
70, 80, 91, 103, 115, 127, 140, 153,
166, 180, 194, 208, 222, 237, 251, 266,
281, 296, 312, 327, 343, 358, 374, 390,
405, 421, 437, 453, 469, 484, 500, 516,
532, 548, 564, 580, 596, 611, 627, 643,
659, 674, 690, 706, 721, 737, 752, 768,
783, 798, 814, 829, 844, 859, 874, 889,
904, 919, 934, 949, 964, 978, 993, 1008,
1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122,
1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234,
1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342,
1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544,
1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741,
1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933,
1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199,
2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467,
2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788,
2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127,
3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517,
3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951,
4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420,
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942,
5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517,
5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149,
6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867,
6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715,
7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788,
8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245,
10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409,
12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812,
16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387,
};
#endif
static const int16_t ac_qlookup[QINDEX_RANGE] = {
4, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76, 77, 78,
79, 80, 81, 82, 83, 84, 85, 86,
87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99, 100, 101, 102,
104, 106, 108, 110, 112, 114, 116, 118,
120, 122, 124, 126, 128, 130, 132, 134,
136, 138, 140, 142, 144, 146, 148, 150,
152, 155, 158, 161, 164, 167, 170, 173,
176, 179, 182, 185, 188, 191, 194, 197,
200, 203, 207, 211, 215, 219, 223, 227,
231, 235, 239, 243, 247, 251, 255, 260,
265, 270, 275, 280, 285, 290, 295, 300,
305, 311, 317, 323, 329, 335, 341, 347,
353, 359, 366, 373, 380, 387, 394, 401,
408, 416, 424, 432, 440, 448, 456, 465,
474, 483, 492, 501, 510, 520, 530, 540,
550, 560, 571, 582, 593, 604, 615, 627,
639, 651, 663, 676, 689, 702, 715, 729,
743, 757, 771, 786, 801, 816, 832, 848,
864, 881, 898, 915, 933, 951, 969, 988,
1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151,
1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567,
1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
};
#if CONFIG_VP9_HIGHBITDEPTH
static const int16_t ac_qlookup_10[QINDEX_RANGE] = {
4, 9, 11, 13, 16, 18, 21, 24,
27, 30, 33, 37, 40, 44, 48, 51,
55, 59, 63, 67, 71, 75, 79, 83,
88, 92, 96, 100, 105, 109, 114, 118,
122, 127, 131, 136, 140, 145, 149, 154,
158, 163, 168, 172, 177, 181, 186, 190,
195, 199, 204, 208, 213, 217, 222, 226,
231, 235, 240, 244, 249, 253, 258, 262,
267, 271, 275, 280, 284, 289, 293, 297,
302, 306, 311, 315, 319, 324, 328, 332,
337, 341, 345, 349, 354, 358, 362, 367,
371, 375, 379, 384, 388, 392, 396, 401,
409, 417, 425, 433, 441, 449, 458, 466,
474, 482, 490, 498, 506, 514, 523, 531,
539, 547, 555, 563, 571, 579, 588, 596,
604, 616, 628, 640, 652, 664, 676, 688,
700, 713, 725, 737, 749, 761, 773, 785,
797, 809, 825, 841, 857, 873, 889, 905,
922, 938, 954, 970, 986, 1002, 1018, 1038,
1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198,
1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603,
1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859,
1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159,
2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507,
2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915,
2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391,
3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952,
4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604,
4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372,
5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268,
6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
};
static const int16_t ac_qlookup_12[QINDEX_RANGE] = {
4, 13, 19, 27, 35, 44, 54, 64,
75, 87, 99, 112, 126, 139, 154, 168,
183, 199, 214, 230, 247, 263, 280, 297,
314, 331, 349, 366, 384, 402, 420, 438,
456, 475, 493, 511, 530, 548, 567, 586,
604, 623, 642, 660, 679, 698, 716, 735,
753, 772, 791, 809, 828, 846, 865, 884,
902, 920, 939, 957, 976, 994, 1012, 1030,
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175,
1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317,
1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457,
1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595,
1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856,
1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118,
2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378,
2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750,
2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137,
3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619,
3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149,
4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791,
4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544,
5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410,
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435,
7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635,
8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028,
10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661,
11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565,
13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806,
16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414,
18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486,
21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070,
25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247,
};
#endif
int16_t vp10_dc_quant(int qindex, int delta, vpx_bit_depth_t bit_depth) {
#if CONFIG_VP9_HIGHBITDEPTH
switch (bit_depth) {
case VPX_BITS_8:
return dc_qlookup[clamp(qindex + delta, 0, MAXQ)];
case VPX_BITS_10:
return dc_qlookup_10[clamp(qindex + delta, 0, MAXQ)];
case VPX_BITS_12:
return dc_qlookup_12[clamp(qindex + delta, 0, MAXQ)];
default:
assert(0 && "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
return -1;
}
#else
(void) bit_depth;
return dc_qlookup[clamp(qindex + delta, 0, MAXQ)];
#endif
}
int16_t vp10_ac_quant(int qindex, int delta, vpx_bit_depth_t bit_depth) {
#if CONFIG_VP9_HIGHBITDEPTH
switch (bit_depth) {
case VPX_BITS_8:
return ac_qlookup[clamp(qindex + delta, 0, MAXQ)];
case VPX_BITS_10:
return ac_qlookup_10[clamp(qindex + delta, 0, MAXQ)];
case VPX_BITS_12:
return ac_qlookup_12[clamp(qindex + delta, 0, MAXQ)];
default:
assert(0 && "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
return -1;
}
#else
(void) bit_depth;
return ac_qlookup[clamp(qindex + delta, 0, MAXQ)];
#endif
}
int vp10_get_qindex(const struct segmentation *seg, int segment_id,
int base_qindex) {
if (segfeature_active(seg, segment_id, SEG_LVL_ALT_Q)) {
const int data = get_segdata(seg, segment_id, SEG_LVL_ALT_Q);
const int seg_qindex = seg->abs_delta == SEGMENT_ABSDATA ?
data : base_qindex + data;
return clamp(seg_qindex, 0, MAXQ);
} else {
return base_qindex;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_QUANT_COMMON_H_
#define VP10_COMMON_QUANT_COMMON_H_
#include "vpx/vpx_codec.h"
#include "vp10/common/seg_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MINQ 0
#define MAXQ 255
#define QINDEX_RANGE (MAXQ - MINQ + 1)
#define QINDEX_BITS 8
int16_t vp10_dc_quant(int qindex, int delta, vpx_bit_depth_t bit_depth);
int16_t vp10_ac_quant(int qindex, int delta, vpx_bit_depth_t bit_depth);
int vp10_get_qindex(const struct segmentation *seg, int segment_id,
int base_qindex);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_QUANT_COMMON_H_

213
vp10/common/reconinter.c Normal file
View File

@@ -0,0 +1,213 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "./vpx_scale_rtcd.h"
#include "./vpx_config.h"
#include "vpx/vpx_integer.h"
#include "vp10/common/blockd.h"
#include "vp10/common/reconinter.h"
#include "vp10/common/reconintra.h"
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_build_inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
const MV *src_mv,
const struct scale_factors *sf,
int w, int h, int ref,
const InterpKernel *kernel,
enum mv_precision precision,
int x, int y, int bd) {
const int is_q4 = precision == MV_PRECISION_Q4;
const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
is_q4 ? src_mv->col : src_mv->col * 2 };
MV32 mv = vp10_scale_mv(&mv_q4, x, y, sf);
const int subpel_x = mv.col & SUBPEL_MASK;
const int subpel_y = mv.row & SUBPEL_MASK;
src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);
high_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
sf, w, h, ref, kernel, sf->x_step_q4, sf->y_step_q4, bd);
}
#endif // CONFIG_VP9_HIGHBITDEPTH
void vp10_build_inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
const MV *src_mv,
const struct scale_factors *sf,
int w, int h, int ref,
const InterpKernel *kernel,
enum mv_precision precision,
int x, int y) {
const int is_q4 = precision == MV_PRECISION_Q4;
const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
is_q4 ? src_mv->col : src_mv->col * 2 };
MV32 mv = vp10_scale_mv(&mv_q4, x, y, sf);
const int subpel_x = mv.col & SUBPEL_MASK;
const int subpel_y = mv.row & SUBPEL_MASK;
src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);
inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
sf, w, h, ref, kernel, sf->x_step_q4, sf->y_step_q4);
}
void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
int bw, int bh,
int x, int y, int w, int h,
int mi_x, int mi_y) {
struct macroblockd_plane *const pd = &xd->plane[plane];
const MODE_INFO *mi = xd->mi[0];
const int is_compound = has_second_ref(&mi->mbmi);
const InterpKernel *kernel = vp10_filter_kernels[mi->mbmi.interp_filter];
int ref;
for (ref = 0; ref < 1 + is_compound; ++ref) {
const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
struct buf_2d *const pre_buf = &pd->pre[ref];
struct buf_2d *const dst_buf = &pd->dst;
uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
const MV mv = mi->mbmi.sb_type < BLOCK_8X8
? average_split_mvs(pd, mi, ref, block)
: mi->mbmi.mv[ref].as_mv;
// TODO(jkoleszar): This clamping is done in the incorrect place for the
// scaling case. It needs to be done on the scaled MV, not the pre-scaling
// MV. Note however that it performs the subsampling aware scaling so
// that the result is always q4.
// mv_precision precision is MV_PRECISION_Q4.
const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
pd->subsampling_x,
pd->subsampling_y);
uint8_t *pre;
MV32 scaled_mv;
int xs, ys, subpel_x, subpel_y;
const int is_scaled = vp10_is_scaled(sf);
if (is_scaled) {
pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, sf);
scaled_mv = vp10_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
xs = sf->x_step_q4;
ys = sf->y_step_q4;
} else {
pre = pre_buf->buf + (y * pre_buf->stride + x);
scaled_mv.row = mv_q4.row;
scaled_mv.col = mv_q4.col;
xs = ys = 16;
}
subpel_x = scaled_mv.col & SUBPEL_MASK;
subpel_y = scaled_mv.row & SUBPEL_MASK;
pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride
+ (scaled_mv.col >> SUBPEL_BITS);
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
high_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys,
xd->bd);
} else {
inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
}
#else
inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
}
static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
int mi_row, int mi_col,
int plane_from, int plane_to) {
int plane;
const int mi_x = mi_col * MI_SIZE;
const int mi_y = mi_row * MI_SIZE;
for (plane = plane_from; plane <= plane_to; ++plane) {
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize,
&xd->plane[plane]);
const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
const int bw = 4 * num_4x4_w;
const int bh = 4 * num_4x4_h;
if (xd->mi[0]->mbmi.sb_type < BLOCK_8X8) {
int i = 0, x, y;
assert(bsize == BLOCK_8X8);
for (y = 0; y < num_4x4_h; ++y)
for (x = 0; x < num_4x4_w; ++x)
build_inter_predictors(xd, plane, i++, bw, bh,
4 * x, 4 * y, 4, 4, mi_x, mi_y);
} else {
build_inter_predictors(xd, plane, 0, bw, bh,
0, 0, bw, bh, mi_x, mi_y);
}
}
}
void vp10_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
}
void vp10_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize, int plane) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane);
}
void vp10_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
MAX_MB_PLANE - 1);
}
void vp10_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
MAX_MB_PLANE - 1);
}
void vp10_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
const YV12_BUFFER_CONFIG *src,
int mi_row, int mi_col) {
uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer,
src->v_buffer};
const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride,
src->uv_stride};
int i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
struct macroblockd_plane *const pd = &planes[i];
setup_pred_plane(&pd->dst, buffers[i], strides[i], mi_row, mi_col, NULL,
pd->subsampling_x, pd->subsampling_y);
}
}
void vp10_setup_pre_planes(MACROBLOCKD *xd, int idx,
const YV12_BUFFER_CONFIG *src,
int mi_row, int mi_col,
const struct scale_factors *sf) {
if (src != NULL) {
int i;
uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer,
src->v_buffer};
const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride,
src->uv_stride};
for (i = 0; i < MAX_MB_PLANE; ++i) {
struct macroblockd_plane *const pd = &xd->plane[i];
setup_pred_plane(&pd->pre[idx], buffers[i], strides[i], mi_row, mi_col,
sf, pd->subsampling_x, pd->subsampling_y);
}
}
}

196
vp10/common/reconinter.h Normal file
View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_RECONINTER_H_
#define VP10_COMMON_RECONINTER_H_
#include "vp10/common/filter.h"
#include "vp10/common/onyxc_int.h"
#include "vpx/vpx_integer.h"
#include "vpx_dsp/vpx_filter.h"
#ifdef __cplusplus
extern "C" {
#endif
static INLINE void inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
const int subpel_x,
const int subpel_y,
const struct scale_factors *sf,
int w, int h, int ref,
const InterpKernel *kernel,
int xs, int ys) {
sf->predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
kernel[subpel_x], xs, kernel[subpel_y], ys, w, h);
}
#if CONFIG_VP9_HIGHBITDEPTH
static INLINE void high_inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
const int subpel_x,
const int subpel_y,
const struct scale_factors *sf,
int w, int h, int ref,
const InterpKernel *kernel,
int xs, int ys, int bd) {
sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref](
src, src_stride, dst, dst_stride,
kernel[subpel_x], xs, kernel[subpel_y], ys, w, h, bd);
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static INLINE int round_mv_comp_q4(int value) {
return (value < 0 ? value - 2 : value + 2) / 4;
}
static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) {
MV res = { round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.row +
mi->bmi[1].as_mv[idx].as_mv.row +
mi->bmi[2].as_mv[idx].as_mv.row +
mi->bmi[3].as_mv[idx].as_mv.row),
round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.col +
mi->bmi[1].as_mv[idx].as_mv.col +
mi->bmi[2].as_mv[idx].as_mv.col +
mi->bmi[3].as_mv[idx].as_mv.col) };
return res;
}
static INLINE int round_mv_comp_q2(int value) {
return (value < 0 ? value - 1 : value + 1) / 2;
}
static MV mi_mv_pred_q2(const MODE_INFO *mi, int idx, int block0, int block1) {
MV res = { round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.row +
mi->bmi[block1].as_mv[idx].as_mv.row),
round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.col +
mi->bmi[block1].as_mv[idx].as_mv.col) };
return res;
}
// TODO(jkoleszar): yet another mv clamping function :-(
static INLINE MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd,
const MV *src_mv,
int bw, int bh, int ss_x, int ss_y) {
// If the MV points so far into the UMV border that no visible pixels
// are used for reconstruction, the subpel part of the MV can be
// discarded and the MV limited to 16 pixels with equivalent results.
const int spel_left = (VP9_INTERP_EXTEND + bw) << SUBPEL_BITS;
const int spel_right = spel_left - SUBPEL_SHIFTS;
const int spel_top = (VP9_INTERP_EXTEND + bh) << SUBPEL_BITS;
const int spel_bottom = spel_top - SUBPEL_SHIFTS;
MV clamped_mv = {
src_mv->row * (1 << (1 - ss_y)),
src_mv->col * (1 << (1 - ss_x))
};
assert(ss_x <= 1);
assert(ss_y <= 1);
clamp_mv(&clamped_mv,
xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left,
xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right,
xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top,
xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom);
return clamped_mv;
}
static INLINE MV average_split_mvs(const struct macroblockd_plane *pd,
const MODE_INFO *mi, int ref, int block) {
const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0);
MV res = {0, 0};
switch (ss_idx) {
case 0:
res = mi->bmi[block].as_mv[ref].as_mv;
break;
case 1:
res = mi_mv_pred_q2(mi, ref, block, block + 2);
break;
case 2:
res = mi_mv_pred_q2(mi, ref, block, block + 1);
break;
case 3:
res = mi_mv_pred_q4(mi, ref);
break;
default:
assert(ss_idx <= 3 && ss_idx >= 0);
}
return res;
}
void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
int bw, int bh,
int x, int y, int w, int h,
int mi_x, int mi_y);
void vp10_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize);
void vp10_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize, int plane);
void vp10_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize);
void vp10_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize);
void vp10_build_inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
const MV *mv_q3,
const struct scale_factors *sf,
int w, int h, int do_avg,
const InterpKernel *kernel,
enum mv_precision precision,
int x, int y);
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_build_inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
const MV *mv_q3,
const struct scale_factors *sf,
int w, int h, int do_avg,
const InterpKernel *kernel,
enum mv_precision precision,
int x, int y, int bd);
#endif
static INLINE int scaled_buffer_offset(int x_offset, int y_offset, int stride,
const struct scale_factors *sf) {
const int x = sf ? sf->scale_value_x(x_offset, sf) : x_offset;
const int y = sf ? sf->scale_value_y(y_offset, sf) : y_offset;
return y * stride + x;
}
static INLINE void setup_pred_plane(struct buf_2d *dst,
uint8_t *src, int stride,
int mi_row, int mi_col,
const struct scale_factors *scale,
int subsampling_x, int subsampling_y) {
const int x = (MI_SIZE * mi_col) >> subsampling_x;
const int y = (MI_SIZE * mi_row) >> subsampling_y;
dst->buf = src + scaled_buffer_offset(x, y, stride, scale);
dst->stride = stride;
}
void vp10_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
const YV12_BUFFER_CONFIG *src,
int mi_row, int mi_col);
void vp10_setup_pre_planes(MACROBLOCKD *xd, int idx,
const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
const struct scale_factors *sf);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_RECONINTER_H_

402
vp10/common/reconintra.c Normal file
View File

@@ -0,0 +1,402 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_config.h"
#include "./vpx_dsp_rtcd.h"
#if CONFIG_VP9_HIGHBITDEPTH
#include "vpx_dsp/vpx_dsp_common.h"
#endif // CONFIG_VP9_HIGHBITDEPTH
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/vpx_once.h"
#include "vp10/common/reconintra.h"
#include "vp10/common/onyxc_int.h"
enum {
NEED_LEFT = 1 << 1,
NEED_ABOVE = 1 << 2,
NEED_ABOVERIGHT = 1 << 3,
};
static const uint8_t extend_modes[INTRA_MODES] = {
NEED_ABOVE | NEED_LEFT, // DC
NEED_ABOVE, // V
NEED_LEFT, // H
NEED_ABOVERIGHT, // D45
NEED_LEFT | NEED_ABOVE, // D135
NEED_LEFT | NEED_ABOVE, // D117
NEED_LEFT | NEED_ABOVE, // D153
NEED_LEFT, // D207
NEED_ABOVERIGHT, // D63
NEED_LEFT | NEED_ABOVE, // TM
};
typedef void (*intra_pred_fn)(uint8_t *dst, ptrdiff_t stride,
const uint8_t *above, const uint8_t *left);
static intra_pred_fn pred[INTRA_MODES][TX_SIZES];
static intra_pred_fn dc_pred[2][2][TX_SIZES];
#if CONFIG_VP9_HIGHBITDEPTH
typedef void (*intra_high_pred_fn)(uint16_t *dst, ptrdiff_t stride,
const uint16_t *above, const uint16_t *left,
int bd);
static intra_high_pred_fn pred_high[INTRA_MODES][4];
static intra_high_pred_fn dc_pred_high[2][2][4];
#endif // CONFIG_VP9_HIGHBITDEPTH
static void vp10_init_intra_predictors_internal(void) {
#define INIT_ALL_SIZES(p, type) \
p[TX_4X4] = vpx_##type##_predictor_4x4; \
p[TX_8X8] = vpx_##type##_predictor_8x8; \
p[TX_16X16] = vpx_##type##_predictor_16x16; \
p[TX_32X32] = vpx_##type##_predictor_32x32
INIT_ALL_SIZES(pred[V_PRED], v);
INIT_ALL_SIZES(pred[H_PRED], h);
INIT_ALL_SIZES(pred[D207_PRED], d207);
INIT_ALL_SIZES(pred[D45_PRED], d45);
INIT_ALL_SIZES(pred[D63_PRED], d63);
INIT_ALL_SIZES(pred[D117_PRED], d117);
INIT_ALL_SIZES(pred[D135_PRED], d135);
INIT_ALL_SIZES(pred[D153_PRED], d153);
INIT_ALL_SIZES(pred[TM_PRED], tm);
INIT_ALL_SIZES(dc_pred[0][0], dc_128);
INIT_ALL_SIZES(dc_pred[0][1], dc_top);
INIT_ALL_SIZES(dc_pred[1][0], dc_left);
INIT_ALL_SIZES(dc_pred[1][1], dc);
#if CONFIG_VP9_HIGHBITDEPTH
INIT_ALL_SIZES(pred_high[V_PRED], highbd_v);
INIT_ALL_SIZES(pred_high[H_PRED], highbd_h);
INIT_ALL_SIZES(pred_high[D207_PRED], highbd_d207);
INIT_ALL_SIZES(pred_high[D45_PRED], highbd_d45);
INIT_ALL_SIZES(pred_high[D63_PRED], highbd_d63);
INIT_ALL_SIZES(pred_high[D117_PRED], highbd_d117);
INIT_ALL_SIZES(pred_high[D135_PRED], highbd_d135);
INIT_ALL_SIZES(pred_high[D153_PRED], highbd_d153);
INIT_ALL_SIZES(pred_high[TM_PRED], highbd_tm);
INIT_ALL_SIZES(dc_pred_high[0][0], highbd_dc_128);
INIT_ALL_SIZES(dc_pred_high[0][1], highbd_dc_top);
INIT_ALL_SIZES(dc_pred_high[1][0], highbd_dc_left);
INIT_ALL_SIZES(dc_pred_high[1][1], highbd_dc);
#endif // CONFIG_VP9_HIGHBITDEPTH
#undef intra_pred_allsizes
}
#if CONFIG_VP9_HIGHBITDEPTH
static void build_intra_predictors_high(const MACROBLOCKD *xd,
const uint8_t *ref8,
int ref_stride,
uint8_t *dst8,
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 bd) {
int i;
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
DECLARE_ALIGNED(16, uint16_t, left_col[32]);
DECLARE_ALIGNED(16, uint16_t, above_data[64 + 16]);
uint16_t *above_row = above_data + 16;
const uint16_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];
// int base=128;
int base = 128 << (bd - 8);
// 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
// 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;
// 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];
}
} else {
// TODO(Peter): this value should probably change for high bitdepth
vpx_memset16(left_col, base + 1, bs);
}
// TODO(hkuang) do not extend 2*bs pixels for all modes.
// above
if (up_available) {
const uint16_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) {
memcpy(above_row, above_ref, 2 * bs * sizeof(above_row[0]));
} else {
memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
vpx_memset16(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) {
memcpy(above_row, above_ref, r * sizeof(above_row[0]));
vpx_memset16(above_row + r, above_row[r - 1],
x0 + 2 * bs - frame_width);
} else {
memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
vpx_memset16(above_row + bs, above_row[bs - 1], bs);
}
} else if (x0 <= frame_width) {
const int r = frame_width - x0;
memcpy(above_row, above_ref, r * sizeof(above_row[0]));
vpx_memset16(above_row + r, above_row[r - 1],
x0 + 2 * bs - frame_width);
}
// TODO(Peter) this value should probably change for high bitdepth
above_row[-1] = left_available ? above_ref[-1] : (base+1);
} else {
/* faster path if the block does not need extension */
if (bs == 4 && right_available && left_available) {
const_above_row = above_ref;
} else {
memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
if (bs == 4 && right_available)
memcpy(above_row + bs, above_ref + bs, bs * sizeof(above_row[0]));
else
vpx_memset16(above_row + bs, above_row[bs - 1], bs);
// TODO(Peter): this value should probably change for high bitdepth
above_row[-1] = left_available ? above_ref[-1] : (base+1);
}
}
} else {
vpx_memset16(above_row, base - 1, bs * 2);
// TODO(Peter): this value should probably change for high bitdepth
above_row[-1] = base - 1;
}
// predict
if (mode == DC_PRED) {
dc_pred_high[left_available][up_available][tx_size](dst, dst_stride,
const_above_row,
left_col, xd->bd);
} else {
pred_high[mode][tx_size](dst, dst_stride, const_above_row, left_col,
xd->bd);
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static void build_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(16, uint8_t, left_col[32]);
DECLARE_ALIGNED(16, uint8_t, above_data[64 + 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];
// 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
// ..
// 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;
// NEED_LEFT
if (extend_modes[mode] & NEED_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];
}
} else {
memset(left_col, 129, bs);
}
}
// NEED_ABOVE
if (extend_modes[mode] & NEED_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 + bs <= frame_width) {
memcpy(above_row, above_ref, bs);
} else if (x0 <= frame_width) {
const int r = frame_width - x0;
memcpy(above_row, above_ref, r);
memset(above_row + r, above_row[r - 1], x0 + 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 {
memcpy(above_row, above_ref, bs);
}
}
above_row[-1] = left_available ? above_ref[-1] : 129;
} else {
memset(above_row, 127, bs);
above_row[-1] = 127;
}
}
// NEED_ABOVERIGHT
if (extend_modes[mode] & NEED_ABOVERIGHT) {
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) {
memcpy(above_row, above_ref, 2 * bs);
} else {
memcpy(above_row, above_ref, bs);
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) {
memcpy(above_row, above_ref, r);
memset(above_row + r, above_row[r - 1], x0 + 2 * bs - frame_width);
} else {
memcpy(above_row, above_ref, bs);
memset(above_row + bs, above_row[bs - 1], bs);
}
} else if (x0 <= frame_width) {
const int r = frame_width - x0;
memcpy(above_row, above_ref, r);
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 {
memcpy(above_row, above_ref, bs);
if (bs == 4 && right_available)
memcpy(above_row + bs, above_ref + bs, bs);
else
memset(above_row + bs, above_row[bs - 1], bs);
}
}
above_row[-1] = left_available ? above_ref[-1] : 129;
} else {
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);
}
}
void vp10_predict_intra_block(const MACROBLOCKD *xd, int bwl_in,
TX_SIZE tx_size, PREDICTION_MODE mode,
const uint8_t *ref, int ref_stride,
uint8_t *dst, int dst_stride,
int aoff, int loff, int plane) {
const int bw = (1 << bwl_in);
const int txw = (1 << tx_size);
const int have_top = loff || xd->up_available;
const int have_left = aoff || xd->left_available;
const int have_right = (aoff + txw) < bw;
const int x = aoff * 4;
const int y = loff * 4;
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
build_intra_predictors_high(xd, ref, ref_stride, dst, dst_stride, mode,
tx_size, have_top, have_left, have_right,
x, y, plane, xd->bd);
return;
}
#endif
build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
have_top, have_left, have_right, x, y, plane);
}
void vp10_init_intra_predictors(void) {
once(vp10_init_intra_predictors_internal);
}

32
vp10/common/reconintra.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_RECONINTRA_H_
#define VP10_COMMON_RECONINTRA_H_
#include "vpx/vpx_integer.h"
#include "vp10/common/blockd.h"
#ifdef __cplusplus
extern "C" {
#endif
void vp10_init_intra_predictors(void);
void vp10_predict_intra_block(const MACROBLOCKD *xd, int bwl_in,
TX_SIZE tx_size, PREDICTION_MODE mode,
const uint8_t *ref, int ref_stride,
uint8_t *dst, int dst_stride,
int aoff, int loff, int plane);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_RECONINTRA_H_

166
vp10/common/scale.c Normal file
View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2013 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 "./vpx_dsp_rtcd.h"
#include "vp10/common/filter.h"
#include "vp10/common/scale.h"
#include "vpx_dsp/vpx_filter.h"
static INLINE int scaled_x(int val, const struct scale_factors *sf) {
return (int)((int64_t)val * sf->x_scale_fp >> REF_SCALE_SHIFT);
}
static INLINE int scaled_y(int val, const struct scale_factors *sf) {
return (int)((int64_t)val * sf->y_scale_fp >> REF_SCALE_SHIFT);
}
static int unscaled_value(int val, const struct scale_factors *sf) {
(void) sf;
return val;
}
static int get_fixed_point_scale_factor(int other_size, int this_size) {
// Calculate scaling factor once for each reference frame
// and use fixed point scaling factors in decoding and encoding routines.
// Hardware implementations can calculate scale factor in device driver
// and use multiplication and shifting on hardware instead of division.
return (other_size << REF_SCALE_SHIFT) / this_size;
}
MV32 vp10_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;
const MV32 res = {
scaled_y(mv->row, sf) + y_off_q4,
scaled_x(mv->col, sf) + x_off_q4
};
return res;
}
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_setup_scale_factors_for_frame(struct scale_factors *sf,
int other_w, int other_h,
int this_w, int this_h,
int use_highbd) {
#else
void vp10_setup_scale_factors_for_frame(struct scale_factors *sf,
int other_w, int other_h,
int this_w, int this_h) {
#endif
if (!valid_ref_frame_size(other_w, other_h, this_w, this_h)) {
sf->x_scale_fp = REF_INVALID_SCALE;
sf->y_scale_fp = REF_INVALID_SCALE;
return;
}
sf->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
sf->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);
sf->x_step_q4 = scaled_x(16, sf);
sf->y_step_q4 = scaled_y(16, sf);
if (vp10_is_scaled(sf)) {
sf->scale_value_x = scaled_x;
sf->scale_value_y = scaled_y;
} else {
sf->scale_value_x = unscaled_value;
sf->scale_value_y = unscaled_value;
}
// TODO(agrange): Investigate the best choice of functions to use here
// for EIGHTTAP_SMOOTH. Since it is not interpolating, need to choose what
// to do at full-pel offsets. The current selection, where the filter is
// applied in one direction only, and not at all for 0,0, seems to give the
// best quality, but it may be worth trying an additional mode that does
// do the filtering on full-pel.
if (sf->x_step_q4 == 16) {
if (sf->y_step_q4 == 16) {
// No scaling in either direction.
sf->predict[0][0][0] = vpx_convolve_copy;
sf->predict[0][0][1] = vpx_convolve_avg;
sf->predict[0][1][0] = vpx_convolve8_vert;
sf->predict[0][1][1] = vpx_convolve8_avg_vert;
sf->predict[1][0][0] = vpx_convolve8_horiz;
sf->predict[1][0][1] = vpx_convolve8_avg_horiz;
} else {
// No scaling in x direction. Must always scale in the y direction.
sf->predict[0][0][0] = vpx_convolve8_vert;
sf->predict[0][0][1] = vpx_convolve8_avg_vert;
sf->predict[0][1][0] = vpx_convolve8_vert;
sf->predict[0][1][1] = vpx_convolve8_avg_vert;
sf->predict[1][0][0] = vpx_convolve8;
sf->predict[1][0][1] = vpx_convolve8_avg;
}
} else {
if (sf->y_step_q4 == 16) {
// No scaling in the y direction. Must always scale in the x direction.
sf->predict[0][0][0] = vpx_convolve8_horiz;
sf->predict[0][0][1] = vpx_convolve8_avg_horiz;
sf->predict[0][1][0] = vpx_convolve8;
sf->predict[0][1][1] = vpx_convolve8_avg;
sf->predict[1][0][0] = vpx_convolve8_horiz;
sf->predict[1][0][1] = vpx_convolve8_avg_horiz;
} else {
// Must always scale in both directions.
sf->predict[0][0][0] = vpx_convolve8;
sf->predict[0][0][1] = vpx_convolve8_avg;
sf->predict[0][1][0] = vpx_convolve8;
sf->predict[0][1][1] = vpx_convolve8_avg;
sf->predict[1][0][0] = vpx_convolve8;
sf->predict[1][0][1] = vpx_convolve8_avg;
}
}
// 2D subpel motion always gets filtered in both directions
sf->predict[1][1][0] = vpx_convolve8;
sf->predict[1][1][1] = vpx_convolve8_avg;
#if CONFIG_VP9_HIGHBITDEPTH
if (use_highbd) {
if (sf->x_step_q4 == 16) {
if (sf->y_step_q4 == 16) {
// No scaling in either direction.
sf->highbd_predict[0][0][0] = vpx_highbd_convolve_copy;
sf->highbd_predict[0][0][1] = vpx_highbd_convolve_avg;
sf->highbd_predict[0][1][0] = vpx_highbd_convolve8_vert;
sf->highbd_predict[0][1][1] = vpx_highbd_convolve8_avg_vert;
sf->highbd_predict[1][0][0] = vpx_highbd_convolve8_horiz;
sf->highbd_predict[1][0][1] = vpx_highbd_convolve8_avg_horiz;
} else {
// No scaling in x direction. Must always scale in the y direction.
sf->highbd_predict[0][0][0] = vpx_highbd_convolve8_vert;
sf->highbd_predict[0][0][1] = vpx_highbd_convolve8_avg_vert;
sf->highbd_predict[0][1][0] = vpx_highbd_convolve8_vert;
sf->highbd_predict[0][1][1] = vpx_highbd_convolve8_avg_vert;
sf->highbd_predict[1][0][0] = vpx_highbd_convolve8;
sf->highbd_predict[1][0][1] = vpx_highbd_convolve8_avg;
}
} else {
if (sf->y_step_q4 == 16) {
// No scaling in the y direction. Must always scale in the x direction.
sf->highbd_predict[0][0][0] = vpx_highbd_convolve8_horiz;
sf->highbd_predict[0][0][1] = vpx_highbd_convolve8_avg_horiz;
sf->highbd_predict[0][1][0] = vpx_highbd_convolve8;
sf->highbd_predict[0][1][1] = vpx_highbd_convolve8_avg;
sf->highbd_predict[1][0][0] = vpx_highbd_convolve8_horiz;
sf->highbd_predict[1][0][1] = vpx_highbd_convolve8_avg_horiz;
} else {
// Must always scale in both directions.
sf->highbd_predict[0][0][0] = vpx_highbd_convolve8;
sf->highbd_predict[0][0][1] = vpx_highbd_convolve8_avg;
sf->highbd_predict[0][1][0] = vpx_highbd_convolve8;
sf->highbd_predict[0][1][1] = vpx_highbd_convolve8_avg;
sf->highbd_predict[1][0][0] = vpx_highbd_convolve8;
sf->highbd_predict[1][0][1] = vpx_highbd_convolve8_avg;
}
}
// 2D subpel motion always gets filtered in both directions.
sf->highbd_predict[1][1][0] = vpx_highbd_convolve8;
sf->highbd_predict[1][1][1] = vpx_highbd_convolve8_avg;
}
#endif
}

75
vp10/common/scale.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2013 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_SCALE_H_
#define VP10_COMMON_SCALE_H_
#include "vp10/common/mv.h"
#include "vpx_dsp/vpx_convolve.h"
#ifdef __cplusplus
extern "C" {
#endif
#define REF_SCALE_SHIFT 14
#define REF_NO_SCALE (1 << REF_SCALE_SHIFT)
#define REF_INVALID_SCALE -1
struct scale_factors {
int x_scale_fp; // horizontal fixed point scale factor
int y_scale_fp; // vertical fixed point scale factor
int x_step_q4;
int y_step_q4;
int (*scale_value_x)(int val, const struct scale_factors *sf);
int (*scale_value_y)(int val, const struct scale_factors *sf);
convolve_fn_t predict[2][2][2]; // horiz, vert, avg
#if CONFIG_VP9_HIGHBITDEPTH
highbd_convolve_fn_t highbd_predict[2][2][2]; // horiz, vert, avg
#endif
};
MV32 vp10_scale_mv(const MV *mv, int x, int y, const struct scale_factors *sf);
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_setup_scale_factors_for_frame(struct scale_factors *sf,
int other_w, int other_h,
int this_w, int this_h,
int use_high);
#else
void vp10_setup_scale_factors_for_frame(struct scale_factors *sf,
int other_w, int other_h,
int this_w, int this_h);
#endif
static INLINE int vp10_is_valid_scale(const struct scale_factors *sf) {
return sf->x_scale_fp != REF_INVALID_SCALE &&
sf->y_scale_fp != REF_INVALID_SCALE;
}
static INLINE int vp10_is_scaled(const struct scale_factors *sf) {
return vp10_is_valid_scale(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
#endif // VP10_COMMON_SCALE_H_

720
vp10/common/scan.c Normal file
View File

@@ -0,0 +1,720 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "vp10/common/scan.h"
DECLARE_ALIGNED(16, static const int16_t, default_scan_4x4[16]) = {
0, 4, 1, 5,
8, 2, 12, 9,
3, 6, 13, 10,
7, 14, 11, 15,
};
DECLARE_ALIGNED(16, static const int16_t, col_scan_4x4[16]) = {
0, 4, 8, 1,
12, 5, 9, 2,
13, 6, 10, 3,
7, 14, 11, 15,
};
DECLARE_ALIGNED(16, static const int16_t, row_scan_4x4[16]) = {
0, 1, 4, 2,
5, 3, 6, 8,
9, 7, 12, 10,
13, 11, 14, 15,
};
DECLARE_ALIGNED(16, static const int16_t, default_scan_8x8[64]) = {
0, 8, 1, 16, 9, 2, 17, 24,
10, 3, 18, 25, 32, 11, 4, 26,
33, 19, 40, 12, 34, 27, 5, 41,
20, 48, 13, 35, 42, 28, 21, 6,
49, 56, 36, 43, 29, 7, 14, 50,
57, 44, 22, 37, 15, 51, 58, 30,
45, 23, 52, 59, 38, 31, 60, 53,
46, 39, 61, 54, 47, 62, 55, 63,
};
DECLARE_ALIGNED(16, static const int16_t, col_scan_8x8[64]) = {
0, 8, 16, 1, 24, 9, 32, 17,
2, 40, 25, 10, 33, 18, 48, 3,
26, 41, 11, 56, 19, 34, 4, 49,
27, 42, 12, 35, 20, 57, 50, 28,
5, 43, 13, 36, 58, 51, 21, 44,
6, 29, 59, 37, 14, 52, 22, 7,
45, 60, 30, 15, 38, 53, 23, 46,
31, 61, 39, 54, 47, 62, 55, 63,
};
DECLARE_ALIGNED(16, static const int16_t, row_scan_8x8[64]) = {
0, 1, 2, 8, 9, 3, 16, 10,
4, 17, 11, 24, 5, 18, 25, 12,
19, 26, 32, 6, 13, 20, 33, 27,
7, 34, 40, 21, 28, 41, 14, 35,
48, 42, 29, 36, 49, 22, 43, 15,
56, 37, 50, 44, 30, 57, 23, 51,
58, 45, 38, 52, 31, 59, 53, 46,
60, 39, 61, 47, 54, 55, 62, 63,
};
DECLARE_ALIGNED(16, static const int16_t, default_scan_16x16[256]) = {
0, 16, 1, 32, 17, 2, 48, 33, 18, 3, 64, 34, 49, 19, 65, 80,
50, 4, 35, 66, 20, 81, 96, 51, 5, 36, 82, 97, 67, 112, 21, 52,
98, 37, 83, 113, 6, 68, 128, 53, 22, 99, 114, 84, 7, 129, 38, 69,
100, 115, 144, 130, 85, 54, 23, 8, 145, 39, 70, 116, 101, 131, 160, 146,
55, 86, 24, 71, 132, 117, 161, 40, 9, 102, 147, 176, 162, 87, 56, 25,
133, 118, 177, 148, 72, 103, 41, 163, 10, 192, 178, 88, 57, 134, 149, 119,
26, 164, 73, 104, 193, 42, 179, 208, 11, 135, 89, 165, 120, 150, 58, 194,
180, 27, 74, 209, 105, 151, 136, 43, 90, 224, 166, 195, 181, 121, 210, 59,
12, 152, 106, 167, 196, 75, 137, 225, 211, 240, 182, 122, 91, 28, 197, 13,
226, 168, 183, 153, 44, 212, 138, 107, 241, 60, 29, 123, 198, 184, 227, 169,
242, 76, 213, 154, 45, 92, 14, 199, 139, 61, 228, 214, 170, 185, 243, 108,
77, 155, 30, 15, 200, 229, 124, 215, 244, 93, 46, 186, 171, 201, 109, 140,
230, 62, 216, 245, 31, 125, 78, 156, 231, 47, 187, 202, 217, 94, 246, 141,
63, 232, 172, 110, 247, 157, 79, 218, 203, 126, 233, 188, 248, 95, 173, 142,
219, 111, 249, 234, 158, 127, 189, 204, 250, 235, 143, 174, 220, 205, 159,
251,
190, 221, 175, 236, 237, 191, 206, 252, 222, 253, 207, 238, 223, 254, 239,
255,
};
DECLARE_ALIGNED(16, static const int16_t, col_scan_16x16[256]) = {
0, 16, 32, 48, 1, 64, 17, 80, 33, 96, 49, 2, 65, 112, 18, 81,
34, 128, 50, 97, 3, 66, 144, 19, 113, 35, 82, 160, 98, 51, 129, 4,
67, 176, 20, 114, 145, 83, 36, 99, 130, 52, 192, 5, 161, 68, 115, 21,
146, 84, 208, 177, 37, 131, 100, 53, 162, 224, 69, 6, 116, 193, 147, 85,
22, 240, 132, 38, 178, 101, 163, 54, 209, 117, 70, 7, 148, 194, 86, 179,
225, 23, 133, 39, 164, 8, 102, 210, 241, 55, 195, 118, 149, 71, 180, 24,
87, 226, 134, 165, 211, 40, 103, 56, 72, 150, 196, 242, 119, 9, 181, 227,
88, 166, 25, 135, 41, 104, 212, 57, 151, 197, 120, 73, 243, 182, 136, 167,
213, 89, 10, 228, 105, 152, 198, 26, 42, 121, 183, 244, 168, 58, 137, 229,
74, 214, 90, 153, 199, 184, 11, 106, 245, 27, 122, 230, 169, 43, 215, 59,
200, 138, 185, 246, 75, 12, 91, 154, 216, 231, 107, 28, 44, 201, 123, 170,
60, 247, 232, 76, 139, 13, 92, 217, 186, 248, 155, 108, 29, 124, 45, 202,
233, 171, 61, 14, 77, 140, 15, 249, 93, 30, 187, 156, 218, 46, 109, 125,
62, 172, 78, 203, 31, 141, 234, 94, 47, 188, 63, 157, 110, 250, 219, 79,
126, 204, 173, 142, 95, 189, 111, 235, 158, 220, 251, 127, 174, 143, 205,
236,
159, 190, 221, 252, 175, 206, 237, 191, 253, 222, 238, 207, 254, 223, 239,
255,
};
DECLARE_ALIGNED(16, static const int16_t, row_scan_16x16[256]) = {
0, 1, 2, 16, 3, 17, 4, 18, 32, 5, 33, 19, 6, 34, 48, 20,
49, 7, 35, 21, 50, 64, 8, 36, 65, 22, 51, 37, 80, 9, 66, 52,
23, 38, 81, 67, 10, 53, 24, 82, 68, 96, 39, 11, 54, 83, 97, 69,
25, 98, 84, 40, 112, 55, 12, 70, 99, 113, 85, 26, 41, 56, 114, 100,
13, 71, 128, 86, 27, 115, 101, 129, 42, 57, 72, 116, 14, 87, 130, 102,
144, 73, 131, 117, 28, 58, 15, 88, 43, 145, 103, 132, 146, 118, 74, 160,
89, 133, 104, 29, 59, 147, 119, 44, 161, 148, 90, 105, 134, 162, 120, 176,
75, 135, 149, 30, 60, 163, 177, 45, 121, 91, 106, 164, 178, 150, 192, 136,
165, 179, 31, 151, 193, 76, 122, 61, 137, 194, 107, 152, 180, 208, 46, 166,
167, 195, 92, 181, 138, 209, 123, 153, 224, 196, 77, 168, 210, 182, 240, 108,
197, 62, 154, 225, 183, 169, 211, 47, 139, 93, 184, 226, 212, 241, 198, 170,
124, 155, 199, 78, 213, 185, 109, 227, 200, 63, 228, 242, 140, 214, 171, 186,
156, 229, 243, 125, 94, 201, 244, 215, 216, 230, 141, 187, 202, 79, 172, 110,
157, 245, 217, 231, 95, 246, 232, 126, 203, 247, 233, 173, 218, 142, 111,
158,
188, 248, 127, 234, 219, 249, 189, 204, 143, 174, 159, 250, 235, 205, 220,
175,
190, 251, 221, 191, 206, 236, 207, 237, 252, 222, 253, 223, 238, 239, 254,
255,
};
DECLARE_ALIGNED(16, static const int16_t, default_scan_32x32[1024]) = {
0, 32, 1, 64, 33, 2, 96, 65, 34, 128, 3, 97, 66, 160,
129, 35, 98, 4, 67, 130, 161, 192, 36, 99, 224, 5, 162, 193,
68, 131, 37, 100,
225, 194, 256, 163, 69, 132, 6, 226, 257, 288, 195, 101, 164, 38,
258, 7, 227, 289, 133, 320, 70, 196, 165, 290, 259, 228, 39, 321,
102, 352, 8, 197,
71, 134, 322, 291, 260, 353, 384, 229, 166, 103, 40, 354, 323, 292,
135, 385, 198, 261, 72, 9, 416, 167, 386, 355, 230, 324, 104, 293,
41, 417, 199, 136,
262, 387, 448, 325, 356, 10, 73, 418, 231, 168, 449, 294, 388, 105,
419, 263, 42, 200, 357, 450, 137, 480, 74, 326, 232, 11, 389, 169,
295, 420, 106, 451,
481, 358, 264, 327, 201, 43, 138, 512, 482, 390, 296, 233, 170, 421,
75, 452, 359, 12, 513, 265, 483, 328, 107, 202, 514, 544, 422, 391,
453, 139, 44, 234,
484, 297, 360, 171, 76, 515, 545, 266, 329, 454, 13, 423, 203, 108,
546, 485, 576, 298, 235, 140, 361, 330, 172, 547, 45, 455, 267, 577,
486, 77, 204, 362,
608, 14, 299, 578, 109, 236, 487, 609, 331, 141, 579, 46, 15, 173,
610, 363, 78, 205, 16, 110, 237, 611, 142, 47, 174, 79, 206, 17,
111, 238, 48, 143,
80, 175, 112, 207, 49, 18, 239, 81, 113, 19, 50, 82, 114, 51,
83, 115, 640, 516, 392, 268, 144, 20, 672, 641, 548, 517, 424,
393, 300, 269, 176, 145,
52, 21, 704, 673, 642, 580, 549, 518, 456, 425, 394, 332, 301,
270, 208, 177, 146, 84, 53, 22, 736, 705, 674, 643, 612, 581,
550, 519, 488, 457, 426, 395,
364, 333, 302, 271, 240, 209, 178, 147, 116, 85, 54, 23, 737,
706, 675, 613, 582, 551, 489, 458, 427, 365, 334, 303, 241,
210, 179, 117, 86, 55, 738, 707,
614, 583, 490, 459, 366, 335, 242, 211, 118, 87, 739, 615, 491,
367, 243, 119, 768, 644, 520, 396, 272, 148, 24, 800, 769, 676,
645, 552, 521, 428, 397, 304,
273, 180, 149, 56, 25, 832, 801, 770, 708, 677, 646, 584, 553,
522, 460, 429, 398, 336, 305, 274, 212, 181, 150, 88, 57, 26,
864, 833, 802, 771, 740, 709,
678, 647, 616, 585, 554, 523, 492, 461, 430, 399, 368, 337, 306,
275, 244, 213, 182, 151, 120, 89, 58, 27, 865, 834, 803, 741,
710, 679, 617, 586, 555, 493,
462, 431, 369, 338, 307, 245, 214, 183, 121, 90, 59, 866, 835,
742, 711, 618, 587, 494, 463, 370, 339, 246, 215, 122, 91, 867,
743, 619, 495, 371, 247, 123,
896, 772, 648, 524, 400, 276, 152, 28, 928, 897, 804, 773, 680,
649, 556, 525, 432, 401, 308, 277, 184, 153, 60, 29, 960, 929,
898, 836, 805, 774, 712, 681,
650, 588, 557, 526, 464, 433, 402, 340, 309, 278, 216, 185, 154,
92, 61, 30, 992, 961, 930, 899, 868, 837, 806, 775, 744, 713, 682,
651, 620, 589, 558, 527,
496, 465, 434, 403, 372, 341, 310, 279, 248, 217, 186, 155, 124,
93, 62, 31, 993, 962, 931, 869, 838, 807, 745, 714, 683, 621, 590,
559, 497, 466, 435, 373,
342, 311, 249, 218, 187, 125, 94, 63, 994, 963, 870, 839, 746, 715,
622, 591, 498, 467, 374, 343, 250, 219, 126, 95, 995, 871, 747, 623,
499, 375, 251, 127,
900, 776, 652, 528, 404, 280, 156, 932, 901, 808, 777, 684, 653, 560,
529, 436, 405, 312, 281, 188, 157, 964, 933, 902, 840, 809, 778, 716,
685, 654, 592, 561,
530, 468, 437, 406, 344, 313, 282, 220, 189, 158, 996, 965, 934, 903,
872, 841, 810, 779, 748, 717, 686, 655, 624, 593, 562, 531, 500, 469,
438, 407, 376, 345,
314, 283, 252, 221, 190, 159, 997, 966, 935, 873, 842, 811, 749, 718,
687, 625, 594, 563, 501, 470, 439, 377, 346, 315, 253, 222, 191, 998,
967, 874, 843, 750,
719, 626, 595, 502, 471, 378, 347, 254, 223, 999, 875, 751, 627, 503,
379, 255, 904, 780, 656, 532, 408, 284, 936, 905, 812, 781, 688, 657,
564, 533, 440, 409,
316, 285, 968, 937, 906, 844, 813, 782, 720, 689, 658, 596, 565, 534,
472, 441, 410, 348, 317, 286, 1000, 969, 938, 907, 876, 845, 814, 783,
752, 721, 690, 659,
628, 597, 566, 535, 504, 473, 442, 411, 380, 349, 318, 287, 1001, 970,
939, 877, 846, 815, 753, 722, 691, 629, 598, 567, 505, 474, 443, 381,
350, 319, 1002, 971,
878, 847, 754, 723, 630, 599, 506, 475, 382, 351, 1003, 879, 755, 631,
507, 383, 908, 784, 660, 536, 412, 940, 909, 816, 785, 692, 661, 568,
537, 444, 413, 972,
941, 910, 848, 817, 786, 724, 693, 662, 600, 569, 538, 476, 445, 414,
1004, 973, 942, 911, 880, 849, 818, 787, 756, 725, 694, 663, 632, 601,
570, 539, 508, 477,
446, 415, 1005, 974, 943, 881, 850, 819, 757, 726, 695, 633, 602, 571,
509, 478, 447, 1006, 975, 882, 851, 758, 727, 634, 603, 510, 479,
1007, 883, 759, 635, 511,
912, 788, 664, 540, 944, 913, 820, 789, 696, 665, 572, 541, 976, 945,
914, 852, 821, 790, 728, 697, 666, 604, 573, 542, 1008, 977, 946, 915,
884, 853, 822, 791,
760, 729, 698, 667, 636, 605, 574, 543, 1009, 978, 947, 885, 854, 823,
761, 730, 699, 637, 606, 575, 1010, 979, 886, 855, 762, 731, 638, 607,
1011, 887, 763, 639,
916, 792, 668, 948, 917, 824, 793, 700, 669, 980, 949, 918, 856, 825,
794, 732, 701, 670, 1012, 981, 950, 919, 888, 857, 826, 795, 764, 733,
702, 671, 1013, 982,
951, 889, 858, 827, 765, 734, 703, 1014, 983, 890, 859, 766, 735, 1015,
891, 767, 920, 796, 952, 921, 828, 797, 984, 953, 922, 860, 829, 798,
1016, 985, 954, 923,
892, 861, 830, 799, 1017, 986, 955, 893, 862, 831, 1018, 987, 894, 863,
1019, 895, 924, 956, 925, 988, 957, 926, 1020, 989, 958, 927, 1021,
990, 959, 1022, 991, 1023,
};
// Neighborhood 5-tuples for various scans and blocksizes,
// in {top, left, topleft, topright, bottomleft} order
// for each position in raster scan order.
// -1 indicates the neighbor does not exist.
DECLARE_ALIGNED(16, static const int16_t,
default_scan_4x4_neighbors[17 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 0, 0, 1, 4, 4, 4, 1, 1, 8, 8, 5, 8, 2, 2, 2, 5, 9, 12, 6, 9,
3, 6, 10, 13, 7, 10, 11, 14, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
col_scan_4x4_neighbors[17 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 4, 4, 0, 0, 8, 8, 1, 1, 5, 5, 1, 1, 9, 9, 2, 2, 6, 6, 2, 2, 3,
3, 10, 10, 7, 7, 11, 11, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
row_scan_4x4_neighbors[17 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 0, 0, 1, 1, 4, 4, 2, 2, 5, 5, 4, 4, 8, 8, 6, 6, 8, 8, 9, 9, 12,
12, 10, 10, 13, 13, 14, 14, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
col_scan_8x8_neighbors[65 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 8, 8, 0, 0, 16, 16, 1, 1, 24, 24, 9, 9, 1, 1, 32, 32, 17, 17, 2,
2, 25, 25, 10, 10, 40, 40, 2, 2, 18, 18, 33, 33, 3, 3, 48, 48, 11, 11, 26,
26, 3, 3, 41, 41, 19, 19, 34, 34, 4, 4, 27, 27, 12, 12, 49, 49, 42, 42, 20,
20, 4, 4, 35, 35, 5, 5, 28, 28, 50, 50, 43, 43, 13, 13, 36, 36, 5, 5, 21, 21,
51, 51, 29, 29, 6, 6, 44, 44, 14, 14, 6, 6, 37, 37, 52, 52, 22, 22, 7, 7, 30,
30, 45, 45, 15, 15, 38, 38, 23, 23, 53, 53, 31, 31, 46, 46, 39, 39, 54, 54,
47, 47, 55, 55, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
row_scan_8x8_neighbors[65 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 1, 1, 0, 0, 8, 8, 2, 2, 8, 8, 9, 9, 3, 3, 16, 16, 10, 10, 16, 16,
4, 4, 17, 17, 24, 24, 11, 11, 18, 18, 25, 25, 24, 24, 5, 5, 12, 12, 19, 19,
32, 32, 26, 26, 6, 6, 33, 33, 32, 32, 20, 20, 27, 27, 40, 40, 13, 13, 34, 34,
40, 40, 41, 41, 28, 28, 35, 35, 48, 48, 21, 21, 42, 42, 14, 14, 48, 48, 36,
36, 49, 49, 43, 43, 29, 29, 56, 56, 22, 22, 50, 50, 57, 57, 44, 44, 37, 37,
51, 51, 30, 30, 58, 58, 52, 52, 45, 45, 59, 59, 38, 38, 60, 60, 46, 46, 53,
53, 54, 54, 61, 61, 62, 62, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
default_scan_8x8_neighbors[65 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 0, 0, 8, 8, 1, 8, 1, 1, 9, 16, 16, 16, 2, 9, 2, 2, 10, 17, 17,
24, 24, 24, 3, 10, 3, 3, 18, 25, 25, 32, 11, 18, 32, 32, 4, 11, 26, 33, 19,
26, 4, 4, 33, 40, 12, 19, 40, 40, 5, 12, 27, 34, 34, 41, 20, 27, 13, 20, 5,
5, 41, 48, 48, 48, 28, 35, 35, 42, 21, 28, 6, 6, 6, 13, 42, 49, 49, 56, 36,
43, 14, 21, 29, 36, 7, 14, 43, 50, 50, 57, 22, 29, 37, 44, 15, 22, 44, 51,
51, 58, 30, 37, 23, 30, 52, 59, 45, 52, 38, 45, 31, 38, 53, 60, 46, 53, 39,
46, 54, 61, 47, 54, 55, 62, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
col_scan_16x16_neighbors[257 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 16, 16, 32, 32, 0, 0, 48, 48, 1, 1, 64, 64,
17, 17, 80, 80, 33, 33, 1, 1, 49, 49, 96, 96, 2, 2, 65, 65,
18, 18, 112, 112, 34, 34, 81, 81, 2, 2, 50, 50, 128, 128, 3, 3,
97, 97, 19, 19, 66, 66, 144, 144, 82, 82, 35, 35, 113, 113, 3, 3,
51, 51, 160, 160, 4, 4, 98, 98, 129, 129, 67, 67, 20, 20, 83, 83,
114, 114, 36, 36, 176, 176, 4, 4, 145, 145, 52, 52, 99, 99, 5, 5,
130, 130, 68, 68, 192, 192, 161, 161, 21, 21, 115, 115, 84, 84, 37, 37,
146, 146, 208, 208, 53, 53, 5, 5, 100, 100, 177, 177, 131, 131, 69, 69,
6, 6, 224, 224, 116, 116, 22, 22, 162, 162, 85, 85, 147, 147, 38, 38,
193, 193, 101, 101, 54, 54, 6, 6, 132, 132, 178, 178, 70, 70, 163, 163,
209, 209, 7, 7, 117, 117, 23, 23, 148, 148, 7, 7, 86, 86, 194, 194,
225, 225, 39, 39, 179, 179, 102, 102, 133, 133, 55, 55, 164, 164, 8, 8,
71, 71, 210, 210, 118, 118, 149, 149, 195, 195, 24, 24, 87, 87, 40, 40,
56, 56, 134, 134, 180, 180, 226, 226, 103, 103, 8, 8, 165, 165, 211, 211,
72, 72, 150, 150, 9, 9, 119, 119, 25, 25, 88, 88, 196, 196, 41, 41,
135, 135, 181, 181, 104, 104, 57, 57, 227, 227, 166, 166, 120, 120, 151, 151,
197, 197, 73, 73, 9, 9, 212, 212, 89, 89, 136, 136, 182, 182, 10, 10,
26, 26, 105, 105, 167, 167, 228, 228, 152, 152, 42, 42, 121, 121, 213, 213,
58, 58, 198, 198, 74, 74, 137, 137, 183, 183, 168, 168, 10, 10, 90, 90,
229, 229, 11, 11, 106, 106, 214, 214, 153, 153, 27, 27, 199, 199, 43, 43,
184, 184, 122, 122, 169, 169, 230, 230, 59, 59, 11, 11, 75, 75, 138, 138,
200, 200, 215, 215, 91, 91, 12, 12, 28, 28, 185, 185, 107, 107, 154, 154,
44, 44, 231, 231, 216, 216, 60, 60, 123, 123, 12, 12, 76, 76, 201, 201,
170, 170, 232, 232, 139, 139, 92, 92, 13, 13, 108, 108, 29, 29, 186, 186,
217, 217, 155, 155, 45, 45, 13, 13, 61, 61, 124, 124, 14, 14, 233, 233,
77, 77, 14, 14, 171, 171, 140, 140, 202, 202, 30, 30, 93, 93, 109, 109,
46, 46, 156, 156, 62, 62, 187, 187, 15, 15, 125, 125, 218, 218, 78, 78,
31, 31, 172, 172, 47, 47, 141, 141, 94, 94, 234, 234, 203, 203, 63, 63,
110, 110, 188, 188, 157, 157, 126, 126, 79, 79, 173, 173, 95, 95, 219, 219,
142, 142, 204, 204, 235, 235, 111, 111, 158, 158, 127, 127, 189, 189, 220,
220, 143, 143, 174, 174, 205, 205, 236, 236, 159, 159, 190, 190, 221, 221,
175, 175, 237, 237, 206, 206, 222, 222, 191, 191, 238, 238, 207, 207, 223,
223, 239, 239, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
row_scan_16x16_neighbors[257 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 16, 16, 3, 3, 17, 17,
16, 16, 4, 4, 32, 32, 18, 18, 5, 5, 33, 33, 32, 32, 19, 19,
48, 48, 6, 6, 34, 34, 20, 20, 49, 49, 48, 48, 7, 7, 35, 35,
64, 64, 21, 21, 50, 50, 36, 36, 64, 64, 8, 8, 65, 65, 51, 51,
22, 22, 37, 37, 80, 80, 66, 66, 9, 9, 52, 52, 23, 23, 81, 81,
67, 67, 80, 80, 38, 38, 10, 10, 53, 53, 82, 82, 96, 96, 68, 68,
24, 24, 97, 97, 83, 83, 39, 39, 96, 96, 54, 54, 11, 11, 69, 69,
98, 98, 112, 112, 84, 84, 25, 25, 40, 40, 55, 55, 113, 113, 99, 99,
12, 12, 70, 70, 112, 112, 85, 85, 26, 26, 114, 114, 100, 100, 128, 128,
41, 41, 56, 56, 71, 71, 115, 115, 13, 13, 86, 86, 129, 129, 101, 101,
128, 128, 72, 72, 130, 130, 116, 116, 27, 27, 57, 57, 14, 14, 87, 87,
42, 42, 144, 144, 102, 102, 131, 131, 145, 145, 117, 117, 73, 73, 144, 144,
88, 88, 132, 132, 103, 103, 28, 28, 58, 58, 146, 146, 118, 118, 43, 43,
160, 160, 147, 147, 89, 89, 104, 104, 133, 133, 161, 161, 119, 119, 160, 160,
74, 74, 134, 134, 148, 148, 29, 29, 59, 59, 162, 162, 176, 176, 44, 44,
120, 120, 90, 90, 105, 105, 163, 163, 177, 177, 149, 149, 176, 176, 135, 135,
164, 164, 178, 178, 30, 30, 150, 150, 192, 192, 75, 75, 121, 121, 60, 60,
136, 136, 193, 193, 106, 106, 151, 151, 179, 179, 192, 192, 45, 45, 165, 165,
166, 166, 194, 194, 91, 91, 180, 180, 137, 137, 208, 208, 122, 122, 152, 152,
208, 208, 195, 195, 76, 76, 167, 167, 209, 209, 181, 181, 224, 224, 107, 107,
196, 196, 61, 61, 153, 153, 224, 224, 182, 182, 168, 168, 210, 210, 46, 46,
138, 138, 92, 92, 183, 183, 225, 225, 211, 211, 240, 240, 197, 197, 169, 169,
123, 123, 154, 154, 198, 198, 77, 77, 212, 212, 184, 184, 108, 108, 226, 226,
199, 199, 62, 62, 227, 227, 241, 241, 139, 139, 213, 213, 170, 170, 185, 185,
155, 155, 228, 228, 242, 242, 124, 124, 93, 93, 200, 200, 243, 243, 214, 214,
215, 215, 229, 229, 140, 140, 186, 186, 201, 201, 78, 78, 171, 171, 109, 109,
156, 156, 244, 244, 216, 216, 230, 230, 94, 94, 245, 245, 231, 231, 125, 125,
202, 202, 246, 246, 232, 232, 172, 172, 217, 217, 141, 141, 110, 110, 157,
157, 187, 187, 247, 247, 126, 126, 233, 233, 218, 218, 248, 248, 188, 188,
203, 203, 142, 142, 173, 173, 158, 158, 249, 249, 234, 234, 204, 204, 219,
219, 174, 174, 189, 189, 250, 250, 220, 220, 190, 190, 205, 205, 235, 235,
206, 206, 236, 236, 251, 251, 221, 221, 252, 252, 222, 222, 237, 237, 238,
238, 253, 253, 254, 254, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
default_scan_16x16_neighbors[257 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 0, 0, 16, 16, 1, 16, 1, 1, 32, 32, 17, 32,
2, 17, 2, 2, 48, 48, 18, 33, 33, 48, 3, 18, 49, 64, 64, 64,
34, 49, 3, 3, 19, 34, 50, 65, 4, 19, 65, 80, 80, 80, 35, 50,
4, 4, 20, 35, 66, 81, 81, 96, 51, 66, 96, 96, 5, 20, 36, 51,
82, 97, 21, 36, 67, 82, 97, 112, 5, 5, 52, 67, 112, 112, 37, 52,
6, 21, 83, 98, 98, 113, 68, 83, 6, 6, 113, 128, 22, 37, 53, 68,
84, 99, 99, 114, 128, 128, 114, 129, 69, 84, 38, 53, 7, 22, 7, 7,
129, 144, 23, 38, 54, 69, 100, 115, 85, 100, 115, 130, 144, 144, 130, 145,
39, 54, 70, 85, 8, 23, 55, 70, 116, 131, 101, 116, 145, 160, 24, 39,
8, 8, 86, 101, 131, 146, 160, 160, 146, 161, 71, 86, 40, 55, 9, 24,
117, 132, 102, 117, 161, 176, 132, 147, 56, 71, 87, 102, 25, 40, 147, 162,
9, 9, 176, 176, 162, 177, 72, 87, 41, 56, 118, 133, 133, 148, 103, 118,
10, 25, 148, 163, 57, 72, 88, 103, 177, 192, 26, 41, 163, 178, 192, 192,
10, 10, 119, 134, 73, 88, 149, 164, 104, 119, 134, 149, 42, 57, 178, 193,
164, 179, 11, 26, 58, 73, 193, 208, 89, 104, 135, 150, 120, 135, 27, 42,
74, 89, 208, 208, 150, 165, 179, 194, 165, 180, 105, 120, 194, 209, 43, 58,
11, 11, 136, 151, 90, 105, 151, 166, 180, 195, 59, 74, 121, 136, 209, 224,
195, 210, 224, 224, 166, 181, 106, 121, 75, 90, 12, 27, 181, 196, 12, 12,
210, 225, 152, 167, 167, 182, 137, 152, 28, 43, 196, 211, 122, 137, 91, 106,
225, 240, 44, 59, 13, 28, 107, 122, 182, 197, 168, 183, 211, 226, 153, 168,
226, 241, 60, 75, 197, 212, 138, 153, 29, 44, 76, 91, 13, 13, 183, 198,
123, 138, 45, 60, 212, 227, 198, 213, 154, 169, 169, 184, 227, 242, 92, 107,
61, 76, 139, 154, 14, 29, 14, 14, 184, 199, 213, 228, 108, 123, 199, 214,
228, 243, 77, 92, 30, 45, 170, 185, 155, 170, 185, 200, 93, 108, 124, 139,
214, 229, 46, 61, 200, 215, 229, 244, 15, 30, 109, 124, 62, 77, 140, 155,
215, 230, 31, 46, 171, 186, 186, 201, 201, 216, 78, 93, 230, 245, 125, 140,
47, 62, 216, 231, 156, 171, 94, 109, 231, 246, 141, 156, 63, 78, 202, 217,
187, 202, 110, 125, 217, 232, 172, 187, 232, 247, 79, 94, 157, 172, 126, 141,
203, 218, 95, 110, 233, 248, 218, 233, 142, 157, 111, 126, 173, 188, 188, 203,
234, 249, 219, 234, 127, 142, 158, 173, 204, 219, 189, 204, 143, 158, 235,
250, 174, 189, 205, 220, 159, 174, 220, 235, 221, 236, 175, 190, 190, 205,
236, 251, 206, 221, 237, 252, 191, 206, 222, 237, 207, 222, 238, 253, 223,
238, 239, 254, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t,
default_scan_32x32_neighbors[1025 * MAX_NEIGHBORS]) = {
0, 0, 0, 0, 0, 0, 32, 32, 1, 32, 1, 1, 64, 64, 33, 64,
2, 33, 96, 96, 2, 2, 65, 96, 34, 65, 128, 128, 97, 128, 3, 34,
66, 97, 3, 3, 35, 66, 98, 129, 129, 160, 160, 160, 4, 35, 67, 98,
192, 192, 4, 4, 130, 161, 161, 192, 36, 67, 99, 130, 5, 36, 68, 99,
193, 224, 162, 193, 224, 224, 131, 162, 37, 68, 100, 131, 5, 5, 194, 225,
225, 256, 256, 256, 163, 194, 69, 100, 132, 163, 6, 37, 226, 257, 6, 6,
195, 226, 257, 288, 101, 132, 288, 288, 38, 69, 164, 195, 133, 164, 258, 289,
227, 258, 196, 227, 7, 38, 289, 320, 70, 101, 320, 320, 7, 7, 165, 196,
39, 70, 102, 133, 290, 321, 259, 290, 228, 259, 321, 352, 352, 352, 197, 228,
134, 165, 71, 102, 8, 39, 322, 353, 291, 322, 260, 291, 103, 134, 353, 384,
166, 197, 229, 260, 40, 71, 8, 8, 384, 384, 135, 166, 354, 385, 323, 354,
198, 229, 292, 323, 72, 103, 261, 292, 9, 40, 385, 416, 167, 198, 104, 135,
230, 261, 355, 386, 416, 416, 293, 324, 324, 355, 9, 9, 41, 72, 386, 417,
199, 230, 136, 167, 417, 448, 262, 293, 356, 387, 73, 104, 387, 418, 231, 262,
10, 41, 168, 199, 325, 356, 418, 449, 105, 136, 448, 448, 42, 73, 294, 325,
200, 231, 10, 10, 357, 388, 137, 168, 263, 294, 388, 419, 74, 105, 419, 450,
449, 480, 326, 357, 232, 263, 295, 326, 169, 200, 11, 42, 106, 137, 480, 480,
450, 481, 358, 389, 264, 295, 201, 232, 138, 169, 389, 420, 43, 74, 420, 451,
327, 358, 11, 11, 481, 512, 233, 264, 451, 482, 296, 327, 75, 106, 170, 201,
482, 513, 512, 512, 390, 421, 359, 390, 421, 452, 107, 138, 12, 43, 202, 233,
452, 483, 265, 296, 328, 359, 139, 170, 44, 75, 483, 514, 513, 544, 234, 265,
297, 328, 422, 453, 12, 12, 391, 422, 171, 202, 76, 107, 514, 545, 453, 484,
544, 544, 266, 297, 203, 234, 108, 139, 329, 360, 298, 329, 140, 171, 515,
546, 13, 44, 423, 454, 235, 266, 545, 576, 454, 485, 45, 76, 172, 203, 330,
361, 576, 576, 13, 13, 267, 298, 546, 577, 77, 108, 204, 235, 455, 486, 577,
608, 299, 330, 109, 140, 547, 578, 14, 45, 14, 14, 141, 172, 578, 609, 331,
362, 46, 77, 173, 204, 15, 15, 78, 109, 205, 236, 579, 610, 110, 141, 15, 46,
142, 173, 47, 78, 174, 205, 16, 16, 79, 110, 206, 237, 16, 47, 111, 142,
48, 79, 143, 174, 80, 111, 175, 206, 17, 48, 17, 17, 207, 238, 49, 80,
81, 112, 18, 18, 18, 49, 50, 81, 82, 113, 19, 50, 51, 82, 83, 114, 608, 608,
484, 515, 360, 391, 236, 267, 112, 143, 19, 19, 640, 640, 609, 640, 516, 547,
485, 516, 392, 423, 361, 392, 268, 299, 237, 268, 144, 175, 113, 144, 20, 51,
20, 20, 672, 672, 641, 672, 610, 641, 548, 579, 517, 548, 486, 517, 424, 455,
393, 424, 362, 393, 300, 331, 269, 300, 238, 269, 176, 207, 145, 176, 114,
145, 52, 83, 21, 52, 21, 21, 704, 704, 673, 704, 642, 673, 611, 642, 580,
611, 549, 580, 518, 549, 487, 518, 456, 487, 425, 456, 394, 425, 363, 394,
332, 363, 301, 332, 270, 301, 239, 270, 208, 239, 177, 208, 146, 177, 115,
146, 84, 115, 53, 84, 22, 53, 22, 22, 705, 736, 674, 705, 643, 674, 581, 612,
550, 581, 519, 550, 457, 488, 426, 457, 395, 426, 333, 364, 302, 333, 271,
302, 209, 240, 178, 209, 147, 178, 85, 116, 54, 85, 23, 54, 706, 737, 675,
706, 582, 613, 551, 582, 458, 489, 427, 458, 334, 365, 303, 334, 210, 241,
179, 210, 86, 117, 55, 86, 707, 738, 583, 614, 459, 490, 335, 366, 211, 242,
87, 118, 736, 736, 612, 643, 488, 519, 364, 395, 240, 271, 116, 147, 23, 23,
768, 768, 737, 768, 644, 675, 613, 644, 520, 551, 489, 520, 396, 427, 365,
396, 272, 303, 241, 272, 148, 179, 117, 148, 24, 55, 24, 24, 800, 800, 769,
800, 738, 769, 676, 707, 645, 676, 614, 645, 552, 583, 521, 552, 490, 521,
428, 459, 397, 428, 366, 397, 304, 335, 273, 304, 242, 273, 180, 211, 149,
180, 118, 149, 56, 87, 25, 56, 25, 25, 832, 832, 801, 832, 770, 801, 739,
770, 708, 739, 677, 708, 646, 677, 615, 646, 584, 615, 553, 584, 522, 553,
491, 522, 460, 491, 429, 460, 398, 429, 367, 398, 336, 367, 305, 336, 274,
305, 243, 274, 212, 243, 181, 212, 150, 181, 119, 150, 88, 119, 57, 88, 26,
57, 26, 26, 833, 864, 802, 833, 771, 802, 709, 740, 678, 709, 647, 678, 585,
616, 554, 585, 523, 554, 461, 492, 430, 461, 399, 430, 337, 368, 306, 337,
275, 306, 213, 244, 182, 213, 151, 182, 89, 120, 58, 89, 27, 58, 834, 865,
803, 834, 710, 741, 679, 710, 586, 617, 555, 586, 462, 493, 431, 462, 338,
369, 307, 338, 214, 245, 183, 214, 90, 121, 59, 90, 835, 866, 711, 742, 587,
618, 463, 494, 339, 370, 215, 246, 91, 122, 864, 864, 740, 771, 616, 647,
492, 523, 368, 399, 244, 275, 120, 151, 27, 27, 896, 896, 865, 896, 772, 803,
741, 772, 648, 679, 617, 648, 524, 555, 493, 524, 400, 431, 369, 400, 276,
307, 245, 276, 152, 183, 121, 152, 28, 59, 28, 28, 928, 928, 897, 928, 866,
897, 804, 835, 773, 804, 742, 773, 680, 711, 649, 680, 618, 649, 556, 587,
525, 556, 494, 525, 432, 463, 401, 432, 370, 401, 308, 339, 277, 308, 246,
277, 184, 215, 153, 184, 122, 153, 60, 91, 29, 60, 29, 29, 960, 960, 929,
960, 898, 929, 867, 898, 836, 867, 805, 836, 774, 805, 743, 774, 712, 743,
681, 712, 650, 681, 619, 650, 588, 619, 557, 588, 526, 557, 495, 526, 464,
495, 433, 464, 402, 433, 371, 402, 340, 371, 309, 340, 278, 309, 247, 278,
216, 247, 185, 216, 154, 185, 123, 154, 92, 123, 61, 92, 30, 61, 30, 30,
961, 992, 930, 961, 899, 930, 837, 868, 806, 837, 775, 806, 713, 744, 682,
713, 651, 682, 589, 620, 558, 589, 527, 558, 465, 496, 434, 465, 403, 434,
341, 372, 310, 341, 279, 310, 217, 248, 186, 217, 155, 186, 93, 124, 62, 93,
31, 62, 962, 993, 931, 962, 838, 869, 807, 838, 714, 745, 683, 714, 590, 621,
559, 590, 466, 497, 435, 466, 342, 373, 311, 342, 218, 249, 187, 218, 94,
125, 63, 94, 963, 994, 839, 870, 715, 746, 591, 622, 467, 498, 343, 374, 219,
250, 95, 126, 868, 899, 744, 775, 620, 651, 496, 527, 372, 403, 248, 279,
124, 155, 900, 931, 869, 900, 776, 807, 745, 776, 652, 683, 621, 652, 528,
559, 497, 528, 404, 435, 373, 404, 280, 311, 249, 280, 156, 187, 125, 156,
932, 963, 901, 932, 870, 901, 808, 839, 777, 808, 746, 777, 684, 715, 653,
684, 622, 653, 560, 591, 529, 560, 498, 529, 436, 467, 405, 436, 374, 405,
312, 343, 281, 312, 250, 281, 188, 219, 157, 188, 126, 157, 964, 995, 933,
964, 902, 933, 871, 902, 840, 871, 809, 840, 778, 809, 747, 778, 716, 747,
685, 716, 654, 685, 623, 654, 592, 623, 561, 592, 530, 561, 499, 530, 468,
499, 437, 468, 406, 437, 375, 406, 344, 375, 313, 344, 282, 313, 251, 282,
220, 251, 189, 220, 158, 189, 127, 158, 965, 996, 934, 965, 903, 934, 841,
872, 810, 841, 779, 810, 717, 748, 686, 717, 655, 686, 593, 624, 562, 593,
531, 562, 469, 500, 438, 469, 407, 438, 345, 376, 314, 345, 283, 314, 221,
252, 190, 221, 159, 190, 966, 997, 935, 966, 842, 873, 811, 842, 718, 749,
687, 718, 594, 625, 563, 594, 470, 501, 439, 470, 346, 377, 315, 346, 222,
253, 191, 222, 967, 998, 843, 874, 719, 750, 595, 626, 471, 502, 347, 378,
223, 254, 872, 903, 748, 779, 624, 655, 500, 531, 376, 407, 252, 283, 904,
935, 873, 904, 780, 811, 749, 780, 656, 687, 625, 656, 532, 563, 501, 532,
408, 439, 377, 408, 284, 315, 253, 284, 936, 967, 905, 936, 874, 905, 812,
843, 781, 812, 750, 781, 688, 719, 657, 688, 626, 657, 564, 595, 533, 564,
502, 533, 440, 471, 409, 440, 378, 409, 316, 347, 285, 316, 254, 285, 968,
999, 937, 968, 906, 937, 875, 906, 844, 875, 813, 844, 782, 813, 751, 782,
720, 751, 689, 720, 658, 689, 627, 658, 596, 627, 565, 596, 534, 565, 503,
534, 472, 503, 441, 472, 410, 441, 379, 410, 348, 379, 317, 348, 286, 317,
255, 286, 969, 1000, 938, 969, 907, 938, 845, 876, 814, 845, 783, 814, 721,
752, 690, 721, 659, 690, 597, 628, 566, 597, 535, 566, 473, 504, 442, 473,
411, 442, 349, 380, 318, 349, 287, 318, 970, 1001, 939, 970, 846, 877, 815,
846, 722, 753, 691, 722, 598, 629, 567, 598, 474, 505, 443, 474, 350, 381,
319, 350, 971, 1002, 847, 878, 723, 754, 599, 630, 475, 506, 351, 382, 876,
907, 752, 783, 628, 659, 504, 535, 380, 411, 908, 939, 877, 908, 784, 815,
753, 784, 660, 691, 629, 660, 536, 567, 505, 536, 412, 443, 381, 412, 940,
971, 909, 940, 878, 909, 816, 847, 785, 816, 754, 785, 692, 723, 661, 692,
630, 661, 568, 599, 537, 568, 506, 537, 444, 475, 413, 444, 382, 413, 972,
1003, 941, 972, 910, 941, 879, 910, 848, 879, 817, 848, 786, 817, 755, 786,
724, 755, 693, 724, 662, 693, 631, 662, 600, 631, 569, 600, 538, 569, 507,
538, 476, 507, 445, 476, 414, 445, 383, 414, 973, 1004, 942, 973, 911, 942,
849, 880, 818, 849, 787, 818, 725, 756, 694, 725, 663, 694, 601, 632, 570,
601, 539, 570, 477, 508, 446, 477, 415, 446, 974, 1005, 943, 974, 850, 881,
819, 850, 726, 757, 695, 726, 602, 633, 571, 602, 478, 509, 447, 478, 975,
1006, 851, 882, 727, 758, 603, 634, 479, 510, 880, 911, 756, 787, 632, 663,
508, 539, 912, 943, 881, 912, 788, 819, 757, 788, 664, 695, 633, 664, 540,
571, 509, 540, 944, 975, 913, 944, 882, 913, 820, 851, 789, 820, 758, 789,
696, 727, 665, 696, 634, 665, 572, 603, 541, 572, 510, 541, 976, 1007, 945,
976, 914, 945, 883, 914, 852, 883, 821, 852, 790, 821, 759, 790, 728, 759,
697, 728, 666, 697, 635, 666, 604, 635, 573, 604, 542, 573, 511, 542, 977,
1008, 946, 977, 915, 946, 853, 884, 822, 853, 791, 822, 729, 760, 698, 729,
667, 698, 605, 636, 574, 605, 543, 574, 978, 1009, 947, 978, 854, 885, 823,
854, 730, 761, 699, 730, 606, 637, 575, 606, 979, 1010, 855, 886, 731, 762,
607, 638, 884, 915, 760, 791, 636, 667, 916, 947, 885, 916, 792, 823, 761,
792, 668, 699, 637, 668, 948, 979, 917, 948, 886, 917, 824, 855, 793, 824,
762, 793, 700, 731, 669, 700, 638, 669, 980, 1011, 949, 980, 918, 949, 887,
918, 856, 887, 825, 856, 794, 825, 763, 794, 732, 763, 701, 732, 670, 701,
639, 670, 981, 1012, 950, 981, 919, 950, 857, 888, 826, 857, 795, 826, 733,
764, 702, 733, 671, 702, 982, 1013, 951, 982, 858, 889, 827, 858, 734, 765,
703, 734, 983, 1014, 859, 890, 735, 766, 888, 919, 764, 795, 920, 951, 889,
920, 796, 827, 765, 796, 952, 983, 921, 952, 890, 921, 828, 859, 797, 828,
766, 797, 984, 1015, 953, 984, 922, 953, 891, 922, 860, 891, 829, 860, 798,
829, 767, 798, 985, 1016, 954, 985, 923, 954, 861, 892, 830, 861, 799, 830,
986, 1017, 955, 986, 862, 893, 831, 862, 987, 1018, 863, 894, 892, 923, 924,
955, 893, 924, 956, 987, 925, 956, 894, 925, 988, 1019, 957, 988, 926, 957,
895, 926, 989, 1020, 958, 989, 927, 958, 990, 1021, 959, 990, 991, 1022, 0, 0,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_default_iscan_4x4[16]) = {
0, 2, 5, 8, 1, 3, 9, 12, 4, 7, 11, 14, 6, 10, 13, 15,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_col_iscan_4x4[16]) = {
0, 3, 7, 11, 1, 5, 9, 12, 2, 6, 10, 14, 4, 8, 13, 15,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_row_iscan_4x4[16]) = {
0, 1, 3, 5, 2, 4, 6, 9, 7, 8, 11, 13, 10, 12, 14, 15,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_col_iscan_8x8[64]) = {
0, 3, 8, 15, 22, 32, 40, 47, 1, 5, 11, 18, 26, 34, 44, 51,
2, 7, 13, 20, 28, 38, 46, 54, 4, 10, 16, 24, 31, 41, 50, 56,
6, 12, 21, 27, 35, 43, 52, 58, 9, 17, 25, 33, 39, 48, 55, 60,
14, 23, 30, 37, 45, 53, 59, 62, 19, 29, 36, 42, 49, 57, 61, 63,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_row_iscan_8x8[64]) = {
0, 1, 2, 5, 8, 12, 19, 24, 3, 4, 7, 10, 15, 20, 30, 39,
6, 9, 13, 16, 21, 27, 37, 46, 11, 14, 17, 23, 28, 34, 44, 52,
18, 22, 25, 31, 35, 41, 50, 57, 26, 29, 33, 38, 43, 49, 55, 59,
32, 36, 42, 47, 51, 54, 60, 61, 40, 45, 48, 53, 56, 58, 62, 63,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_default_iscan_8x8[64]) = {
0, 2, 5, 9, 14, 22, 31, 37, 1, 4, 8, 13, 19, 26, 38, 44,
3, 6, 10, 17, 24, 30, 42, 49, 7, 11, 15, 21, 29, 36, 47, 53,
12, 16, 20, 27, 34, 43, 52, 57, 18, 23, 28, 35, 41, 48, 56, 60,
25, 32, 39, 45, 50, 55, 59, 62, 33, 40, 46, 51, 54, 58, 61, 63,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_col_iscan_16x16[256]) = {
0, 4, 11, 20, 31, 43, 59, 75, 85, 109, 130, 150, 165, 181, 195, 198,
1, 6, 14, 23, 34, 47, 64, 81, 95, 114, 135, 153, 171, 188, 201, 212,
2, 8, 16, 25, 38, 52, 67, 83, 101, 116, 136, 157, 172, 190, 205, 216,
3, 10, 18, 29, 41, 55, 71, 89, 103, 119, 141, 159, 176, 194, 208, 218,
5, 12, 21, 32, 45, 58, 74, 93, 104, 123, 144, 164, 179, 196, 210, 223,
7, 15, 26, 37, 49, 63, 78, 96, 112, 129, 146, 166, 182, 200, 215, 228,
9, 19, 28, 39, 54, 69, 86, 102, 117, 132, 151, 170, 187, 206, 220, 230,
13, 24, 35, 46, 60, 73, 91, 108, 122, 137, 154, 174, 189, 207, 224, 235,
17, 30, 40, 53, 66, 82, 98, 115, 126, 142, 161, 180, 197, 213, 227, 237,
22, 36, 48, 62, 76, 92, 105, 120, 133, 147, 167, 186, 203, 219, 232, 240,
27, 44, 56, 70, 84, 99, 113, 127, 140, 156, 175, 193, 209, 226, 236, 244,
33, 51, 68, 79, 94, 110, 125, 138, 149, 162, 184, 202, 217, 229, 241, 247,
42, 61, 77, 90, 106, 121, 134, 148, 160, 173, 191, 211, 225, 238, 245, 251,
50, 72, 87, 100, 118, 128, 145, 158, 168, 183, 204, 222, 233, 242, 249, 253,
57, 80, 97, 111, 131, 143, 155, 169, 178, 192, 214, 231, 239, 246, 250, 254,
65, 88, 107, 124, 139, 152, 163, 177, 185, 199, 221, 234, 243, 248, 252, 255,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_row_iscan_16x16[256]) = {
0, 1, 2, 4, 6, 9, 12, 17, 22, 29, 36, 43, 54, 64, 76, 86,
3, 5, 7, 11, 15, 19, 25, 32, 38, 48, 59, 68, 84, 99, 115, 130,
8, 10, 13, 18, 23, 27, 33, 42, 51, 60, 72, 88, 103, 119, 142, 167,
14, 16, 20, 26, 31, 37, 44, 53, 61, 73, 85, 100, 116, 135, 161, 185,
21, 24, 30, 35, 40, 47, 55, 65, 74, 81, 94, 112, 133, 154, 179, 205,
28, 34, 39, 45, 50, 58, 67, 77, 87, 96, 106, 121, 146, 169, 196, 212,
41, 46, 49, 56, 63, 70, 79, 90, 98, 107, 122, 138, 159, 182, 207, 222,
52, 57, 62, 69, 75, 83, 93, 102, 110, 120, 134, 150, 176, 195, 215, 226,
66, 71, 78, 82, 91, 97, 108, 113, 127, 136, 148, 168, 188, 202, 221, 232,
80, 89, 92, 101, 105, 114, 125, 131, 139, 151, 162, 177, 192, 208, 223, 234,
95, 104, 109, 117, 123, 128, 143, 144, 155, 165, 175, 190, 206, 219, 233, 239,
111, 118, 124, 129, 140, 147, 157, 164, 170, 181, 191, 203, 224, 230, 240,
243, 126, 132, 137, 145, 153, 160, 174, 178, 184, 197, 204, 216, 231, 237,
244, 246, 141, 149, 156, 166, 172, 180, 189, 199, 200, 210, 220, 228, 238,
242, 249, 251, 152, 163, 171, 183, 186, 193, 201, 211, 214, 218, 227, 236,
245, 247, 252, 253, 158, 173, 187, 194, 198, 209, 213, 217, 225, 229, 235,
241, 248, 250, 254, 255,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_default_iscan_16x16[256]) = {
0, 2, 5, 9, 17, 24, 36, 44, 55, 72, 88, 104, 128, 143, 166, 179,
1, 4, 8, 13, 20, 30, 40, 54, 66, 79, 96, 113, 141, 154, 178, 196,
3, 7, 11, 18, 25, 33, 46, 57, 71, 86, 101, 119, 148, 164, 186, 201,
6, 12, 16, 23, 31, 39, 53, 64, 78, 92, 110, 127, 153, 169, 193, 208,
10, 14, 19, 28, 37, 47, 58, 67, 84, 98, 114, 133, 161, 176, 198, 214,
15, 21, 26, 34, 43, 52, 65, 77, 91, 106, 120, 140, 165, 185, 205, 221,
22, 27, 32, 41, 48, 60, 73, 85, 99, 116, 130, 151, 175, 190, 211, 225,
29, 35, 42, 49, 59, 69, 81, 95, 108, 125, 139, 155, 182, 197, 217, 229,
38, 45, 51, 61, 68, 80, 93, 105, 118, 134, 150, 168, 191, 207, 223, 234,
50, 56, 63, 74, 83, 94, 109, 117, 129, 147, 163, 177, 199, 213, 228, 238,
62, 70, 76, 87, 97, 107, 122, 131, 145, 159, 172, 188, 210, 222, 235, 242,
75, 82, 90, 102, 112, 124, 138, 146, 157, 173, 187, 202, 219, 230, 240, 245,
89, 100, 111, 123, 132, 142, 156, 167, 180, 189, 203, 216, 231, 237, 246, 250,
103, 115, 126, 136, 149, 162, 171, 183, 194, 204, 215, 224, 236, 241, 248,
252, 121, 135, 144, 158, 170, 181, 192, 200, 209, 218, 227, 233, 243, 244,
251, 254, 137, 152, 160, 174, 184, 195, 206, 212, 220, 226, 232, 239, 247,
249, 253, 255,
};
DECLARE_ALIGNED(16, static const int16_t, vp10_default_iscan_32x32[1024]) = {
0, 2, 5, 10, 17, 25, 38, 47, 62, 83, 101, 121, 145, 170, 193, 204,
210, 219, 229, 233, 245, 257, 275, 299, 342, 356, 377, 405, 455, 471, 495,
527, 1, 4, 8, 15, 22, 30, 45, 58, 74, 92, 112, 133, 158, 184, 203, 215, 222,
228, 234, 237, 256, 274, 298, 317, 355, 376, 404, 426, 470, 494, 526, 551,
3, 7, 12, 18, 28, 36, 52, 64, 82, 102, 118, 142, 164, 189, 208, 217, 224,
231, 235, 238, 273, 297, 316, 329, 375, 403, 425, 440, 493, 525, 550, 567,
6, 11, 16, 23, 31, 43, 60, 73, 90, 109, 126, 150, 173, 196, 211, 220, 226,
232, 236, 239, 296, 315, 328, 335, 402, 424, 439, 447, 524, 549, 566, 575,
9, 14, 19, 29, 37, 50, 65, 78, 95, 116, 134, 157, 179, 201, 214, 223, 244,
255, 272, 295, 341, 354, 374, 401, 454, 469, 492, 523, 582, 596, 617, 645,
13, 20, 26, 35, 44, 54, 72, 85, 105, 123, 140, 163, 182, 205, 216, 225,
254, 271, 294, 314, 353, 373, 400, 423, 468, 491, 522, 548, 595, 616, 644,
666, 21, 27, 33, 42, 53, 63, 80, 94, 113, 132, 151, 172, 190, 209, 218, 227,
270, 293, 313, 327, 372, 399, 422, 438, 490, 521, 547, 565, 615, 643, 665,
680, 24, 32, 39, 48, 57, 71, 88, 104, 120, 139, 159, 178, 197, 212, 221, 230,
292, 312, 326, 334, 398, 421, 437, 446, 520, 546, 564, 574, 642, 664, 679,
687, 34, 40, 46, 56, 68, 81, 96, 111, 130, 147, 167, 186, 243, 253, 269, 291,
340, 352, 371, 397, 453, 467, 489, 519, 581, 594, 614, 641, 693, 705, 723,
747, 41, 49, 55, 67, 77, 91, 107, 124, 138, 161, 177, 194, 252, 268, 290,
311, 351, 370, 396, 420, 466, 488, 518, 545, 593, 613, 640, 663, 704, 722,
746, 765, 51, 59, 66, 76, 89, 99, 119, 131, 149, 168, 181, 200, 267, 289,
310, 325, 369, 395, 419, 436, 487, 517, 544, 563, 612, 639, 662, 678, 721,
745, 764, 777, 61, 69, 75, 87, 100, 114, 129, 144, 162, 180, 191, 207, 288,
309, 324, 333, 394, 418, 435, 445, 516, 543, 562, 573, 638, 661, 677, 686,
744, 763, 776, 783, 70, 79, 86, 97, 108, 122, 137, 155, 242, 251, 266, 287,
339, 350, 368, 393, 452, 465, 486, 515, 580, 592, 611, 637, 692, 703, 720,
743, 788, 798, 813, 833, 84, 93, 103, 110, 125, 141, 154, 171, 250, 265, 286,
308, 349, 367, 392, 417, 464, 485, 514, 542, 591, 610, 636, 660, 702, 719,
742, 762, 797, 812, 832, 848, 98, 106, 115, 127, 143, 156, 169, 185, 264,
285, 307, 323, 366, 391, 416, 434, 484, 513, 541, 561, 609, 635, 659, 676,
718, 741, 761, 775, 811, 831, 847, 858, 117, 128, 136, 148, 160, 175, 188,
198, 284, 306, 322, 332, 390, 415, 433, 444, 512, 540, 560, 572, 634, 658,
675, 685, 740, 760, 774, 782, 830, 846, 857, 863, 135, 146, 152, 165, 241,
249, 263, 283, 338, 348, 365, 389, 451, 463, 483, 511, 579, 590, 608, 633,
691, 701, 717, 739, 787, 796, 810, 829, 867, 875, 887, 903, 153, 166, 174,
183, 248, 262, 282, 305, 347, 364, 388, 414, 462, 482, 510, 539, 589, 607,
632, 657, 700, 716, 738, 759, 795, 809, 828, 845, 874, 886, 902, 915, 176,
187, 195, 202, 261, 281, 304, 321, 363, 387, 413, 432, 481, 509, 538, 559,
606, 631, 656, 674, 715, 737, 758, 773, 808, 827, 844, 856, 885, 901, 914,
923, 192, 199, 206, 213, 280, 303, 320, 331, 386, 412, 431, 443, 508, 537,
558, 571, 630, 655, 673, 684, 736, 757, 772, 781, 826, 843, 855, 862, 900,
913, 922, 927, 240, 247, 260, 279, 337, 346, 362, 385, 450, 461, 480, 507,
578, 588, 605, 629, 690, 699, 714, 735, 786, 794, 807, 825, 866, 873, 884,
899, 930, 936, 945, 957, 246, 259, 278, 302, 345, 361, 384, 411, 460, 479,
506, 536, 587, 604, 628, 654, 698, 713, 734, 756, 793, 806, 824, 842, 872,
883, 898, 912, 935, 944, 956, 966, 258, 277, 301, 319, 360, 383, 410, 430,
478, 505, 535, 557, 603, 627, 653, 672, 712, 733, 755, 771, 805, 823, 841,
854, 882, 897, 911, 921, 943, 955, 965, 972, 276, 300, 318, 330, 382, 409,
429, 442, 504, 534, 556, 570, 626, 652, 671, 683, 732, 754, 770, 780, 822,
840, 853, 861, 896, 910, 920, 926, 954, 964, 971, 975, 336, 344, 359, 381,
449, 459, 477, 503, 577, 586, 602, 625, 689, 697, 711, 731, 785, 792, 804,
821, 865, 871, 881, 895, 929, 934, 942, 953, 977, 981, 987, 995, 343, 358,
380, 408, 458, 476, 502, 533, 585, 601, 624, 651, 696, 710, 730, 753, 791,
803, 820, 839, 870, 880, 894, 909, 933, 941, 952, 963, 980, 986, 994, 1001,
357, 379, 407, 428, 475, 501, 532, 555, 600, 623, 650, 670, 709, 729, 752,
769, 802, 819, 838, 852, 879, 893, 908, 919, 940, 951, 962, 970, 985, 993,
1000, 1005, 378, 406, 427, 441, 500, 531, 554, 569, 622, 649, 669, 682, 728,
751, 768, 779, 818, 837, 851, 860, 892, 907, 918, 925, 950, 961, 969, 974,
992, 999, 1004, 1007, 448, 457, 474, 499, 576, 584, 599, 621, 688, 695, 708,
727, 784, 790, 801, 817, 864, 869, 878, 891, 928, 932, 939, 949, 976, 979,
984, 991, 1008, 1010, 1013, 1017, 456, 473, 498, 530, 583, 598, 620, 648,
694, 707, 726, 750, 789, 800, 816, 836, 868, 877, 890, 906, 931, 938, 948,
960, 978, 983, 990, 998, 1009, 1012, 1016, 1020, 472, 497, 529, 553, 597,
619, 647, 668, 706, 725, 749, 767, 799, 815, 835, 850, 876, 889, 905, 917,
937, 947, 959, 968, 982, 989, 997, 1003, 1011, 1015, 1019, 1022, 496, 528,
552, 568, 618, 646, 667, 681, 724, 748, 766, 778, 814, 834, 849, 859, 888,
904, 916, 924, 946, 958, 967, 973, 988, 996, 1002, 1006, 1014, 1018, 1021,
1023,
};
const scan_order vp10_scan_orders[TX_SIZES][TX_TYPES] = {
{ // TX_4X4
{default_scan_4x4, vp10_default_iscan_4x4, default_scan_4x4_neighbors},
{row_scan_4x4, vp10_row_iscan_4x4, row_scan_4x4_neighbors},
{col_scan_4x4, vp10_col_iscan_4x4, col_scan_4x4_neighbors},
{default_scan_4x4, vp10_default_iscan_4x4, default_scan_4x4_neighbors}
}, { // TX_8X8
{default_scan_8x8, vp10_default_iscan_8x8, default_scan_8x8_neighbors},
{row_scan_8x8, vp10_row_iscan_8x8, row_scan_8x8_neighbors},
{col_scan_8x8, vp10_col_iscan_8x8, col_scan_8x8_neighbors},
{default_scan_8x8, vp10_default_iscan_8x8, default_scan_8x8_neighbors}
}, { // TX_16X16
{default_scan_16x16, vp10_default_iscan_16x16, default_scan_16x16_neighbors},
{row_scan_16x16, vp10_row_iscan_16x16, row_scan_16x16_neighbors},
{col_scan_16x16, vp10_col_iscan_16x16, col_scan_16x16_neighbors},
{default_scan_16x16, vp10_default_iscan_16x16, default_scan_16x16_neighbors}
}, { // TX_32X32
{default_scan_32x32, vp10_default_iscan_32x32, default_scan_32x32_neighbors},
{default_scan_32x32, vp10_default_iscan_32x32, default_scan_32x32_neighbors},
{default_scan_32x32, vp10_default_iscan_32x32, default_scan_32x32_neighbors},
{default_scan_32x32, vp10_default_iscan_32x32, default_scan_32x32_neighbors},
}
};

48
vp10/common/scan.h Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2013 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_SCAN_H_
#define VP10_COMMON_SCAN_H_
#include "vpx/vpx_integer.h"
#include "vpx_ports/mem.h"
#include "vp10/common/enums.h"
#include "vp10/common/blockd.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_NEIGHBORS 2
typedef struct {
const int16_t *scan;
const int16_t *iscan;
const int16_t *neighbors;
} scan_order;
extern const scan_order vp10_scan_orders[TX_SIZES][TX_TYPES];
static INLINE int get_coef_context(const int16_t *neighbors,
const uint8_t *token_cache, int c) {
return (1 + token_cache[neighbors[MAX_NEIGHBORS * c + 0]] +
token_cache[neighbors[MAX_NEIGHBORS * c + 1]]) >> 1;
}
static INLINE const scan_order *get_scan(TX_SIZE tx_size, TX_TYPE tx_type) {
return &vp10_scan_orders[tx_size][tx_type];
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_SCAN_H_

63
vp10/common/seg_common.c Normal file
View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "vp10/common/blockd.h"
#include "vp10/common/loopfilter.h"
#include "vp10/common/seg_common.h"
#include "vp10/common/quant_common.h"
static const int seg_feature_data_signed[SEG_LVL_MAX] = { 1, 1, 0, 0 };
static const int seg_feature_data_max[SEG_LVL_MAX] = {
MAXQ, MAX_LOOP_FILTER, 3, 0 };
// These functions provide access to new segment level features.
// Eventually these function may be "optimized out" but for the moment,
// the coding mechanism is still subject to change so these provide a
// convenient single point of change.
void vp10_clearall_segfeatures(struct segmentation *seg) {
vp10_zero(seg->feature_data);
vp10_zero(seg->feature_mask);
}
void vp10_enable_segfeature(struct segmentation *seg, int segment_id,
SEG_LVL_FEATURES feature_id) {
seg->feature_mask[segment_id] |= 1 << feature_id;
}
int vp10_seg_feature_data_max(SEG_LVL_FEATURES feature_id) {
return seg_feature_data_max[feature_id];
}
int vp10_is_segfeature_signed(SEG_LVL_FEATURES feature_id) {
return seg_feature_data_signed[feature_id];
}
void vp10_set_segdata(struct segmentation *seg, int segment_id,
SEG_LVL_FEATURES feature_id, int seg_data) {
assert(seg_data <= seg_feature_data_max[feature_id]);
if (seg_data < 0) {
assert(seg_feature_data_signed[feature_id]);
assert(-seg_data <= seg_feature_data_max[feature_id]);
}
seg->feature_data[segment_id][feature_id] = seg_data;
}
const vpx_tree_index vp10_segment_tree[TREE_SIZE(MAX_SEGMENTS)] = {
2, 4, 6, 8, 10, 12,
0, -1, -2, -3, -4, -5, -6, -7
};
// TBD? Functions to read and write segment data with range / validity checking

86
vp10/common/seg_common.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* 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.
*/
#ifndef VP10_COMMON_SEG_COMMON_H_
#define VP10_COMMON_SEG_COMMON_H_
#include "vpx_dsp/prob.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SEGMENT_DELTADATA 0
#define SEGMENT_ABSDATA 1
#define MAX_SEGMENTS 8
#define SEG_TREE_PROBS (MAX_SEGMENTS-1)
#define PREDICTION_PROBS 3
// Segment level features.
typedef enum {
SEG_LVL_ALT_Q = 0, // Use alternate Quantizer ....
SEG_LVL_ALT_LF = 1, // Use alternate loop filter value...
SEG_LVL_REF_FRAME = 2, // Optional Segment reference frame
SEG_LVL_SKIP = 3, // Optional Segment (0,0) + skip mode
SEG_LVL_MAX = 4 // Number of features supported
} SEG_LVL_FEATURES;
struct segmentation {
uint8_t enabled;
uint8_t update_map;
uint8_t update_data;
uint8_t abs_delta;
uint8_t temporal_update;
vpx_prob tree_probs[SEG_TREE_PROBS];
vpx_prob pred_probs[PREDICTION_PROBS];
int16_t feature_data[MAX_SEGMENTS][SEG_LVL_MAX];
unsigned int feature_mask[MAX_SEGMENTS];
};
static INLINE int segfeature_active(const struct segmentation *seg,
int segment_id,
SEG_LVL_FEATURES feature_id) {
return seg->enabled &&
(seg->feature_mask[segment_id] & (1 << feature_id));
}
void vp10_clearall_segfeatures(struct segmentation *seg);
void vp10_enable_segfeature(struct segmentation *seg,
int segment_id,
SEG_LVL_FEATURES feature_id);
int vp10_seg_feature_data_max(SEG_LVL_FEATURES feature_id);
int vp10_is_segfeature_signed(SEG_LVL_FEATURES feature_id);
void vp10_set_segdata(struct segmentation *seg,
int segment_id,
SEG_LVL_FEATURES feature_id,
int seg_data);
static INLINE int get_segdata(const struct segmentation *seg, int segment_id,
SEG_LVL_FEATURES feature_id) {
return seg->feature_data[segment_id][feature_id];
}
extern const vpx_tree_index vp10_segment_tree[TREE_SIZE(MAX_SEGMENTS)];
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_SEG_COMMON_H_

120
vp10/common/textblit.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdlib.h>
#include "vp10/common/textblit.h"
static const int font[] = {
0x0, 0x5C00, 0x8020, 0xAFABEA, 0xD7EC0, 0x1111111, 0x1855740, 0x18000,
0x45C0, 0x74400, 0x51140, 0x23880, 0xC4000, 0x21080, 0x80000, 0x111110,
0xE9D72E, 0x87E40, 0x12AD732, 0xAAD62A, 0x4F94C4, 0x4D6B7, 0x456AA,
0x3E8423, 0xAAD6AA, 0xAAD6A2, 0x2800, 0x2A00, 0x8A880, 0x52940, 0x22A20,
0x15422, 0x6AD62E, 0x1E4A53E, 0xAAD6BF, 0x8C62E, 0xE8C63F, 0x118D6BF,
0x1094BF, 0xCAC62E, 0x1F2109F, 0x118FE31, 0xF8C628, 0x8A89F, 0x108421F,
0x1F1105F, 0x1F4105F, 0xE8C62E, 0x2294BF, 0x164C62E, 0x12694BF, 0x8AD6A2,
0x10FC21, 0x1F8421F, 0x744107, 0xF8220F, 0x1151151, 0x117041, 0x119D731,
0x47E0, 0x1041041, 0xFC400, 0x10440, 0x1084210, 0x820
};
static void plot(int x, int y, unsigned char *image, int pitch) {
image[x + y * pitch] ^= 255;
}
void vp10_blit_text(const char *msg, unsigned char *address, const int pitch) {
int letter_bitmap;
unsigned char *output_pos = address;
int colpos = 0;
while (msg[colpos] != 0) {
char letter = msg[colpos];
int fontcol, fontrow;
if (letter <= 'Z' && letter >= ' ')
letter_bitmap = font[letter - ' '];
else if (letter <= 'z' && letter >= 'a')
letter_bitmap = font[letter - 'a' + 'A' - ' '];
else
letter_bitmap = font[0];
for (fontcol = 6; fontcol >= 0; fontcol--)
for (fontrow = 0; fontrow < 5; fontrow++)
output_pos[fontrow * pitch + fontcol] =
((letter_bitmap >> (fontcol * 5)) & (1 << fontrow) ? 255 : 0);
output_pos += 7;
colpos++;
}
}
/* Bresenham line algorithm */
void vp10_blit_line(int x0, int x1, int y0, int y1, unsigned char *image,
int pitch) {
int steep = abs(y1 - y0) > abs(x1 - x0);
int deltax, deltay;
int error, ystep, y, x;
if (steep) {
int t;
t = x0;
x0 = y0;
y0 = t;
t = x1;
x1 = y1;
y1 = t;
}
if (x0 > x1) {
int t;
t = x0;
x0 = x1;
x1 = t;
t = y0;
y0 = y1;
y1 = t;
}
deltax = x1 - x0;
deltay = abs(y1 - y0);
error = deltax / 2;
y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
if (steep) {
for (x = x0; x <= x1; x++) {
plot(y, x, image, pitch);
error = error - deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
} else {
for (x = x0; x <= x1; x++) {
plot(x, y, image, pitch);
error = error - deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
}
}

27
vp10/common/textblit.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_TEXTBLIT_H_
#define VP10_COMMON_TEXTBLIT_H_
#ifdef __cplusplus
extern "C" {
#endif
void vp10_blit_text(const char *msg, unsigned char *address, int pitch);
void vp10_blit_line(int x0, int x1, int y0, int y1, unsigned char *image,
int pitch);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_TEXTBLIT_H_

437
vp10/common/thread_common.c Normal file
View File

@@ -0,0 +1,437 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_config.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/thread_common.h"
#include "vp10/common/reconinter.h"
#include "vp10/common/loopfilter.h"
#if CONFIG_MULTITHREAD
static INLINE void mutex_lock(pthread_mutex_t *const mutex) {
const int kMaxTryLocks = 4000;
int locked = 0;
int i;
for (i = 0; i < kMaxTryLocks; ++i) {
if (!pthread_mutex_trylock(mutex)) {
locked = 1;
break;
}
}
if (!locked)
pthread_mutex_lock(mutex);
}
#endif // CONFIG_MULTITHREAD
static INLINE void sync_read(VP9LfSync *const lf_sync, int r, int c) {
#if CONFIG_MULTITHREAD
const int nsync = lf_sync->sync_range;
if (r && !(c & (nsync - 1))) {
pthread_mutex_t *const mutex = &lf_sync->mutex_[r - 1];
mutex_lock(mutex);
while (c > lf_sync->cur_sb_col[r - 1] - nsync) {
pthread_cond_wait(&lf_sync->cond_[r - 1], mutex);
}
pthread_mutex_unlock(mutex);
}
#else
(void)lf_sync;
(void)r;
(void)c;
#endif // CONFIG_MULTITHREAD
}
static INLINE void sync_write(VP9LfSync *const lf_sync, int r, int c,
const int sb_cols) {
#if CONFIG_MULTITHREAD
const int nsync = lf_sync->sync_range;
int cur;
// Only signal when there are enough filtered SB for next row to run.
int sig = 1;
if (c < sb_cols - 1) {
cur = c;
if (c % nsync)
sig = 0;
} else {
cur = sb_cols + nsync;
}
if (sig) {
mutex_lock(&lf_sync->mutex_[r]);
lf_sync->cur_sb_col[r] = cur;
pthread_cond_signal(&lf_sync->cond_[r]);
pthread_mutex_unlock(&lf_sync->mutex_[r]);
}
#else
(void)lf_sync;
(void)r;
(void)c;
(void)sb_cols;
#endif // CONFIG_MULTITHREAD
}
// Implement row loopfiltering for each thread.
static INLINE
void thread_loop_filter_rows(const YV12_BUFFER_CONFIG *const frame_buffer,
VP10_COMMON *const cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int start, int stop, int y_only,
VP9LfSync *const lf_sync) {
const int num_planes = y_only ? 1 : MAX_MB_PLANE;
const int sb_cols = mi_cols_aligned_to_sb(cm->mi_cols) >> MI_BLOCK_SIZE_LOG2;
int mi_row, mi_col;
enum lf_path path;
if (y_only)
path = LF_PATH_444;
else if (planes[1].subsampling_y == 1 && planes[1].subsampling_x == 1)
path = LF_PATH_420;
else if (planes[1].subsampling_y == 0 && planes[1].subsampling_x == 0)
path = LF_PATH_444;
else
path = LF_PATH_SLOW;
for (mi_row = start; mi_row < stop;
mi_row += lf_sync->num_workers * MI_BLOCK_SIZE) {
MODE_INFO **const mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) {
const int r = mi_row >> MI_BLOCK_SIZE_LOG2;
const int c = mi_col >> MI_BLOCK_SIZE_LOG2;
LOOP_FILTER_MASK lfm;
int plane;
sync_read(lf_sync, r, c);
vp10_setup_dst_planes(planes, frame_buffer, mi_row, mi_col);
// TODO(JBB): Make setup_mask work for non 420.
vp10_setup_mask(cm, mi_row, mi_col, mi + mi_col, cm->mi_stride,
&lfm);
vp10_filter_block_plane_ss00(cm, &planes[0], mi_row, &lfm);
for (plane = 1; plane < num_planes; ++plane) {
switch (path) {
case LF_PATH_420:
vp10_filter_block_plane_ss11(cm, &planes[plane], mi_row, &lfm);
break;
case LF_PATH_444:
vp10_filter_block_plane_ss00(cm, &planes[plane], mi_row, &lfm);
break;
case LF_PATH_SLOW:
vp10_filter_block_plane_non420(cm, &planes[plane], mi + mi_col,
mi_row, mi_col);
break;
}
}
sync_write(lf_sync, r, c, sb_cols);
}
}
}
// Row-based multi-threaded loopfilter hook
static int loop_filter_row_worker(VP9LfSync *const lf_sync,
LFWorkerData *const lf_data) {
thread_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
lf_data->start, lf_data->stop, lf_data->y_only,
lf_sync);
return 1;
}
static void loop_filter_rows_mt(YV12_BUFFER_CONFIG *frame,
VP10_COMMON *cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int start, int stop, int y_only,
VPxWorker *workers, int nworkers,
VP9LfSync *lf_sync) {
const VPxWorkerInterface *const winterface = vpx_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;
// Decoder may allocate more threads than number of tiles based on user's
// input.
const int tile_cols = 1 << cm->log2_tile_cols;
const int num_workers = VPXMIN(nworkers, tile_cols);
int i;
if (!lf_sync->sync_range || sb_rows != lf_sync->rows ||
num_workers > lf_sync->num_workers) {
vp10_loop_filter_dealloc(lf_sync);
vp10_loop_filter_alloc(lf_sync, cm, sb_rows, cm->width, num_workers);
}
// Initialize cur_sb_col to -1 for all SB rows.
memset(lf_sync->cur_sb_col, -1, sizeof(*lf_sync->cur_sb_col) * sb_rows);
// Set up loopfilter thread data.
// The decoder is capping num_workers because it has been observed that using
// more threads on the loopfilter than there are cores will hurt performance
// on Android. This is because the system will only schedule the tile decode
// workers on cores equal to the number of tile columns. Then if the decoder
// tries to use more threads for the loopfilter, it will hurt performance
// because of contention. If the multithreading code changes in the future
// then the number of workers used by the loopfilter should be revisited.
for (i = 0; i < num_workers; ++i) {
VPxWorker *const worker = &workers[i];
LFWorkerData *const lf_data = &lf_sync->lfdata[i];
worker->hook = (VPxWorkerHook)loop_filter_row_worker;
worker->data1 = lf_sync;
worker->data2 = lf_data;
// Loopfilter data
vp10_loop_filter_data_reset(lf_data, frame, cm, planes);
lf_data->start = start + i * MI_BLOCK_SIZE;
lf_data->stop = stop;
lf_data->y_only = y_only;
// Start loopfiltering
if (i == num_workers - 1) {
winterface->execute(worker);
} else {
winterface->launch(worker);
}
}
// Wait till all rows are finished
for (i = 0; i < num_workers; ++i) {
winterface->sync(&workers[i]);
}
}
void vp10_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame,
VP10_COMMON *cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int frame_filter_level,
int y_only, int partial_frame,
VPxWorker *workers, int num_workers,
VP9LfSync *lf_sync) {
int start_mi_row, end_mi_row, mi_rows_to_filter;
if (!frame_filter_level) return;
start_mi_row = 0;
mi_rows_to_filter = cm->mi_rows;
if (partial_frame && cm->mi_rows > 8) {
start_mi_row = cm->mi_rows >> 1;
start_mi_row &= 0xfffffff8;
mi_rows_to_filter = VPXMAX(cm->mi_rows / 8, 8);
}
end_mi_row = start_mi_row + mi_rows_to_filter;
vp10_loop_filter_frame_init(cm, frame_filter_level);
loop_filter_rows_mt(frame, cm, planes, start_mi_row, end_mi_row,
y_only, workers, num_workers, lf_sync);
}
// Set up nsync by width.
static INLINE int get_sync_range(int width) {
// nsync numbers are picked by testing. For example, for 4k
// video, using 4 gives best performance.
if (width < 640)
return 1;
else if (width <= 1280)
return 2;
else if (width <= 4096)
return 4;
else
return 8;
}
// Allocate memory for lf row synchronization
void vp10_loop_filter_alloc(VP9LfSync *lf_sync, VP10_COMMON *cm, int rows,
int width, int num_workers) {
lf_sync->rows = rows;
#if CONFIG_MULTITHREAD
{
int i;
CHECK_MEM_ERROR(cm, lf_sync->mutex_,
vpx_malloc(sizeof(*lf_sync->mutex_) * rows));
if (lf_sync->mutex_) {
for (i = 0; i < rows; ++i) {
pthread_mutex_init(&lf_sync->mutex_[i], NULL);
}
}
CHECK_MEM_ERROR(cm, lf_sync->cond_,
vpx_malloc(sizeof(*lf_sync->cond_) * rows));
if (lf_sync->cond_) {
for (i = 0; i < rows; ++i) {
pthread_cond_init(&lf_sync->cond_[i], NULL);
}
}
}
#endif // CONFIG_MULTITHREAD
CHECK_MEM_ERROR(cm, lf_sync->lfdata,
vpx_malloc(num_workers * sizeof(*lf_sync->lfdata)));
lf_sync->num_workers = num_workers;
CHECK_MEM_ERROR(cm, lf_sync->cur_sb_col,
vpx_malloc(sizeof(*lf_sync->cur_sb_col) * rows));
// Set up nsync.
lf_sync->sync_range = get_sync_range(width);
}
// Deallocate lf synchronization related mutex and data
void vp10_loop_filter_dealloc(VP9LfSync *lf_sync) {
if (lf_sync != NULL) {
#if CONFIG_MULTITHREAD
int i;
if (lf_sync->mutex_ != NULL) {
for (i = 0; i < lf_sync->rows; ++i) {
pthread_mutex_destroy(&lf_sync->mutex_[i]);
}
vpx_free(lf_sync->mutex_);
}
if (lf_sync->cond_ != NULL) {
for (i = 0; i < lf_sync->rows; ++i) {
pthread_cond_destroy(&lf_sync->cond_[i]);
}
vpx_free(lf_sync->cond_);
}
#endif // CONFIG_MULTITHREAD
vpx_free(lf_sync->lfdata);
vpx_free(lf_sync->cur_sb_col);
// clear the structure as the source of this call may be a resize in which
// case this call will be followed by an _alloc() which may fail.
vp10_zero(*lf_sync);
}
}
// Accumulate frame counts.
void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts,
int is_dec) {
int i, j, k, l, m;
for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
for (j = 0; j < INTRA_MODES; j++)
cm->counts.y_mode[i][j] += counts->y_mode[i][j];
for (i = 0; i < INTRA_MODES; i++)
for (j = 0; j < INTRA_MODES; j++)
cm->counts.uv_mode[i][j] += counts->uv_mode[i][j];
for (i = 0; i < PARTITION_CONTEXTS; i++)
for (j = 0; j < PARTITION_TYPES; j++)
cm->counts.partition[i][j] += counts->partition[i][j];
if (is_dec) {
int n;
for (i = 0; i < TX_SIZES; i++)
for (j = 0; j < PLANE_TYPES; j++)
for (k = 0; k < REF_TYPES; k++)
for (l = 0; l < COEF_BANDS; l++)
for (m = 0; m < COEFF_CONTEXTS; m++) {
cm->counts.eob_branch[i][j][k][l][m] +=
counts->eob_branch[i][j][k][l][m];
for (n = 0; n < UNCONSTRAINED_NODES + 1; n++)
cm->counts.coef[i][j][k][l][m][n] +=
counts->coef[i][j][k][l][m][n];
}
} else {
for (i = 0; i < TX_SIZES; i++)
for (j = 0; j < PLANE_TYPES; j++)
for (k = 0; k < REF_TYPES; k++)
for (l = 0; l < COEF_BANDS; l++)
for (m = 0; m < COEFF_CONTEXTS; m++)
cm->counts.eob_branch[i][j][k][l][m] +=
counts->eob_branch[i][j][k][l][m];
// In the encoder, cm->counts.coef is only updated at frame
// level, so not need to accumulate it here.
// for (n = 0; n < UNCONSTRAINED_NODES + 1; n++)
// cm->counts.coef[i][j][k][l][m][n] +=
// counts->coef[i][j][k][l][m][n];
}
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
for (j = 0; j < SWITCHABLE_FILTERS; j++)
cm->counts.switchable_interp[i][j] += counts->switchable_interp[i][j];
for (i = 0; i < INTER_MODE_CONTEXTS; i++)
for (j = 0; j < INTER_MODES; j++)
cm->counts.inter_mode[i][j] += counts->inter_mode[i][j];
for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
for (j = 0; j < 2; j++)
cm->counts.intra_inter[i][j] += counts->intra_inter[i][j];
for (i = 0; i < COMP_INTER_CONTEXTS; i++)
for (j = 0; j < 2; j++)
cm->counts.comp_inter[i][j] += counts->comp_inter[i][j];
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
cm->counts.single_ref[i][j][k] += counts->single_ref[i][j][k];
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
cm->counts.comp_ref[i][j] += counts->comp_ref[i][j];
for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
for (j = 0; j < TX_SIZES; j++)
cm->counts.tx.p32x32[i][j] += counts->tx.p32x32[i][j];
for (j = 0; j < TX_SIZES - 1; j++)
cm->counts.tx.p16x16[i][j] += counts->tx.p16x16[i][j];
for (j = 0; j < TX_SIZES - 2; j++)
cm->counts.tx.p8x8[i][j] += counts->tx.p8x8[i][j];
}
for (i = 0; i < TX_SIZES; i++)
cm->counts.tx.tx_totals[i] += counts->tx.tx_totals[i];
for (i = 0; i < SKIP_CONTEXTS; i++)
for (j = 0; j < 2; j++)
cm->counts.skip[i][j] += counts->skip[i][j];
for (i = 0; i < MV_JOINTS; i++)
cm->counts.mv.joints[i] += counts->mv.joints[i];
for (k = 0; k < 2; k++) {
nmv_component_counts *comps = &cm->counts.mv.comps[k];
nmv_component_counts *comps_t = &counts->mv.comps[k];
for (i = 0; i < 2; i++) {
comps->sign[i] += comps_t->sign[i];
comps->class0_hp[i] += comps_t->class0_hp[i];
comps->hp[i] += comps_t->hp[i];
}
for (i = 0; i < MV_CLASSES; i++)
comps->classes[i] += comps_t->classes[i];
for (i = 0; i < CLASS0_SIZE; i++) {
comps->class0[i] += comps_t->class0[i];
for (j = 0; j < MV_FP_SIZE; j++)
comps->class0_fp[i][j] += comps_t->class0_fp[i][j];
}
for (i = 0; i < MV_OFFSET_BITS; i++)
for (j = 0; j < 2; j++)
comps->bits[i][j] += comps_t->bits[i][j];
for (i = 0; i < MV_FP_SIZE; i++)
comps->fp[i] += comps_t->fp[i];
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_LOOPFILTER_THREAD_H_
#define VP10_COMMON_LOOPFILTER_THREAD_H_
#include "./vpx_config.h"
#include "vp10/common/loopfilter.h"
#include "vpx_util/vpx_thread.h"
struct VP10Common;
struct FRAME_COUNTS;
// Loopfilter row synchronization
typedef struct VP9LfSyncData {
#if CONFIG_MULTITHREAD
pthread_mutex_t *mutex_;
pthread_cond_t *cond_;
#endif
// Allocate memory to store the loop-filtered superblock index in each row.
int *cur_sb_col;
// The optimal sync_range for different resolution and platform should be
// determined by testing. Currently, it is chosen to be a power-of-2 number.
int sync_range;
int rows;
// Row-based parallel loopfilter data
LFWorkerData *lfdata;
int num_workers;
} VP9LfSync;
// Allocate memory for loopfilter row synchronization.
void vp10_loop_filter_alloc(VP9LfSync *lf_sync, struct VP10Common *cm, int rows,
int width, int num_workers);
// Deallocate loopfilter synchronization related mutex and data.
void vp10_loop_filter_dealloc(VP9LfSync *lf_sync);
// Multi-threaded loopfilter that uses the tile threads.
void vp10_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame,
struct VP10Common *cm,
struct macroblockd_plane planes[MAX_MB_PLANE],
int frame_filter_level,
int y_only, int partial_frame,
VPxWorker *workers, int num_workers,
VP9LfSync *lf_sync);
void vp10_accumulate_frame_counts(struct VP10Common *cm,
struct FRAME_COUNTS *counts, int is_dec);
#endif // VP10_COMMON_LOOPFILTER_THREAD_H_

59
vp10/common/tile_common.c Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp10/common/tile_common.h"
#include "vp10/common/onyxc_int.h"
#include "vpx_dsp/vpx_dsp_common.h"
#define MIN_TILE_WIDTH_B64 4
#define MAX_TILE_WIDTH_B64 64
static int get_tile_offset(int idx, int mis, int log2) {
const int sb_cols = mi_cols_aligned_to_sb(mis) >> MI_BLOCK_SIZE_LOG2;
const int offset = ((idx * sb_cols) >> log2) << MI_BLOCK_SIZE_LOG2;
return VPXMIN(offset, mis);
}
void vp10_tile_set_row(TileInfo *tile, const VP10_COMMON *cm, int row) {
tile->mi_row_start = get_tile_offset(row, cm->mi_rows, cm->log2_tile_rows);
tile->mi_row_end = get_tile_offset(row + 1, cm->mi_rows, cm->log2_tile_rows);
}
void vp10_tile_set_col(TileInfo *tile, const VP10_COMMON *cm, int col) {
tile->mi_col_start = get_tile_offset(col, cm->mi_cols, cm->log2_tile_cols);
tile->mi_col_end = get_tile_offset(col + 1, cm->mi_cols, cm->log2_tile_cols);
}
void vp10_tile_init(TileInfo *tile, const VP10_COMMON *cm, int row, int col) {
vp10_tile_set_row(tile, cm, row);
vp10_tile_set_col(tile, cm, col);
}
static int get_min_log2_tile_cols(const int sb64_cols) {
int min_log2 = 0;
while ((MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols)
++min_log2;
return min_log2;
}
static int get_max_log2_tile_cols(const int sb64_cols) {
int max_log2 = 1;
while ((sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64)
++max_log2;
return max_log2 - 1;
}
void vp10_get_tile_n_bits(int mi_cols,
int *min_log2_tile_cols, int *max_log2_tile_cols) {
const int sb64_cols = mi_cols_aligned_to_sb(mi_cols) >> MI_BLOCK_SIZE_LOG2;
*min_log2_tile_cols = get_min_log2_tile_cols(sb64_cols);
*max_log2_tile_cols = get_max_log2_tile_cols(sb64_cols);
assert(*min_log2_tile_cols <= *max_log2_tile_cols);
}

40
vp10/common/tile_common.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP10_COMMON_TILE_COMMON_H_
#define VP10_COMMON_TILE_COMMON_H_
#ifdef __cplusplus
extern "C" {
#endif
struct VP10Common;
typedef struct TileInfo {
int mi_row_start, mi_row_end;
int mi_col_start, mi_col_end;
} TileInfo;
// initializes 'tile->mi_(row|col)_(start|end)' for (row, col) based on
// 'cm->log2_tile_(rows|cols)' & 'cm->mi_(rows|cols)'
void vp10_tile_init(TileInfo *tile, const struct VP10Common *cm,
int row, int col);
void vp10_tile_set_row(TileInfo *tile, const struct VP10Common *cm, int row);
void vp10_tile_set_col(TileInfo *tile, const struct VP10Common *cm, int col);
void vp10_get_tile_n_bits(int mi_cols,
int *min_log2_tile_cols, int *max_log2_tile_cols);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VP10_COMMON_TILE_COMMON_H_

19
vp10/common/vp10_rtcd.c Normal file
View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2011 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 "./vpx_config.h"
#define RTCD_C
#include "./vp10_rtcd.h"
#include "vpx_ports/vpx_once.h"
void vp10_rtcd() {
// TODO(JBB): Remove this once, by insuring that both the encoder and
// decoder setup functions are protected by once();
once(setup_rtcd_internal);
}

View File

@@ -0,0 +1,343 @@
sub vp10_common_forward_decls() {
print <<EOF
/*
* VP10
*/
#include "vpx/vpx_integer.h"
#include "vp10/common/common.h"
#include "vp10/common/enums.h"
struct macroblockd;
/* Encoder forward decls */
struct macroblock;
struct vp9_variance_vtable;
struct search_site_config;
struct mv;
union int_mv;
struct yv12_buffer_config;
EOF
}
forward_decls qw/vp10_common_forward_decls/;
# x86inc.asm had specific constraints. break it out so it's easy to disable.
# zero all the variables to avoid tricky else conditions.
$mmx_x86inc = $sse_x86inc = $sse2_x86inc = $ssse3_x86inc = $avx_x86inc =
$avx2_x86inc = '';
$mmx_x86_64_x86inc = $sse_x86_64_x86inc = $sse2_x86_64_x86inc =
$ssse3_x86_64_x86inc = $avx_x86_64_x86inc = $avx2_x86_64_x86inc = '';
if (vpx_config("CONFIG_USE_X86INC") eq "yes") {
$mmx_x86inc = 'mmx';
$sse_x86inc = 'sse';
$sse2_x86inc = 'sse2';
$ssse3_x86inc = 'ssse3';
$avx_x86inc = 'avx';
$avx2_x86inc = 'avx2';
if ($opts{arch} eq "x86_64") {
$mmx_x86_64_x86inc = 'mmx';
$sse_x86_64_x86inc = 'sse';
$sse2_x86_64_x86inc = 'sse2';
$ssse3_x86_64_x86inc = 'ssse3';
$avx_x86_64_x86inc = 'avx';
$avx2_x86_64_x86inc = 'avx2';
}
}
# functions that are 64 bit only.
$mmx_x86_64 = $sse2_x86_64 = $ssse3_x86_64 = $avx_x86_64 = $avx2_x86_64 = '';
if ($opts{arch} eq "x86_64") {
$mmx_x86_64 = 'mmx';
$sse2_x86_64 = 'sse2';
$ssse3_x86_64 = 'ssse3';
$avx_x86_64 = 'avx';
$avx2_x86_64 = 'avx2';
}
#
# post proc
#
if (vpx_config("CONFIG_VP9_POSTPROC") eq "yes") {
add_proto qw/void vp10_mbpost_proc_down/, "uint8_t *dst, int pitch, int rows, int cols, int flimit";
specialize qw/vp10_mbpost_proc_down sse2/;
$vp10_mbpost_proc_down_sse2=vp10_mbpost_proc_down_xmm;
add_proto qw/void vp10_mbpost_proc_across_ip/, "uint8_t *src, int pitch, int rows, int cols, int flimit";
specialize qw/vp10_mbpost_proc_across_ip sse2/;
$vp10_mbpost_proc_across_ip_sse2=vp10_mbpost_proc_across_ip_xmm;
add_proto qw/void vp10_post_proc_down_and_across/, "const uint8_t *src_ptr, uint8_t *dst_ptr, int src_pixels_per_line, int dst_pixels_per_line, int rows, int cols, int flimit";
specialize qw/vp10_post_proc_down_and_across sse2/;
$vp10_post_proc_down_and_across_sse2=vp10_post_proc_down_and_across_xmm;
add_proto qw/void vp10_plane_add_noise/, "uint8_t *Start, char *noise, char blackclamp[16], char whiteclamp[16], char bothclamp[16], unsigned int Width, unsigned int Height, int Pitch";
specialize qw/vp10_plane_add_noise sse2/;
$vp10_plane_add_noise_sse2=vp10_plane_add_noise_wmt;
add_proto qw/void vp10_filter_by_weight16x16/, "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int src_weight";
specialize qw/vp10_filter_by_weight16x16 sse2 msa/;
add_proto qw/void vp10_filter_by_weight8x8/, "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int src_weight";
specialize qw/vp10_filter_by_weight8x8 sse2 msa/;
}
#
# dct
#
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
# Note as optimized versions of these functions are added we need to add a check to ensure
# that when CONFIG_EMULATE_HARDWARE is on, it defaults to the C versions only.
add_proto qw/void vp10_iht4x4_16_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type";
specialize qw/vp10_iht4x4_16_add/;
add_proto qw/void vp10_iht8x8_64_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type";
specialize qw/vp10_iht8x8_64_add/;
add_proto qw/void vp10_iht16x16_256_add/, "const tran_low_t *input, uint8_t *output, int pitch, int tx_type";
specialize qw/vp10_iht16x16_256_add/;
} else {
# Force C versions if CONFIG_EMULATE_HARDWARE is 1
if (vpx_config("CONFIG_EMULATE_HARDWARE") eq "yes") {
add_proto qw/void vp10_iht4x4_16_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type";
specialize qw/vp10_iht4x4_16_add/;
add_proto qw/void vp10_iht8x8_64_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type";
specialize qw/vp10_iht8x8_64_add/;
add_proto qw/void vp10_iht16x16_256_add/, "const tran_low_t *input, uint8_t *output, int pitch, int tx_type";
specialize qw/vp10_iht16x16_256_add/;
} else {
add_proto qw/void vp10_iht4x4_16_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type";
specialize qw/vp10_iht4x4_16_add sse2 neon dspr2 msa/;
add_proto qw/void vp10_iht8x8_64_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type";
specialize qw/vp10_iht8x8_64_add sse2 neon dspr2 msa/;
add_proto qw/void vp10_iht16x16_256_add/, "const tran_low_t *input, uint8_t *output, int pitch, int tx_type";
specialize qw/vp10_iht16x16_256_add sse2 dspr2 msa/;
}
}
# High bitdepth functions
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
#
# Sub Pixel Filters
#
add_proto qw/void vp10_highbd_convolve_copy/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve_copy/;
add_proto qw/void vp10_highbd_convolve_avg/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve_avg/;
add_proto qw/void vp10_highbd_convolve8/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve8/, "$sse2_x86_64";
add_proto qw/void vp10_highbd_convolve8_horiz/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve8_horiz/, "$sse2_x86_64";
add_proto qw/void vp10_highbd_convolve8_vert/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve8_vert/, "$sse2_x86_64";
add_proto qw/void vp10_highbd_convolve8_avg/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve8_avg/, "$sse2_x86_64";
add_proto qw/void vp10_highbd_convolve8_avg_horiz/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve8_avg_horiz/, "$sse2_x86_64";
add_proto qw/void vp10_highbd_convolve8_avg_vert/, "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, int bps";
specialize qw/vp10_highbd_convolve8_avg_vert/, "$sse2_x86_64";
#
# post proc
#
if (vpx_config("CONFIG_VP9_POSTPROC") eq "yes") {
add_proto qw/void vp10_highbd_mbpost_proc_down/, "uint16_t *dst, int pitch, int rows, int cols, int flimit";
specialize qw/vp10_highbd_mbpost_proc_down/;
add_proto qw/void vp10_highbd_mbpost_proc_across_ip/, "uint16_t *src, int pitch, int rows, int cols, int flimit";
specialize qw/vp10_highbd_mbpost_proc_across_ip/;
add_proto qw/void vp10_highbd_post_proc_down_and_across/, "const uint16_t *src_ptr, uint16_t *dst_ptr, int src_pixels_per_line, int dst_pixels_per_line, int rows, int cols, int flimit";
specialize qw/vp10_highbd_post_proc_down_and_across/;
add_proto qw/void vp10_highbd_plane_add_noise/, "uint8_t *Start, char *noise, char blackclamp[16], char whiteclamp[16], char bothclamp[16], unsigned int Width, unsigned int Height, int Pitch";
specialize qw/vp10_highbd_plane_add_noise/;
}
#
# dct
#
# Note as optimized versions of these functions are added we need to add a check to ensure
# that when CONFIG_EMULATE_HARDWARE is on, it defaults to the C versions only.
add_proto qw/void vp10_highbd_iht4x4_16_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type, int bd";
specialize qw/vp10_highbd_iht4x4_16_add/;
add_proto qw/void vp10_highbd_iht8x8_64_add/, "const tran_low_t *input, uint8_t *dest, int dest_stride, int tx_type, int bd";
specialize qw/vp10_highbd_iht8x8_64_add/;
add_proto qw/void vp10_highbd_iht16x16_256_add/, "const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd";
specialize qw/vp10_highbd_iht16x16_256_add/;
}
#
# Encoder functions below this point.
#
if (vpx_config("CONFIG_VP10_ENCODER") eq "yes") {
add_proto qw/unsigned int vp10_avg_8x8/, "const uint8_t *, int p";
specialize qw/vp10_avg_8x8 sse2 neon msa/;
add_proto qw/unsigned int vp10_avg_4x4/, "const uint8_t *, int p";
specialize qw/vp10_avg_4x4 sse2 msa/;
add_proto qw/void vp10_minmax_8x8/, "const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max";
specialize qw/vp10_minmax_8x8 sse2/;
add_proto qw/void vp10_hadamard_8x8/, "int16_t const *src_diff, int src_stride, int16_t *coeff";
specialize qw/vp10_hadamard_8x8 sse2/, "$ssse3_x86_64_x86inc";
add_proto qw/void vp10_hadamard_16x16/, "int16_t const *src_diff, int src_stride, int16_t *coeff";
specialize qw/vp10_hadamard_16x16 sse2/;
add_proto qw/int16_t vp10_satd/, "const int16_t *coeff, int length";
specialize qw/vp10_satd sse2/;
add_proto qw/void vp10_int_pro_row/, "int16_t *hbuf, uint8_t const *ref, const int ref_stride, const int height";
specialize qw/vp10_int_pro_row sse2 neon/;
add_proto qw/int16_t vp10_int_pro_col/, "uint8_t const *ref, const int width";
specialize qw/vp10_int_pro_col sse2 neon/;
add_proto qw/int vp10_vector_var/, "int16_t const *ref, int16_t const *src, const int bwl";
specialize qw/vp10_vector_var neon sse2/;
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
add_proto qw/unsigned int vp10_highbd_avg_8x8/, "const uint8_t *, int p";
specialize qw/vp10_highbd_avg_8x8/;
add_proto qw/unsigned int vp10_highbd_avg_4x4/, "const uint8_t *, int p";
specialize qw/vp10_highbd_avg_4x4/;
add_proto qw/void vp10_highbd_minmax_8x8/, "const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max";
specialize qw/vp10_highbd_minmax_8x8/;
}
# ENCODEMB INVOKE
#
# Denoiser
#
if (vpx_config("CONFIG_VP9_TEMPORAL_DENOISING") eq "yes") {
add_proto qw/int vp10_denoiser_filter/, "const uint8_t *sig, int sig_stride, const uint8_t *mc_avg, int mc_avg_stride, uint8_t *avg, int avg_stride, int increase_denoising, BLOCK_SIZE bs, int motion_magnitude";
specialize qw/vp10_denoiser_filter sse2/;
}
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
# the transform coefficients are held in 32-bit
# values, so the assembler code for vp10_block_error can no longer be used.
add_proto qw/int64_t vp10_block_error/, "const tran_low_t *coeff, const tran_low_t *dqcoeff, intptr_t block_size, int64_t *ssz";
specialize qw/vp10_block_error/;
add_proto qw/void vp10_quantize_fp/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_quantize_fp/;
add_proto qw/void vp10_quantize_fp_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_quantize_fp_32x32/;
add_proto qw/void vp10_fdct8x8_quant/, "const int16_t *input, int stride, tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_fdct8x8_quant/;
} else {
add_proto qw/int64_t vp10_block_error/, "const tran_low_t *coeff, const tran_low_t *dqcoeff, intptr_t block_size, int64_t *ssz";
specialize qw/vp10_block_error avx2 msa/, "$sse2_x86inc";
add_proto qw/int64_t vp10_block_error_fp/, "const int16_t *coeff, const int16_t *dqcoeff, int block_size";
specialize qw/vp10_block_error_fp neon/, "$sse2_x86inc";
add_proto qw/void vp10_quantize_fp/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_quantize_fp neon sse2/, "$ssse3_x86_64_x86inc";
add_proto qw/void vp10_quantize_fp_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_quantize_fp_32x32/, "$ssse3_x86_64_x86inc";
add_proto qw/void vp10_fdct8x8_quant/, "const int16_t *input, int stride, tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_fdct8x8_quant sse2 ssse3 neon/;
}
# fdct functions
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
add_proto qw/void vp10_fht4x4/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_fht4x4 sse2/;
add_proto qw/void vp10_fht8x8/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_fht8x8 sse2/;
add_proto qw/void vp10_fht16x16/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_fht16x16 sse2/;
add_proto qw/void vp10_fwht4x4/, "const int16_t *input, tran_low_t *output, int stride";
specialize qw/vp10_fwht4x4/, "$mmx_x86inc";
} else {
add_proto qw/void vp10_fht4x4/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_fht4x4 sse2 msa/;
add_proto qw/void vp10_fht8x8/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_fht8x8 sse2 msa/;
add_proto qw/void vp10_fht16x16/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_fht16x16 sse2 msa/;
add_proto qw/void vp10_fwht4x4/, "const int16_t *input, tran_low_t *output, int stride";
specialize qw/vp10_fwht4x4 msa/, "$mmx_x86inc";
}
#
# Motion search
#
add_proto qw/int vp10_full_search_sad/, "const struct macroblock *x, const struct mv *ref_mv, int sad_per_bit, int distance, const struct vp9_variance_vtable *fn_ptr, const struct mv *center_mv, struct mv *best_mv";
specialize qw/vp10_full_search_sad sse3 sse4_1/;
$vp10_full_search_sad_sse3=vp10_full_search_sadx3;
$vp10_full_search_sad_sse4_1=vp10_full_search_sadx8;
add_proto qw/int vp10_diamond_search_sad/, "const struct macroblock *x, const struct search_site_config *cfg, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, const struct vp9_variance_vtable *fn_ptr, const struct mv *center_mv";
specialize qw/vp10_diamond_search_sad/;
add_proto qw/int vp10_full_range_search/, "const struct macroblock *x, const struct search_site_config *cfg, struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, const struct vp9_variance_vtable *fn_ptr, const struct mv *center_mv";
specialize qw/vp10_full_range_search/;
add_proto qw/void vp10_temporal_filter_apply/, "uint8_t *frame1, unsigned int stride, uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, unsigned int *accumulator, uint16_t *count";
specialize qw/vp10_temporal_filter_apply sse2 msa/;
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
# ENCODEMB INVOKE
add_proto qw/int64_t vp10_highbd_block_error/, "const tran_low_t *coeff, const tran_low_t *dqcoeff, intptr_t block_size, int64_t *ssz, int bd";
specialize qw/vp10_highbd_block_error sse2/;
add_proto qw/void vp10_highbd_quantize_fp/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_highbd_quantize_fp/;
add_proto qw/void vp10_highbd_quantize_fp_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
specialize qw/vp10_highbd_quantize_fp_32x32/;
# fdct functions
add_proto qw/void vp10_highbd_fht4x4/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_highbd_fht4x4/;
add_proto qw/void vp10_highbd_fht8x8/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_highbd_fht8x8/;
add_proto qw/void vp10_highbd_fht16x16/, "const int16_t *input, tran_low_t *output, int stride, int tx_type";
specialize qw/vp10_highbd_fht16x16/;
add_proto qw/void vp10_highbd_fwht4x4/, "const int16_t *input, tran_low_t *output, int stride";
specialize qw/vp10_highbd_fwht4x4/;
add_proto qw/void vp10_highbd_temporal_filter_apply/, "uint8_t *frame1, unsigned int stride, uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, unsigned int *accumulator, uint16_t *count";
specialize qw/vp10_highbd_temporal_filter_apply/;
}
# End vp10_high encoder functions
}
# end encoder functions
1;

Some files were not shown because too many files have changed in this diff Show More