Commit 32a5c528 authored by Johann's avatar Johann

Merge branch 'master' into experimental

Conflicts:
	vp9/common/vp9_findnearmv.c
	vp9/common/vp9_rtcd_defs.sh
	vp9/decoder/vp9_decodframe.c
	vp9/decoder/x86/vp9_dequantize_sse2.c
	vp9/encoder/vp9_rdopt.c
	vp9/vp9_common.mk

Resolve file name changes in favor of master. Resolve rdopt changes in
favor of experimental, preserving the newer experiments.

Change-Id: If51ed8f457470281c7b20a5c1a2f4ce2cf76c20f
parents 80fadb26 e5885258
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
# Running ndk-build will build libvpx and include it in your project. # Running ndk-build will build libvpx and include it in your project.
# #
CONFIG_DIR := $(LOCAL_PATH) CONFIG_DIR := $(LOCAL_PATH)/
LIBVPX_PATH := $(LOCAL_PATH)/libvpx LIBVPX_PATH := $(LOCAL_PATH)/libvpx
ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas
ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL) ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL)
...@@ -56,9 +56,9 @@ ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL) ...@@ -56,9 +56,9 @@ ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL)
# Makefiles created by the libvpx configure process # Makefiles created by the libvpx configure process
# This will need to be fixed to handle x86. # This will need to be fixed to handle x86.
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
include $(CONFIG_DIR)/libs-armv7-android-gcc.mk include $(CONFIG_DIR)libs-armv7-android-gcc.mk
else else
include $(CONFIG_DIR)/libs-armv5te-android-gcc.mk include $(CONFIG_DIR)libs-armv5te-android-gcc.mk
endif endif
# Rule that is normally in Makefile created by libvpx # Rule that is normally in Makefile created by libvpx
...@@ -106,26 +106,25 @@ $$(eval $$(call ev-build-file)) ...@@ -106,26 +106,25 @@ $$(eval $$(call ev-build-file))
$(1) : $$(_OBJ) $(2) $(1) : $$(_OBJ) $(2)
@mkdir -p $$(dir $$@) @mkdir -p $$(dir $$@)
@grep $(OFFSET_PATTERN) $$< | tr -d '\#' | $(CONFIG_DIR)/$(ASM_CONVERSION) > $$@ @grep $(OFFSET_PATTERN) $$< | tr -d '\#' | $(CONFIG_DIR)$(ASM_CONVERSION) > $$@
endef endef
# Use ads2gas script to convert from RVCT format to GAS format. This passes # Use ads2gas script to convert from RVCT format to GAS format. This passes
# puts the processed file under $(ASM_CNV_PATH). Local clean rule # puts the processed file under $(ASM_CNV_PATH). Local clean rule
# to handle removing these # to handle removing these
ASM_CNV_OFFSETS_DEPEND = $(ASM_CNV_PATH)/vp8_asm_com_offsets.asm
ifeq ($(CONFIG_VP8_DECODER), yes)
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/vp8_asm_dec_offsets.asm
endif
ifeq ($(CONFIG_VP8_ENCODER), yes) ifeq ($(CONFIG_VP8_ENCODER), yes)
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/vp8_asm_enc_offsets.asm ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/vp8_asm_enc_offsets.asm
endif endif
ifeq ($(HAVE_NEON), yes)
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/vpx_scale_asm_offsets.asm
endif
.PRECIOUS: %.asm.s .PRECIOUS: %.asm.s
$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm $(ASM_CNV_OFFSETS_DEPEND) $(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm $(ASM_CNV_OFFSETS_DEPEND)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@$(CONFIG_DIR)/$(ASM_CONVERSION) <$< > $@ @$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
# For building vpx_rtcd.h, which has a rule in libs.mk # For building *_rtcd.h, which have rules in libs.mk
TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN))) TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
target := libs target := libs
...@@ -177,7 +176,14 @@ ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes) ...@@ -177,7 +176,14 @@ ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
LOCAL_STATIC_LIBRARIES := cpufeatures LOCAL_STATIC_LIBRARIES := cpufeatures
endif endif
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vpx_rtcd.h # Add a dependency to force generation of the RTCD files.
ifeq ($(CONFIG_VP8), yes)
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vp8_rtcd.h
endif
ifeq ($(CONFIG_VP9), yes)
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vp9_rtcd.h
endif
$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vpx_scale_rtcd.h
.PHONY: clean .PHONY: clean
clean: clean:
...@@ -189,14 +195,10 @@ clean: ...@@ -189,14 +195,10 @@ clean:
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)
$(eval $(call asm_offsets_template,\ ifeq ($(HAVE_NEON), yes)
$(ASM_CNV_PATH)/vp8_asm_com_offsets.asm, \
$(LIBVPX_PATH)/vp8/common/vp8_asm_com_offsets.c))
ifeq ($(CONFIG_VP8_DECODER), yes)
$(eval $(call asm_offsets_template,\ $(eval $(call asm_offsets_template,\
$(ASM_CNV_PATH)/vp8_asm_dec_offsets.asm, \ $(ASM_CNV_PATH)/vpx_scale_asm_offsets.asm, \
$(LIBVPX_PATH)/vp8/decoder/vp8_asm_dec_offsets.c)) $(LIBVPX_PATH)/vpx_scale/vpx_scale_asm_offsets.c))
endif endif
ifeq ($(CONFIG_VP8_ENCODER), yes) ifeq ($(CONFIG_VP8_ENCODER), yes)
......
...@@ -918,7 +918,7 @@ process_common_toolchain() { ...@@ -918,7 +918,7 @@ process_common_toolchain() {
add_ldflags -arch_only ${tgt_isa} add_ldflags -arch_only ${tgt_isa}
if [ -z "${alt_libc}" ]; then if [ -z "${alt_libc}" ]; then
alt_libc=${SDK_PATH}/SDKs/iPhoneOS5.1.sdk alt_libc=${SDK_PATH}/SDKs/iPhoneOS6.0.sdk
fi fi
add_cflags "-isysroot ${alt_libc}" add_cflags "-isysroot ${alt_libc}"
...@@ -1088,10 +1088,12 @@ EOF ...@@ -1088,10 +1088,12 @@ EOF
win32) win32)
add_asflags -f win32 add_asflags -f win32
enabled debug && add_asflags -g cv8 enabled debug && add_asflags -g cv8
EXE_SFX=.exe
;; ;;
win64) win64)
add_asflags -f x64 add_asflags -f x64
enabled debug && add_asflags -g cv8 enabled debug && add_asflags -g cv8
EXE_SFX=.exe
;; ;;
linux*|solaris*|android*) linux*|solaris*|android*)
add_asflags -f elf${bits} add_asflags -f elf${bits}
......
...@@ -51,7 +51,7 @@ $$(BUILD_PFX)$(1).h: $$(SRC_PATH_BARE)/$(2) ...@@ -51,7 +51,7 @@ $$(BUILD_PFX)$(1).h: $$(SRC_PATH_BARE)/$(2)
@echo " [CREATE] $$@" @echo " [CREATE] $$@"
$$(qexec)$$(SRC_PATH_BARE)/build/make/rtcd.sh --arch=$$(TGT_ISA) \ $$(qexec)$$(SRC_PATH_BARE)/build/make/rtcd.sh --arch=$$(TGT_ISA) \
--sym=$(1) \ --sym=$(1) \
--config=$$(target)$$(if $$(FAT_ARCHS),,-$$(TOOLCHAIN)).mk \ --config=$$(CONFIG_DIR)$$(target)$$(if $$(FAT_ARCHS),,-$$(TOOLCHAIN)).mk \
$$(RTCD_OPTIONS) $$^ > $$@ $$(RTCD_OPTIONS) $$^ > $$@
CLEAN-OBJS += $$(BUILD_PFX)$(1).h CLEAN-OBJS += $$(BUILD_PFX)$(1).h
RTCD += $$(BUILD_PFX)$(1).h RTCD += $$(BUILD_PFX)$(1).h
...@@ -436,7 +436,7 @@ test_libvpx.vcproj: $(LIBVPX_TEST_SRCS) ...@@ -436,7 +436,7 @@ test_libvpx.vcproj: $(LIBVPX_TEST_SRCS)
PROJECTS-$(CONFIG_MSVS) += test_libvpx.vcproj PROJECTS-$(CONFIG_MSVS) += test_libvpx.vcproj
test:: testdata test:: testdata
@set -e; for t in $(addprefix Win32/Release/,$(notdir $(LIBVPX_TEST_BINS:.cc=.exe))); do $$t; done @set -e; for t in $(addprefix $(TGT_OS:win64=x64)/Release/,$(notdir $(LIBVPX_TEST_BINS:.cc=.exe))); do $$t; done
endif endif
else else
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#ifndef LIBVPX_TEST_ACM_RANDOM_H_ #ifndef LIBVPX_TEST_ACM_RANDOM_H_
#define LIBVPX_TEST_ACM_RANDOM_H_ #define LIBVPX_TEST_ACM_RANDOM_H_
#include <stdlib.h> #include "third_party/googletest/src/include/gtest/gtest.h"
#include "vpx/vpx_integer.h" #include "vpx/vpx_integer.h"
...@@ -19,20 +19,19 @@ namespace libvpx_test { ...@@ -19,20 +19,19 @@ namespace libvpx_test {
class ACMRandom { class ACMRandom {
public: public:
ACMRandom() { ACMRandom() : random_(DeterministicSeed()) {}
Reset(DeterministicSeed());
}
explicit ACMRandom(int seed) { explicit ACMRandom(int seed) : random_(seed) {}
Reset(seed);
}
void Reset(int seed) { void Reset(int seed) {
srand(seed); random_.Reseed(seed);
} }
uint8_t Rand8(void) { uint8_t Rand8(void) {
return (rand() >> 8) & 0xff; const uint32_t value =
random_.Generate(testing::internal::Random::kMaxRange);
// There's a bit more entropy in the upper bits of this implementation.
return (value >> 24) & 0xff;
} }
uint8_t Rand8Extremes(void) { uint8_t Rand8Extremes(void) {
...@@ -43,7 +42,7 @@ class ACMRandom { ...@@ -43,7 +42,7 @@ class ACMRandom {
} }
int PseudoUniform(int range) { int PseudoUniform(int range) {
return (rand() >> 8) % range; return random_.Generate(range);
} }
int operator()(int n) { int operator()(int n) {
...@@ -53,6 +52,9 @@ class ACMRandom { ...@@ -53,6 +52,9 @@ class ACMRandom {
static int DeterministicSeed(void) { static int DeterministicSeed(void) {
return 0xbaba; return 0xbaba;
} }
private:
testing::internal::Random random_;
}; };
} // namespace libvpx_test } // namespace libvpx_test
......
...@@ -51,11 +51,15 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) { ...@@ -51,11 +51,15 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) {
} }
for (int j = 0; j < 64; ++j) { for (int j = 0; j < 64; ++j) {
const bool bias_acceptable = (abs(count_sign_block[j][0] - const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
count_sign_block[j][1]) < 1000); const int max_diff = 1125;
EXPECT_TRUE(bias_acceptable) EXPECT_LT(diff, max_diff)
<< "Error: 8x8 FDCT has a sign bias > 1%" << "Error: 8x8 FDCT has a sign bias > "
<< " for input range [-255, 255] at index " << j; << 1. * max_diff / count_test_block * 100 << "%"
<< " for input range [-255, 255] at index " << j
<< " count0: " << count_sign_block[j][0]
<< " count1: " << count_sign_block[j][1]
<< " diff: " << diff;
} }
memset(count_sign_block, 0, sizeof(count_sign_block)); memset(count_sign_block, 0, sizeof(count_sign_block));
...@@ -76,11 +80,15 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) { ...@@ -76,11 +80,15 @@ TEST(VP9Fdct8x8Test, SignBiasCheck) {
} }
for (int j = 0; j < 64; ++j) { for (int j = 0; j < 64; ++j) {
const bool bias_acceptable = (abs(count_sign_block[j][0] - const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
count_sign_block[j][1]) < 10000); const int max_diff = 10000;
EXPECT_TRUE(bias_acceptable) EXPECT_LT(diff, max_diff)
<< "Error: 8x8 FDCT has a sign bias > 10%" << "Error: 4x4 FDCT has a sign bias > "
<< " for input range [-15, 15] at index " << j; << 1. * max_diff / count_test_block * 100 << "%"
<< " for input range [-15, 15] at index " << j
<< " count0: " << count_sign_block[j][0]
<< " count1: " << count_sign_block[j][1]
<< " diff: " << diff;
} }
}; };
......
...@@ -439,29 +439,28 @@ static void fillrd(struct postproc_state *state, int q, int a) ...@@ -439,29 +439,28 @@ static void fillrd(struct postproc_state *state, int q, int a)
char char_dist[300]; char char_dist[300];
double sigma; double sigma;
int ai = a, qi = q, i; int i;
vp8_clear_system_state(); vp8_clear_system_state();
sigma = ai + .5 + .6 * (63 - qi) / 63.0; sigma = a + .5 + .6 * (63 - q) / 63.0;
/* set up a lookup table of 256 entries that matches /* set up a lookup table of 256 entries that matches
* a gaussian distribution with sigma determined by q. * a gaussian distribution with sigma determined by q.
*/ */
{ {
double i;
int next, j; int next, j;
next = 0; next = 0;
for (i = -32; i < 32; i++) for (i = -32; i < 32; i++)
{ {
int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i)); const int v = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
if (a) if (v)
{ {
for (j = 0; j < a; j++) for (j = 0; j < v; j++)
{ {
char_dist[next+j] = (char) i; char_dist[next+j] = (char) i;
} }
...@@ -544,12 +543,12 @@ void vp8_plane_add_noise_c(unsigned char *Start, char *noise, ...@@ -544,12 +543,12 @@ void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
* filled with the same color block. * filled with the same color block.
*/ */
void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v, void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
int y1, int u1, int v1, int alpha, int stride) int y_1, int u_1, int v_1, int alpha, int stride)
{ {
int i, j; int i, j;
int y1_const = y1*((1<<16)-alpha); int y1_const = y_1*((1<<16)-alpha);
int u1_const = u1*((1<<16)-alpha); int u1_const = u_1*((1<<16)-alpha);
int v1_const = v1*((1<<16)-alpha); int v1_const = v_1*((1<<16)-alpha);
y += 2*stride + 2; y += 2*stride + 2;
for (i = 0; i < 12; i++) for (i = 0; i < 12; i++)
...@@ -582,12 +581,12 @@ void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v, ...@@ -582,12 +581,12 @@ void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
* unblended to allow for other visualizations to be layered. * unblended to allow for other visualizations to be layered.
*/ */
void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v, void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
int y1, int u1, int v1, int alpha, int stride) int y_1, int u_1, int v_1, int alpha, int stride)
{ {
int i, j; int i, j;
int y1_const = y1*((1<<16)-alpha); int y1_const = y_1*((1<<16)-alpha);
int u1_const = u1*((1<<16)-alpha); int u1_const = u_1*((1<<16)-alpha);
int v1_const = v1*((1<<16)-alpha); int v1_const = v_1*((1<<16)-alpha);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
...@@ -646,12 +645,12 @@ void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v, ...@@ -646,12 +645,12 @@ void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
} }
void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v, void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
int y1, int u1, int v1, int alpha, int stride) int y_1, int u_1, int v_1, int alpha, int stride)
{ {
int i, j; int i, j;
int y1_const = y1*((1<<16)-alpha); int y1_const = y_1*((1<<16)-alpha);
int u1_const = u1*((1<<16)-alpha); int u1_const = u_1*((1<<16)-alpha);
int v1_const = v1*((1<<16)-alpha); int v1_const = v_1*((1<<16)-alpha);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
...@@ -676,46 +675,46 @@ void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v, ...@@ -676,46 +675,46 @@ void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
} }
} }
static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height) static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
{ {
int dx; int dx;
int dy; int dy;
if (*x1 > width) if (*x_1 > width)
{ {
dx = *x1 - x0; dx = *x_1 - x_0;
dy = *y1 - y0; dy = *y_1 - y_0;
*x1 = width; *x_1 = width;
if (dx) if (dx)
*y1 = ((width-x0)*dy)/dx + y0; *y_1 = ((width-x_0)*dy)/dx + y_0;
} }
if (*x1 < 0) if (*x_1 < 0)
{ {
dx = *x1 - x0; dx = *x_1 - x_0;
dy = *y1 - y0; dy = *y_1 - y_0;
*x1 = 0; *x_1 = 0;
if (dx) if (dx)
*y1 = ((0-x0)*dy)/dx + y0; *y_1 = ((0-x_0)*dy)/dx + y_0;
} }
if (*y1 > height) if (*y_1 > height)
{ {
dx = *x1 - x0; dx = *x_1 - x_0;
dy = *y1 - y0; dy = *y_1 - y_0;
*y1 = height; *y_1 = height;
if (dy) if (dy)
*x1 = ((height-y0)*dx)/dy + x0; *x_1 = ((height-y_0)*dx)/dy + x_0;
} }
if (*y1 < 0) if (*y_1 < 0)
{ {
dx = *x1 - x0; dx = *x_1 - x_0;
dy = *y1 - y0; dy = *y_1 - y_0;
*y1 = 0; *y_1 = 0;
if (dy) if (dy)
*x1 = ((0-y0)*dx)/dy + x0; *x_1 = ((0-y_0)*dx)/dy + x_0;
} }
} }
......
...@@ -1365,11 +1365,11 @@ int vp8_decode_frame(VP8D_COMP *pbi) ...@@ -1365,11 +1365,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_MULTITHREAD #if CONFIG_MULTITHREAD
if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION) if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
{ {
unsigned int i; unsigned int thread;
vp8mt_decode_mb_rows(pbi, xd); vp8mt_decode_mb_rows(pbi, xd);
vp8_yv12_extend_frame_borders(yv12_fb_new); vp8_yv12_extend_frame_borders(yv12_fb_new);
for (i = 0; i < pbi->decoding_thread_count; ++i) for (thread = 0; thread < pbi->decoding_thread_count; ++thread)
corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted; corrupt_tokens |= pbi->mb_row_di[thread].mbd.corrupted;
} }
else else
#endif #endif
......
...@@ -343,7 +343,6 @@ static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row) ...@@ -343,7 +343,6 @@ static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row)
for (mb_row = start_mb_row; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1)) for (mb_row = start_mb_row; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
{ {
int i;
int recon_yoffset, recon_uvoffset; int recon_yoffset, recon_uvoffset;
int mb_col; int mb_col;
int filter_level; int filter_level;
......
...@@ -90,17 +90,17 @@ static void update_mode( ...@@ -90,17 +90,17 @@ static void update_mode(
if (new_b + (n << 8) < old_b) if (new_b + (n << 8) < old_b)
{ {
int i = 0; int j = 0;
vp8_write_bit(w, 1); vp8_write_bit(w, 1);
do do
{ {
const vp8_prob p = Pnew[i]; const vp8_prob p = Pnew[j];
vp8_write_literal(w, Pcur[i] = p ? p : 1, 8); vp8_write_literal(w, Pcur[j] = p ? p : 1, 8);
} }
while (++i < n); while (++j < n);
} }
else else
vp8_write_bit(w, 0); vp8_write_bit(w, 0);
...@@ -245,15 +245,15 @@ void vp8_pack_tokens_c(vp8_writer *w, const TOKENEXTRA *p, int xcount) ...@@ -245,15 +245,15 @@ void vp8_pack_tokens_c(vp8_writer *w, const TOKENEXTRA *p, int xcount)
if (L) if (L)
{ {
const unsigned char *pp = b->prob; const unsigned char *proba = b->prob;
int v = e >> 1; const int v2 = e >> 1;
int n = L; /* number of bits in v, assumed nonzero */ int n2 = L; /* number of bits in v2, assumed nonzero */
int i = 0; i = 0;
do do
{ {
const int bb = (v >> --n) & 1; const int bb = (v2 >> --n2) & 1;
split = 1 + (((range - 1) * pp[i>>1]) >> 8); split = 1 + (((range - 1) * proba[i>>1]) >> 8);
i = b->tree[i+bb]; i = b->tree[i+bb]; <